Merge lp:~frankban/juju-quickstart/joyent into lp:juju-quickstart

Proposed by Francesco Banconi
Status: Merged
Merged at revision: 64
Proposed branch: lp:~frankban/juju-quickstart/joyent
Merge into: lp:juju-quickstart
Diff against target: 210 lines (+129/-1)
4 files modified
quickstart/models/envs.py (+60/-1)
quickstart/models/fields.py (+19/-0)
quickstart/tests/models/test_envs.py (+16/-0)
quickstart/tests/models/test_fields.py (+34/-0)
To merge this branch: bzr merge lp:~frankban/juju-quickstart/joyent
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+214022@code.launchpad.net

Description of the change

Add support for the Joyent provider.

Tests: `make check`.

QA:
QA is not straightforward for this branch, due to the
fact this needs to be tested on a not yet released
juju-core. Sorry about that.
1) Check out the 1.18 juju-core branch (lp:juju-core/1.18),
   and compile it.
2) Edit the quickstart/settings.py file included in this branch:
   set `JUJU_CMD` to point to the juju 1.18 path.
3) Sign up for a Joyent account from http://www.joyent.com/.
4) Run `.venv/bin/python juju-quickstart -i` and create a new
   joyent environment: DO NOT bootstrap it from quickstart, just
   create it and exit (^X).
5) Use juju 1.18 to bootstrap the joyent account, e.g.
   `juju bootstrap -e joyent --upload-tools`. This is required
   because quickstart does not support uploading tools.
6) After a minute, and while the environment is bootstrapping,
   open another terminal and re-run quickstart, select the
   joyent account you created and hit "use"
   (or just invoke quickstart with `-e joyent`).
7) Ensure everything proceeds as expected, and wait
   until the quickstart opens the GUI.
Done, destroy the environment, thank you!

https://codereview.appspot.com/83880044/

To post a comment you must log in.
Revision history for this message
Francesco Banconi (frankban) wrote :

Reviewers: mp+214022_code.launchpad.net,

Message:
Please take a look.

Description:
Add support for the Joyent provider.

Tests: `make check`.

QA:
QA is not straightforward for this branch, due to the
fact this needs to be tested on a not yet released
juju-core. Sorry about that.
1) Check out the 1.18 juju-core branch (lp:juju-core/1.18),
    and compile it.
2) Edit the quickstart/settings.py file included in this branch:
    set `JUJU_CMD` to point to the juju 1.18 path.
3) Sign up for a Joyent account from http://www.joyent.com/.
4) Run `.venv/bin/python juju-quickstart -i` and create a new
    joyent environment: DO NOT bootstrap it from quickstart, just
    create it and exit (^X).
5) Use juju 1.18 to bootstrap the joyent account, e.g.
    `juju bootstrap -e joyent --upload-tools`. This is required
    because quickstart does not support uploading tools.
6) After a minute, and while the environment is bootstrapping,
    open another terminal and re-run quickstart, select the
    joyent account you created and hit "use"
    (or just invoke quickstart with `-e joyent`).
7) Ensure everything proceeds as expected, and wait
    until the quickstart opens the GUI.
Done, destroy the environment, thank you!

https://code.launchpad.net/~frankban/juju-quickstart/joyent/+merge/214022

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/83880044/

Affected files (+117, -4 lines):
   A [revision details]
   M quickstart/models/envs.py
   M quickstart/models/fields.py
   M quickstart/tests/models/test_envs.py
   M quickstart/tests/models/test_fields.py

Revision history for this message
Brad Crittenden (bac) wrote :

Code LGTM. On to QA.

https://codereview.appspot.com/83880044/diff/1/quickstart/tests/models/test_fields.py
File quickstart/tests/models/test_fields.py (right):

https://codereview.appspot.com/83880044/diff/1/quickstart/tests/models/test_fields.py#newcode468
quickstart/tests/models/test_fields.py:468:
field.validate(unicode(__file__))
Nice use of __file__. Nicer then creating a temp file and destroying
it.

https://codereview.appspot.com/83880044/

Revision history for this message
Brad Crittenden (bac) wrote :

When doing QA and bootstrapping the joyent environment I get

http://paste.ubuntu.com/7199671/

https://codereview.appspot.com/83880044/diff/1/quickstart/models/envs.py
File quickstart/models/envs.py (right):

