Merge lp:~frankban/juju-quickstart/support-bundle-urls into lp:juju-quickstart

Proposed by Francesco Banconi
Status: Merged
Merged at revision: 11
Proposed branch: lp:~frankban/juju-quickstart/support-bundle-urls
Merge into: lp:juju-quickstart
Diff against target: 178 lines (+83/-7)
6 files modified
HACKING.rst (+11/-0)
quickstart/app.py (+1/-1)
quickstart/manage.py (+13/-5)
quickstart/tests/test_manage.py (+25/-1)
quickstart/tests/test_utils.py (+22/-0)
quickstart/utils.py (+11/-0)
To merge this branch: bzr merge lp:~frankban/juju-quickstart/support-bundle-urls
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+194889@code.launchpad.net

Description of the change

Support deploying "bundle:" URLs.

Also added packaging information to the
HACKING file, and updated the fallback
charm URL to the latest version which
officially supports bundles.

Tests: `make check`

QA:
`.venv/bin/python juju-quickstart -e ec2 bundle:~hatch/wiki/7/TestBundle`
Remember to destroy your ec2 environment.

https://codereview.appspot.com/23520044/

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

Reviewers: mp+194889_code.launchpad.net,

Message:
Please take a look.

Description:
Support deploying "bundle:" URLs.

Also added packaging information to the
HACKING file, and updated the fallback
charm URL to the latest version which
officially supports bundles.

Tests: `make check`

QA:
`.venv/bin/python juju-quickstart -e ec2
bundle:~hatch/wiki/7/TestBundle`
Remember to destroy your ec2 environment.

https://code.launchpad.net/~frankban/juju-quickstart/support-bundle-urls/+merge/194889

(do not edit description out of merge proposal)

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

Affected files (+84, -6 lines):
   M HACKING.rst
   A [revision details]
   M quickstart/app.py
   M quickstart/manage.py
   M quickstart/tests/test_manage.py
   M quickstart/tests/test_utils.py
   M quickstart/utils.py

Index: HACKING.rst
=== modified file 'HACKING.rst'
--- HACKING.rst 2013-11-06 15:21:19 +0000
+++ HACKING.rst 2013-11-12 15:34:15 +0000
@@ -72,3 +72,14 @@
  installation::

      $ .venv/bin/python juju-quickstart --help
+
+Creating PPA releases
+~~~~~~~~~~~~~~~~~~~~~
+
+The recipe for creating packages is in
+<https://code.launchpad.net/~juju-gui-charmers/+recipe/juju-quickstart-daily>.
+We currently publish releases on the Juju Quickstart Beta PPA: see
+<https://launchpad.net/~juju-gui/+archive/quickstart-beta/+packages>.
+Packages depend on `python-jujuclient` and `python-websocket-client` to be
+available. They are available in saucy, and they are also stored in our
PPA in
+order to support previous Ubuntu releases.

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision:
<email address hidden>
+New revision:
<email address hidden>

Index: quickstart/app.py
=== modified file 'quickstart/app.py'
--- quickstart/app.py 2013-11-06 17:54:09 +0000
+++ quickstart/app.py 2013-11-12 15:55:34 +0000
@@ -31,7 +31,7 @@

  # The default Juju GUI charm URL to use when it is not possible to
retrieve it
  # from the charmworld API, e.g. due to temporary connection/charmworld
errors.
-DEFAULT_CHARM_URL = 'cs:precise/juju-gui-78'
+DEFAULT_CHARM_URL = 'cs:precise/juju-gui-79'

  class ProgramExit(Exception):