https://codereview.appspot.com/83880044/diff/1/quickstart/models/envs.py#newcode621
quickstart/models/envs.py:621: 'manta-user', required=True,
I'm running quickstart for the first time to set up joyent. I don't
know what the manta username and ssh keys are. Are they the same as my
SDC ones? I only have one Joyent username and ssh key.

Kind of confusing.

https://codereview.appspot.com/83880044/diff/1/quickstart/models/envs.py#newcode634
quickstart/models/envs.py:634: 'private-key-path', label='provate key
path', required=False,
typo: provate

https://codereview.appspot.com/83880044/

lp:~frankban/juju-quickstart/joyent updated
67. By Francesco Banconi

Fix typo.

Revision history for this message
Brad Crittenden (bac) wrote :

For the private key file path, the default is listed as ~/.ssh/id_rsa

If you try to enter '~/.ssh/id_rsa_joyent', quickstart does not properly
expand the path and gives an error. Using
'/home/bac/.ssh/id_rsa_joyent' was accepted.

https://codereview.appspot.com/83880044/

Revision history for this message
Brad Crittenden (bac) wrote :

QA-OK after lots of struggles, mainly the issue with
passphrase-protected ssh key, which is not quickstart's problem.

Though if juju doesn't screen for it perhaps we should?

https://codereview.appspot.com/83880044/

Revision history for this message
Francesco Banconi (frankban) wrote :

On 2014/04/03 20:06:11, bac wrote:
> For the private key file path, the default is listed as ~/.ssh/id_rsa

> If you try to enter '~/.ssh/id_rsa_joyent', quickstart does not
properly expand
> the path and gives an error. Using '/home/bac/.ssh/id_rsa_joyent' was
accepted.

Good catch. Fixed the FilePathField validation to use expanduser.

https://codereview.appspot.com/83880044/

Revision history for this message
Francesco Banconi (frankban) wrote :

On 2014/04/03 20:22:37, bac wrote:
> QA-OK after lots of struggles, mainly the issue with
passphrase-protected ssh
> key, which is not quickstart's problem.

> Though if juju doesn't screen for it perhaps we should?

Thanks a lot Brad, and sorry again for the difficult QA.
As you mentioned, this is something that must be handled by juju-core,
so, given this will land later, I'd be inclined to wait for the core
fix.

https://codereview.appspot.com/83880044/

lp:~frankban/juju-quickstart/joyent updated
68. By Francesco Banconi

Changes as per review.

Revision history for this message
Francesco Banconi (frankban) wrote :

Please take a look.

https://codereview.appspot.com/83880044/diff/1/quickstart/models/envs.py
File quickstart/models/envs.py (right):

https://codereview.appspot.com/83880044/diff/1/quickstart/models/envs.py#newcode621
quickstart/models/envs.py:621: 'manta-user', required=True,
On 2014/04/03 17:23:50, bac wrote:
> I'm running quickstart for the first time to set up joyent. I don't
know what
> the manta username and ssh keys are. Are they the same as my SDC
ones? I only
> have one Joyent username and ssh key.

> Kind of confusing.

Good point Brad, updated the fields description.

https://codereview.appspot.com/83880044/diff/1/quickstart/models/envs.py#newcode634
quickstart/models/envs.py:634: 'private-key-path', label='provate key
path', required=False,
On 2014/04/03 17:23:50, bac wrote:
> typo: provate

Done.

https://codereview.appspot.com/83880044/

Revision history for this message
Brad Crittenden (bac) wrote :
lp:~frankban/juju-quickstart/joyent updated
69. By Francesco Banconi

Merged trunk.

Revision history for this message
Francesco Banconi (frankban) wrote :

*** Submitted:

Add support for the Joyent provider.

Tests: `make check`.

QA:
QA is not straightforward for this branch, due to the
fact this needs to be tested on a not yet released
juju-core. Sorry about that.
1) Check out the 1.18 juju-core branch (lp:juju-core/1.18),
    and compile it.
2) Edit the quickstart/settings.py file included in this branch:
    set `JUJU_CMD` to point to the juju 1.18 path.
3) Sign up for a Joyent account from http://www.joyent.com/.
4) Run `.venv/bin/python juju-quickstart -i` and create a new
    joyent environment: DO NOT bootstrap it from quickstart, just
    create it and exit (^X).
5) Use juju 1.18 to bootstrap the joyent account, e.g.
    `juju bootstrap -e joyent --upload-tools`. This is required
    because quickstart does not support uploading tools.
6) After a minute, and while the environment is bootstrapping,
    open another terminal and re-run quickstart, select the
    joyent account you created and hit "use"
    (or just invoke quickstart with `-e joyent`).
7) Ensure everything proceeds as expected, and wait
    until the quickstart opens the GUI.
Done, destroy the environment, thank you!

R=bac
CC=
https://codereview.appspot.com/83880044

https://codereview.appspot.com/83880044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'quickstart/models/envs.py'
2--- quickstart/models/envs.py 2014-04-04 14:03:16 +0000
3+++ quickstart/models/envs.py 2014-04-10 09:23:37 +0000
4@@ -418,6 +418,13 @@
5 azure_locations = (
6 'East US', 'West US', 'West Europe', 'North Europe',
7 'Southeast Asia', 'East Asia')
8+ # The first URL is used as the default one.
9+ joyent_sdc_urls = (
10+ 'https://us-west-1.api.joyentcloud.com',
11+ 'https://us-east-1.api.joyentcloud.com',
12+ 'https://us-sw-1.api.joyentcloud.com',
13+ 'https://us-ams-1.api.joyentcloud.com',
14+ )
15 # Define the env_type_db dictionary: this is done inside this function in
16 # order to avoid instantiating fields at import time.
17 # This is an ordered dict so that views can expose options to create new
18@@ -566,7 +573,7 @@
19 label='management subscription ID',
20 help='this information can be retrieved from '
21 'https://manage.windowsazure.com (Settings)'),
22- fields.StringField(
23+ fields.FilePathField(
24 'management-certificate-path', required=True,
25 label='management certificate path',
26 help='the path to the pem file associated to the certificate '
27@@ -584,6 +591,58 @@
28 is_default_field,
29 ),
30 }
31+ env_type_db['joyent'] = {
32+ 'label': 'Joyent',
33+ 'description': (
34+ 'The joyent provider enables you to run Juju on the Joyent cloud. '
35+ 'This process requires you to have a Joyent account. If you have '
36+ 'not signed up for one yet, it can obtained at '
37+ 'http://www.joyent.com/.'
38+ ),
39+ 'fields': (
40+ provider_field,
41+ name_field,
42+ admin_secret_field,
43+ default_series_field,
44+ fields.StringField(
45+ 'sdc-user', required=True,
46+ label='SDC user name',
47+ help='The Smart Data Center account name. '
48+ 'This is usually your Joyent user name.'),
49+ fields.StringField(
50+ 'sdc-key-id', required=True,
51+ label='SDC key id',
52+ help='the SSH public key fingerprint used to connect to the '
53+ 'Smart Data Center'),
54+ fields.ChoiceField(
55+ 'sdc-url', choices=joyent_sdc_urls, label='SDC URL',
56+ required=False, default=joyent_sdc_urls[0],
57+ help='the region URL to use for SDC'),
58+ fields.StringField(
59+ 'manta-user', required=True,
60+ label='manta user name',
61+ help='The Manta Storage Service account name. '
62+ 'This is usually your Joyent user name.'),
63+ fields.StringField(
64+ 'manta-key-id', required=True,
65+ label='manta key id',
66+ help='The SSH public key fingerprint used to connect to the '
67+ 'Manta Storage Service. This is usually the same SSH '
68+ 'fingerprint provided as SDC key id.'),
69+ fields.StringField(
70+ 'manta-url', label='manta URL', required=False,
71+ default='https://us-east.manta.joyent.com',
72+ help='the region URL to use for manta'),
73+ fields.FilePathField(
74+ 'private-key-path', label='private key path', required=False,
75+ default='~/.ssh/id_rsa',
76+ help='the path to the SSH private key'),
77+ fields.StringField(
78+ 'algorithm', label='SSH algorithm', required=False,
79+ default='rsa-sha256'),
80+ is_default_field,
81+ ),
82+ }
83 env_type_db['local'] = {
84 'label': 'local (LXC)',
85 'description': (
86
87=== modified file 'quickstart/models/fields.py'
88--- quickstart/models/fields.py 2014-01-14 14:42:20 +0000
89+++ quickstart/models/fields.py 2014-04-10 09:23:37 +0000
90@@ -30,6 +30,7 @@
91
92 from __future__ import unicode_literals
93
94+import os
95 import uuid
96
97
98@@ -293,6 +294,24 @@
99 )
100
101
102+class FilePathField(StringField):
103+ """A string field storing a path to an existing file."""
104+
105+ def validate(self, value):
106+ """Check the field is set if required.
107+
108+ If the field is set, also check that the file exists.
109+ """
110+ # The parent field ensures the value is set if required.
111+ super(FilePathField, self).validate(value)
112+ value = self.normalize(value)
113+ # If the value is not set, just return without validating the path.
114+ if value is None:
115+ return
116+ if not os.path.isfile(os.path.expanduser(value)):
117+ raise ValueError('file not found in the specified path')
118+
119+
120 class SuggestionsStringField(StringField):
121 """A string field storing possible value suggestions."""
122
123
124=== modified file 'quickstart/tests/models/test_envs.py'
125--- quickstart/tests/models/test_envs.py 2014-01-28 20:35:42 +0000
126+++ quickstart/tests/models/test_envs.py 2014-04-10 09:23:37 +0000
127@@ -780,6 +780,21 @@
128 self.assert_fields(expected, env_metadata)
129 self.assert_required_fields(expected_required, env_metadata)
130
131+ def test_joyent_environment(self):
132+ # The joyent environment metadata includes the expected fields.
133+ self.assertIn('joyent', self.env_type_db)
134+ env_metadata = self.env_type_db['joyent']
135+ expected = [
136+ 'type', 'name', 'admin-secret', 'default-series',
137+ 'sdc-user', 'sdc-key-id', 'sdc-url',
138+ 'manta-user', 'manta-key-id', 'manta-url',
139+ 'private-key-path', 'algorithm', 'is-default']
140+ expected_required = [
141+ 'type', 'name', 'sdc-user', 'sdc-key-id', 'manta-user',
142+ 'manta-key-id', 'is-default']
143+ self.assert_fields(expected, env_metadata)
144+ self.assert_required_fields(expected_required, env_metadata)
145+
146
147 class TestGetSupportedEnvTypes(unittest.TestCase):
148
149@@ -790,6 +805,7 @@
150 ('ec2', 'Amazon EC2'),
151 ('openstack', 'OpenStack (or HP Public Cloud)'),
152 ('azure', 'Windows Azure'),
153+ ('joyent', 'Joyent'),
154 ('local', 'local (LXC)'),
155 ]
156 obtained_env_types = envs.get_supported_env_types(env_type_db)
157
158=== modified file 'quickstart/tests/models/test_fields.py'
159--- quickstart/tests/models/test_fields.py 2014-01-14 15:46:08 +0000
160+++ quickstart/tests/models/test_fields.py 2014-04-10 09:23:37 +0000
161@@ -19,8 +19,11 @@
162 from __future__ import unicode_literals
163
164 from contextlib import contextmanager
165+import os
166 import unittest
167
168+import mock
169+
170 from quickstart.models import fields
171 from quickstart.tests import helpers
172
173@@ -457,6 +460,37 @@
174 field.validate(None)
175
176
177+class TestFilePathField(TestStringField):
178+
179+ field_class = fields.FilePathField
180+
181+ def test_validation_success(self):
182+ # The validation succeeds if the value is set and the path exists.
183+ field = self.field_class('path')
184+ with self.assert_not_raises(ValueError):
185+ field.validate(unicode(__file__))
186+
187+ def test_validation_expanduser(self):
188+ # The ~ construct is properly expanded.
189+ field = self.field_class('path')
190+ basename, filename = os.path.split(unicode(__file__))
191+ with self.assert_not_raises(ValueError):
192+ with mock.patch('os.environ', {'HOME': basename}):
193+ field.validate('~/{}'.format(filename))
194+
195+ def test_validation_error_file_not_found(self):
196+ # A ValueError is raised if the path does not exist.
197+ field = self.field_class('path')
198+ with self.assert_value_error('file not found in the specified path'):
199+ field.validate('__no-such-file__')
200+
201+ def test_validation_error_directory(self):
202+ # A ValueError is raised if the path is a directory.
203+ field = self.field_class('path')
204+ with self.assert_value_error('file not found in the specified path'):
205+ field.validate('/tmp')
206+
207+
208 class TestSuggestionsStringField(TestStringField):
209
210 field_class = fields.SuggestionsStringField

Subscribers

People subscribed via source and target branches