Index: quickstart/manage.py
=== modified file 'quickstart/manage.py'
--- quickstart/manage.py 2013-11-06 17:54:09 +0000
+++ quickstart/manage.py 2013-11-12 15:39:31 +0000
@@ -53,14 +53,21 @@
      Exit with an error if the bundle options are not valid.
      """
      bundle = options.bundle
+ if bundle.startswith('bundle:'):
+ # Convert "bundle:" URLs into HTTPS ones. The next if block below
will
+ # then load the bundle contents from the remote location.
+ try:
+ bundle = utils.convert_bundle_url(bundle)
+ except ValueError as err:
+ return parser.error('unable to open the bundle:
{}'.format(err))
      if bundle.startswith('http://') or bundle.startswith('https://'):
- # Load the bundle URL.
+ # Load the bundle from a remote URL.
         ...

Read more...

Revision history for this message
Richard Harding (rharding) wrote :

LGTM QA-ok

https://codereview.appspot.com/23520044/diff/1/quickstart/manage.py
File quickstart/manage.py (right):

https://codereview.appspot.com/23520044/diff/1/quickstart/manage.py#newcode171
quickstart/manage.py:171: '3) a fully qualified bundle URL (starting
with "bundle:") or '
with this change should we promote bundle:, then url, then the local
options?

https://codereview.appspot.com/23520044/

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

On 2013/11/12 16:49:26, rharding wrote:
> LGTM QA-ok

> https://codereview.appspot.com/23520044/diff/1/quickstart/manage.py
> File quickstart/manage.py (right):

https://codereview.appspot.com/23520044/diff/1/quickstart/manage.py#newcode171
> quickstart/manage.py:171: '3) a fully qualified bundle URL (starting
with
> "bundle:") or '
> with this change should we promote bundle:, then url, then the local
options?

ok, thanks for the review.

https://codereview.appspot.com/23520044/

14. By Francesco Banconi

Changes as per review.

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

*** Submitted:

Support deploying "bundle:" URLs.

Also added packaging information to the
HACKING file, and updated the fallback
charm URL to the latest version which
officially supports bundles.

Tests: `make check`

QA:
`.venv/bin/python juju-quickstart -e ec2
bundle:~hatch/wiki/7/TestBundle`
Remember to destroy your ec2 environment.

R=rharding
CC=
https://codereview.appspot.com/23520044

https://codereview.appspot.com/23520044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'HACKING.rst'
2--- HACKING.rst 2013-11-06 15:21:19 +0000
3+++ HACKING.rst 2013-11-12 17:01:48 +0000
4@@ -72,3 +72,14 @@
5 installation::
6
7 $ .venv/bin/python juju-quickstart --help
8+
9+Creating PPA releases
10+~~~~~~~~~~~~~~~~~~~~~
11+
12+The recipe for creating packages is in
13+<https://code.launchpad.net/~juju-gui-charmers/+recipe/juju-quickstart-daily>.
14+We currently publish releases on the Juju Quickstart Beta PPA: see
15+<https://launchpad.net/~juju-gui/+archive/quickstart-beta/+packages>.
16+Packages depend on `python-jujuclient` and `python-websocket-client` to be
17+available. They are available in saucy, and they are also stored in our PPA in
18+order to support previous Ubuntu releases.
19
20=== modified file 'quickstart/app.py'
21--- quickstart/app.py 2013-11-06 17:54:09 +0000
22+++ quickstart/app.py 2013-11-12 17:01:48 +0000
23@@ -31,7 +31,7 @@
24
25 # The default Juju GUI charm URL to use when it is not possible to retrieve it
26 # from the charmworld API, e.g. due to temporary connection/charmworld errors.
27-DEFAULT_CHARM_URL = 'cs:precise/juju-gui-78'
28+DEFAULT_CHARM_URL = 'cs:precise/juju-gui-79'
29
30
31 class ProgramExit(Exception):
32
33=== modified file 'quickstart/manage.py'
34--- quickstart/manage.py 2013-11-06 17:54:09 +0000
35+++ quickstart/manage.py 2013-11-12 17:01:48 +0000
36@@ -53,14 +53,21 @@
37 Exit with an error if the bundle options are not valid.
38 """
39 bundle = options.bundle
40+ if bundle.startswith('bundle:'):
41+ # Convert "bundle:" URLs into HTTPS ones. The next if block below will
42+ # then load the bundle contents from the remote location.
43+ try:
44+ bundle = utils.convert_bundle_url(bundle)
45+ except ValueError as err:
46+ return parser.error('unable to open the bundle: {}'.format(err))
47 if bundle.startswith('http://') or bundle.startswith('https://'):
48- # Load the bundle URL.
49+ # Load the bundle from a remote URL.
50 try:
51 bundle_yaml = utils.urlread(bundle)
52 except IOError as err:
53 return parser.error('unable to open bundle URL: {}'.format(err))
54 else:
55- # Load the bundle file.
56+ # Load the bundle from a file.
57 bundle_file = os.path.abspath(os.path.expanduser(bundle))
58 if os.path.isdir(bundle_file):
59 bundle_file = os.path.join(bundle_file, 'bundles.yaml')
60@@ -159,9 +166,10 @@
61 parser.add_argument(
62 'bundle', default=None, nargs='?',
63 help='The optional bundle to be deployed. The bundle can be '
64- '1) a path to a YAML/JSON file or '
65- '2) a path to a directory containing a bundles.yaml file or '
66- '3) a URL (starting with http:// or https://) to a YAML/JSON')
67+ '1) a fully qualified bundle URL (starting with "bundle:") or '
68+ '2) a URL (starting with "http://" or "https://") to a YAML/JSON '
69+ 'or 3) a path to a YAML/JSON file or '
70+ '4) a path to a directory containing a "bundles.yaml" file')
71 parser.add_argument(
72 '-e', '--environment', default=default_env_name, dest='env_name',
73 help=env_help)
74
75=== modified file 'quickstart/tests/test_manage.py'
76--- quickstart/tests/test_manage.py 2013-11-06 15:12:43 +0000
77+++ quickstart/tests/test_manage.py 2013-11-12 17:01:48 +0000
78@@ -70,7 +70,8 @@
79 self.assertEqual(open(bundle_file).read(), options.bundle_yaml)
80
81 def test_resulting_options_from_url(self):
82- # The options object is correctly set up when a bundle URL is passed.
83+ # The options object is correctly set up when a bundle HTTP(S) URL is
84+ # passed.
85 bundle_file = self.make_bundle_file()
86 url = 'http://example.com/bundle.yaml'
87 options = self.make_options(url, bundle_name='bundle1')
88@@ -82,6 +83,21 @@
89 ['mysql', 'wordpress'], sorted(options.bundle_services))
90 self.assertEqual(open(bundle_file).read(), options.bundle_yaml)
91
92+ def test_resulting_options_from_bundle_url(self):
93+ # The options object is correctly set up when a "bundle:" URL is
94+ # passed.
95+ bundle_file = self.make_bundle_file()
96+ url = 'bundle:~who/my/bundle'
97+ options = self.make_options(url, bundle_name='bundle1')
98+ with self.patch_urlread(contents=self.valid_bundle) as mock_urlread:
99+ manage._validate_bundle(options, self.parser)
100+ mock_urlread.assert_called_once_with(
101+ 'https://manage.jujucharms.com/bundle/~who/my/bundle/json')
102+ self.assertEqual('bundle1', options.bundle_name)
103+ self.assertEqual(
104+ ['mysql', 'wordpress'], sorted(options.bundle_services))
105+ self.assertEqual(open(bundle_file).read(), options.bundle_yaml)
106+
107 def test_resulting_options_from_dir(self):
108 # The options object is correctly set up when a bundle dir is passed.
109 bundle_dir = self.make_bundle_dir()
110@@ -141,6 +157,14 @@
111 self.parser.error.assert_called_once_with(
112 'unable to open bundle URL: bad wolf')
113
114+ def test_bundle_url_error(self):
115+ # A parser error is invoked if an invalid "bundle:" URL is provided.
116+ url = 'bundle:'
117+ options = self.make_options(url)
118+ manage._validate_bundle(options, self.parser)
119+ self.parser.error.assert_called_once_with(
120+ "unable to open the bundle: invalid bundle URL: 'bundle:'")
121+
122 def test_error_parsing_bundle_contents(self):
123 # A parser error is invoked if an error occurs parsing the bundle YAML.
124 bundle_file = self.make_bundle_file()
125
126=== modified file 'quickstart/tests/test_utils.py'
127--- quickstart/tests/test_utils.py 2013-11-06 14:55:30 +0000
128+++ quickstart/tests/test_utils.py 2013-11-12 17:01:48 +0000
129@@ -75,6 +75,28 @@
130 utils.call('echo', 'we are the borg!')
131
132
133+class TestConvertBundleUrl(helpers.ValueErrorTestsMixin, unittest.TestCase):
134+
135+ def test_conversion(self):
136+ # The HTTPS location to the YAML contents are correctly returned.
137+ bundle_url = 'bundle:~myuser/wiki-bundle/42/wiki'
138+ expected = ('https://manage.jujucharms.com'
139+ '/bundle/~myuser/wiki-bundle/42/wiki/json')
140+ self.assertEqual(expected, utils.convert_bundle_url(bundle_url))
141+
142+ def test_right_strip(self):
143+ # The trailing slash in the bundle URL is removed.
144+ bundle_url = 'bundle:~myuser/wiki-bundle/42/wiki/'
145+ expected = ('https://manage.jujucharms.com'
146+ '/bundle/~myuser/wiki-bundle/42/wiki/json')
147+ self.assertEqual(expected, utils.convert_bundle_url(bundle_url))
148+
149+ def test_error(self):
150+ # A ValueError is raised if the given bundle URL is not valid.
151+ with self.assert_value_error("invalid bundle URL: 'bundle:'"):
152+ utils.convert_bundle_url('bundle:')
153+
154+
155 class TestGetCharmUrl(helpers.UrlReadTestsMixin, unittest.TestCase):
156
157 def test_charm_url(self):
158
159=== modified file 'quickstart/utils.py'
160--- quickstart/utils.py 2013-11-06 10:16:42 +0000
161+++ quickstart/utils.py 2013-11-12 17:01:48 +0000
162@@ -58,6 +58,17 @@
163 return retcode, output, error
164
165
166+def convert_bundle_url(bundle_url):
167+ """Return the equivalent YAML HTTPS location for the fiven bundle URL.
168+
169+ Raise a ValueError if the given URL is not a valid bundle URL.
170+ """
171+ bundle_id = bundle_url.split(':', 1)[1].rstrip('/')
172+ if not bundle_id:
173+ raise ValueError('invalid bundle URL: {!r}'.format(bundle_url))
174+ return 'https://manage.jujucharms.com/bundle/{}/json'.format(bundle_id)
175+
176+
177 def get_charm_url():
178 """Return the charm URL of the latest Juju GUI charm revision.
179

Subscribers

People subscribed via source and target branches