Merge lp:~rharding/charms/precise/juju-gui/git-ify into lp:~juju-gui/charms/precise/juju-gui/trunk

Proposed by Richard Harding
Status: Merged
Merged at revision: 149
Proposed branch: lp:~rharding/charms/precise/juju-gui/git-ify
Merge into: lp:~juju-gui/charms/precise/juju-gui/trunk
Diff against target: 704 lines (+151/-265)
13 files modified
Makefile (+1/-1)
README.md (+4/-13)
config.yaml (+17/-18)
hooks/backend.py (+11/-1)
hooks/install (+4/-2)
hooks/utils.py (+80/-40)
server/guiserver/auth.py (+2/-62)
server/guiserver/tests/helpers.py (+0/-38)
server/guiserver/tests/test_auth.py (+0/-35)
tests/20-functional.test (+3/-2)
tests/deploy.py (+5/-2)
tests/test_deploy.py (+0/-4)
tests/test_utils.py (+24/-47)
To merge this branch: bzr merge lp:~rharding/charms/precise/juju-gui/git-ify
Reviewer Review Type Date Requested Status
Marco Ceppi (community) Abstain
Juju GUI Hackers Pending
Review via email: mp+201442@code.launchpad.net

Description of the change

Change juju-gui-source to be git-enabled.

- Allow pulling from various repo urls
- Support checking out a branch name
- Support checkout out a direct sha
- Remove support for the trunk releases.

The list of what you can check out is simplified a bit. You can easily use the
git access, url, or a local file in the releases directory to enable loading
the gui with any combination of code you would like to use.

Drive by removing some left over bits of the PyJuju branch previously.

QA:

  juju boostrap
  make deploy
  # make sure the gui is running off the latest release. You can check the
  # local equivelent of https://jujucharms.com/juju-ui/version.js

Run the follow config changes and after each make sure that the version is
correct for what you've requested. You can get the sha values from looking in
Github.

https://github.com/juju/juju-gui/commits/develop

  # The develop support
  juju set juju-gui juju-gui-source="develop"
  # Supports the HEAD of a branch specified.
  juju set juju-gui juju-gui-source="https://github.com/juju/juju-gui.git network-prototype"
  # Supports an older commit in the main develop line.
  juju set juju-gui juju-gui-source="https://github.com/juju/juju-gui.git @c7ddd186"

https://codereview.appspot.com/52790043/

To post a comment you must log in.
Revision history for this message
Richard Harding (rharding) wrote :

Reviewers: mp+201442_code.launchpad.net,

Message:
Please take a look.

Description:
Change juju-gui-source to be git-enabled.

- Allow pulling from various repo urls
- Support checking out a branch name
- Support checkout out a direct sha
- Remove support for the trunk releases.

The list of what you can check out is simplified a bit. You can easily
use the
git access, url, or a local file in the releases directory to enable
loading
the gui with any combination of code you would like to use.

Drive by removing some left over bits of the PyJuju branch previously.

QA:

   juju boostrap
   make deploy
   # make sure the gui is running off the latest release. You can check
the
   # local equivelent of https://jujucharms.com/juju-ui/version.js

Run the follow config changes and after each make sure that the version
is
correct for what you've requested. You can get the sha values from
looking in
Github.

https://github.com/juju/juju-gui/commits/develop

   # The develop support
   juju set juju-gui juju-gui-source="develop"
   # Supports the HEAD of a branch specified.
   juju set juju-gui
juju-gui-source="https://github.com/juju/juju-gui.git network-prototype"
   # Supports an older commit in the main develop line.
   juju set juju-gui
juju-gui-source="https://github.com/juju/juju-gui.git @c7ddd186"

https://code.launchpad.net/~rharding/charms/precise/juju-gui/git-ify/+merge/201442

(do not edit description out of merge proposal)

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

Affected files (+134, -248 lines):
   M README.md
   A [revision details]
   M config.yaml
   M hooks/backend.py
   M hooks/install
   M hooks/utils.py
   M server/guiserver/auth.py
   M server/guiserver/tests/helpers.py
   M server/guiserver/tests/test_auth.py
   M tests/test_utils.py

Revision history for this message
Richard Harding (rharding) wrote :
Download full text (4.1 KiB)

Added reviewer comments

https://codereview.appspot.com/52790043/diff/60001/README.md
File README.md (left):

https://codereview.appspot.com/52790043/diff/60001/README.md#oldcode127
README.md:127: 3. Retry as described in the step 3 above (`juju resolved
--retry juju-gui/0`).
missed pyjuju cleanup.

https://codereview.appspot.com/52790043/diff/60001/README.md
File README.md (right):

https://codereview.appspot.com/52790043/diff/60001/README.md#newcode92
README.md:92: to build the source used by the charm.
this is just to reduce the duplication of what's supported. It
generalizes it a bit to read nicer.

https://codereview.appspot.com/52790043/diff/60001/config.yaml
File config.yaml (left):

https://codereview.appspot.com/52790043/diff/60001/config.yaml#oldcode24
config.yaml:24: - 'trunk': The latest release from the "trunk" series
will be deployed.
this was proven to not be used and there's so many other ways to load a
specific release now it's deemed redundant.

https://codereview.appspot.com/52790043/diff/60001/config.yaml#oldcode39
config.yaml:39: - a "url:" prefixed url: The release found at the given
URL
file:// is gone for the same reason. You can stick that file at a url,
you can put it in the releases folder, you can just point at the branch
for that file.

https://codereview.appspot.com/52790043/diff/60001/hooks/backend.py
File hooks/backend.py (right):

https://codereview.appspot.com/52790043/diff/60001/hooks/backend.py#newcode94
hooks/backend.py:94: if origin in ('branch', 'develop'):
develop is just a shortcut for the branch so it's moved up here.

https://codereview.appspot.com/52790043/diff/60001/hooks/backend.py#newcode112
hooks/backend.py:112: log('Using source {}: {}'.format(branch_url,
revision))
added some logging helpers to make sure things were doing the right
thing in QA.

https://codereview.appspot.com/52790043/diff/60001/hooks/install
File hooks/install (right):

https://codereview.appspot.com/52790043/diff/60001/hooks/install#newcode32
hooks/install:32: 'libapt-pkg-dev', 'python-apt', 'python-launchpadlib',
'python-tempita',
I hit this dep on trusty to build.

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py
File hooks/utils.py (right):

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py#newcode124
hooks/utils.py:124: git_checkout = command('git', 'clone', '--depth',
'1')
this is the equivelent shallow clone. Note, to do a revision checkout we
'undo' this later on.

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py#newcode276
hooks/utils.py:276: log('Source is defaulting to stable release.')
since this is a 'all else fails' log it to note it got hit.

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py#newcode568
hooks/utils.py:568: cmd_log(git_checkout(*checkout_args))
to do anything else we have to have a checkout. So we always checkout
the develop branch and then move on from there if a different branch or
commit was specified.

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py#newcode572
hooks/utils.py:572: git_dir = juju_gui_source_dir + "/.git"
our cwd isn't the source dir so we have to prefix the git commands with
--git-dir and --wor...

Read more...

Revision history for this message
Marco Ceppi (marcoceppi) wrote :

Deferring to ~juju-gui

review: Abstain
155. By Richard Harding

Update functional tests to test a git branch

156. By Richard Harding

Update deploy to ignore .git as well

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

LGTM mit changes.
QA-A-OK

https://codereview.appspot.com/52790043/diff/60001/config.yaml
File config.yaml (right):

https://codereview.appspot.com/52790043/diff/60001/config.yaml#newcode3
config.yaml:3: # Copyright (C) 2012-2013 Canonical Ltd.
update for all files you touch.</pita>

https://codereview.appspot.com/52790043/diff/60001/hooks/install
File hooks/install (right):

https://codereview.appspot.com/52790043/diff/60001/hooks/install#newcode32
hooks/install:32: 'libapt-pkg-dev', 'python-apt', 'python-launchpadlib',
'python-tempita',
thanks for being out front. i should upgrade to trusty soon.

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py
File hooks/utils.py (right):

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py#newcode123
hooks/utils.py:123: # Bazaar checkout command.
s/Bazaar c/C/

https://codereview.appspot.com/52790043/diff/60001/hooks/utils.py#newcode124
hooks/utils.py:124: git_checkout = command('git', 'clone', '--depth',
'1')
I'd promote this review comment to a code comment. Would be useful.

https://codereview.appspot.com/52790043/diff/60001/tests/test_utils.py
File tests/test_utils.py (right):

https://codereview.appspot.com/52790043/diff/60001/tests/test_utils.py#newcode660
tests/test_utils.py:660: def test_stable_release(self, mock_log):
If you aren't going to use the mock, and there may be more, I find using
*args to be appropriate.

https://codereview.appspot.com/52790043/diff/60001/tests/test_utils.py#newcode672
tests/test_utils.py:672: # A Bazaar branch is correctly parsed when
including revision.
s/Bazaar/git/

You may want to grep the whole tree for Bazaar and bzr.

https://codereview.appspot.com/52790043/

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

Thanks for the review. Updated and re-running one final full functional
test run before landing.

https://codereview.appspot.com/52790043/

157. By Richard Harding

update per review

158. By Richard Harding

Remove the master bit

159. By Richard Harding

Update test runs to take a bit to check out master

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2014-01-15 14:49:19 +0000
3+++ Makefile 2014-01-16 20:33:25 +0000
4@@ -14,7 +14,7 @@
5 # You should have received a copy of the GNU Affero General Public License
6 # along with this program. If not, see <http://www.gnu.org/licenses/>.
7
8-JUJUTEST = yes | juju-test --timeout=40m -v -e "$(JUJU_ENV)"
9+JUJUTEST = yes | juju-test --timeout=60m -v -e "$(JUJU_ENV)"
10 VENV = tests/.venv
11 SYSDEPS = build-essential bzr libapt-pkg-dev libpython-dev python-virtualenv \
12 rsync xvfb
13
14=== modified file 'README.md'
15--- README.md 2014-01-14 23:57:37 +0000
16+++ README.md 2014-01-16 20:33:25 +0000
17@@ -85,16 +85,11 @@
18 juju deploy juju-gui
19
20 There are situations and customizations in which the charm needs to connect to
21-Launchpad:
22+the Internet:
23
24-- juju-gui-source is set to "stable" or "trunk": in this cases the charm pulls
25- the latest stable or development release from Launchpad;
26-- juju-gui-source is set to a branch (e.g. "lp:juju-gui"): in this case the
27- charm retrieves a checkout of the specified branch from Launchpad, and adds
28- an external Launchpad PPA to install build dependencies;
29-- juju-gui-source is set to a specific version number not available in the
30- local store (i.e. in the releases directory of the deployed charm): in this
31- case the release is downloaded from Launchpad;
32+- juju-gui-source is set to a configuration that requires accessing an
33+ external source in order to fetch a release tarball or a Git checkout in order
34+ to build the source used by the charm.
35 - builtin-server is set to false: in this case the charm adds an external
36 Launchpad PPA to install the legacy server dependencies.
37
38@@ -122,10 +117,6 @@
39
40 `juju resolved --retry juju-gui/0`
41
42-These steps are sufficient for Juju Core.
43-
44-3. Retry as described in the step 3 above (`juju resolved --retry juju-gui/0`).
45-
46 ### Upgrading the charm behind a firewall ###
47
48 When a new version of Juju GUI is released, the charm is updated to include the
49
50=== modified file 'config.yaml'
51--- config.yaml 2014-01-13 19:26:48 +0000
52+++ config.yaml 2014-01-16 20:33:25 +0000
53@@ -1,6 +1,6 @@
54 # This file is part of the Juju GUI, which lets users view and manage Juju
55 # environments within a graphical interface (https://launchpad.net/juju-gui).
56-# Copyright (C) 2012-2013 Canonical Ltd.
57+# Copyright (C) 2012-2014 Canonical Ltd.
58 #
59 # This program is free software: you can redistribute it and/or modify it under
60 # the terms of the GNU Affero General Public License version 3, as published by
61@@ -21,23 +21,22 @@
62 - 'local' (default): The latest local release will be deployed. Releases
63 are stored in the releases directory of this charm.
64 - 'stable': The latest release from the "stable" series will be deployed.
65- - 'trunk': The latest release from the "trunk" series will be deployed.
66- Please note that this is not a build of the current Juju GUI trunk.
67- For that functionality, use "lp:juju-gui", as described below.
68- - a stable version (e.g '0.1.0'): The specified stable version will be
69- deployed. A suitable release is looked up in the local releases
70- repository (see the "local" choice above). If not found locally, the
71- release will be downloaded from Launchpad.
72- - a trunk version (e.g '0.1.0+build.1'): The specified trunk version
73- will be deployed. A suitable release is looked up in the local releases
74- repository (see the "local" choice above). If not found locally, the
75- release will be downloaded from Launchpad.
76- - a Bazaar branch (e.g. 'lp:juju-gui'): A release will be created and
77- deployed from the specified Bazaar branch. "http://"" prefixed branches
78- work as well. It is also possible to include the specific branch
79- revision, e.g. "lp:juju-gui:42" will checkout revno 42.
80- - a "url:" prefixed url: The release found at the given URL
81- (ex: url:http://... or url:file://...) will be deployed.
82+ - 'develop': The latest, in development, version from the Git repository.
83+ - a specific release version (e.g '0.1.0' or '0.1.0+build.1'): The
84+ specified stable version will be deployed. A suitable release is
85+ looked up in the local releases repository (see the "local" choice
86+ above). If not found locally, the release will be downloaded from
87+ Launchpad.
88+ - a Git branch (e.g. 'https://github.com/juju/juju-gui.git' or
89+ 'https://github.com/mitechie/juju-gui.git updated-test-runner'): A
90+ release will be created and deployed from the specified Git
91+ repository. You can include a branch name or a specific commit SHA
92+ after the url to the Git repository to deploy that specific commit
93+ point. You may instead specify a commit SHA: (e.g.
94+ 'https://github.com/mitechie/juju-gui.git @de5e61bf9fa') which will
95+ clone the git repository and then check out the specified commit
96+ before building the release.
97+ - a URL: The release found at the given URL (ex: http://...) will be deployed.
98 type: string
99 default: local
100 juju-gui-debug:
101
102=== modified file 'hooks/backend.py'
103--- hooks/backend.py 2014-01-13 19:26:48 +0000
104+++ hooks/backend.py 2014-01-16 20:33:25 +0000
105@@ -91,7 +91,14 @@
106 # Get a tarball somehow.
107 origin, version_or_branch = utils.parse_source(
108 backend.config['juju-gui-source'])
109- if origin == 'branch':
110+ if origin in ('branch', 'develop'):
111+ # Develop is the latest passing build from Git.
112+ if origin == 'develop':
113+ version_or_branch = (
114+ 'https://github.com/juju/juju-gui.git',
115+ None
116+ )
117+
118 logpath = backend.config['command-log-file']
119 # Make sure we have the required build dependencies.
120 # Note that we also need to add the juju-gui repository
121@@ -100,7 +107,10 @@
122 utils.install_missing_packages(
123 utils.DEB_BUILD_DEPENDENCIES,
124 repository=backend.config['repository-location'])
125+
126 branch_url, revision = version_or_branch
127+ log('Using source {}: {}'.format(branch_url, revision))
128+
129 release_tarball_path = utils.fetch_gui_from_branch(
130 branch_url, revision, logpath)
131 else:
132
133=== modified file 'hooks/install'
134--- hooks/install 2013-11-13 18:37:07 +0000
135+++ hooks/install 2014-01-16 20:33:25 +0000
136@@ -3,7 +3,7 @@
137
138 # This file is part of the Juju GUI, which lets users view and manage Juju
139 # environments within a graphical interface (https://launchpad.net/juju-gui).
140-# Copyright (C) 2012-2013 Canonical Ltd.
141+# Copyright (C) 2012-2014 Canonical Ltd.
142 #
143 # This program is free software: you can redistribute it and/or modify it under
144 # the terms of the GNU Affero General Public License version 3, as published by
145@@ -29,7 +29,9 @@
146 # Python dependencies must be installed here so that the charm can import and
147 # use required libraries.
148 PYTHON_DEPENDENCIES = (
149- 'python-apt', 'python-launchpadlib', 'python-tempita', 'python-yaml')
150+ 'libapt-pkg-dev', 'python-apt', 'python-launchpadlib', 'python-tempita',
151+ 'python-yaml'
152+)
153
154 run('juju-log', '--', 'Installing base Python dependencies: {}.'.format(
155 ', '.join(PYTHON_DEPENDENCIES)))
156
157=== modified file 'hooks/utils.py'
158--- hooks/utils.py 2014-01-15 12:03:24 +0000
159+++ hooks/utils.py 2014-01-16 20:33:25 +0000
160@@ -1,6 +1,6 @@
161 # This file is part of the Juju GUI, which lets users view and manage Juju
162 # environments within a graphical interface (https://launchpad.net/juju-gui).
163-# Copyright (C) 2012-2013 Canonical Ltd.
164+# Copyright (C) 2012-2014 Canonical Ltd.
165 #
166 # This program is free software: you can redistribute it and/or modify it under
167 # the terms of the GNU Affero General Public License version 3, as published by
168@@ -81,7 +81,6 @@
169 from shelltoolbox import (
170 apt_get_install,
171 command,
172- environ,
173 install_extra_repositories,
174 run,
175 script_name,
176@@ -115,21 +114,17 @@
177
178 JUJU_PEM = 'juju.includes-private-key.pem'
179 DEB_BUILD_DEPENDENCIES = (
180- 'bzr', 'g++', 'imagemagick', 'make', 'nodejs', 'npm',
181+ 'bzr', 'g++', 'git', 'imagemagick', 'make', 'nodejs', 'npm',
182 )
183
184
185 # Store the configuration from on invocation to the next.
186 config_json = Serializer(os.path.join(os.path.sep, 'tmp', 'config.json'))
187-# Bazaar checkout command.
188-bzr_checkout = command('bzr', 'co', '--lightweight')
189+# Git checkout command.
190+# This is the equivalent shallow clone. Note, to do a revision checkout we
191+# 'undo' this later on.
192+git_checkout = command('git', 'clone', '--depth', '1')
193
194-bzr_url_expression = re.compile(r"""
195- ^ # Beginning of line.
196- ((?:lp:|http:\/\/)[^:]+) # Branch URL (scheme + domain/path).
197- (?::(\d+))? # Optional branch revision.
198- $ # End of line.
199-""", re.VERBOSE)
200 release_expression = re.compile(r"""
201 juju-gui- # Juju GUI prefix.
202 (
203@@ -240,29 +235,47 @@
204 Examples:
205 - ('local', None): latest local release;
206 - ('stable', None): latest stable release;
207- - ('stable', '0.1.0'): stable release v0.1.0;
208- - ('trunk', None): latest trunk release;
209- - ('trunk', '0.1.0+build.1'): trunk release v0.1.0 bzr revision 1;
210- - ('branch', ('lp:juju-gui', 42): release is made from a branch -
211- in this case the second element includes the branch URL and revision;
212- - ('branch', ('lp:juju-gui', None): no revision is specified;
213- - ('url', 'http://example.com/gui'): release from a downloaded file.
214+ - ('develop', None): latest build from git trunk;
215+ - ('release', '0.1.0'): release v0.1.0;
216+ - ('branch', ('https://github.com/juju/juju-gui.git', 'add-feature'):
217+ release is made from a branch -
218+ in this case the second element includes the branch or SHA;
219+ - ('branch', ('https://github.com/juju/juju-gui.git', None): no
220+ revision is specified;
221+ - ('url', 'http://example.com/gui.tar.gz'): release from a downloaded
222+ file.
223 """
224- if source.startswith('url:'):
225- source = source[4:]
226- # Support file paths, including relative paths.
227- if urlparse.urlparse(source).scheme == '':
228- if not source.startswith('/'):
229- source = os.path.join(os.path.abspath(CURRENT_DIR), source)
230- source = "file://%s" % source
231+
232+ def is_url(url_check):
233+ if ' ' in url_check:
234+ url_check, _ = url_check.split(' ')
235+
236+ if url_check.startswith('http') and not url_check.endswith('.git'):
237+ return True
238+ else:
239+ return False
240+
241+ def is_branch(check_branch):
242+ target = None
243+ if ' ' in check_branch:
244+ check_branch, target = check_branch.split(' ')
245+
246+ if check_branch.startswith('http') and check_branch.endswith('.git'):
247+ return (check_branch, target)
248+ else:
249+ return False
250+
251+ if is_url(source):
252 return 'url', source
253- if source in ('local', 'stable', 'trunk'):
254+
255+ if source in ('local', 'stable', 'develop'):
256 return source, None
257- match = bzr_url_expression.match(source)
258- if match is not None:
259- return 'branch', match.groups()
260- if 'build' in source:
261- return 'trunk', source
262+
263+ check_branch = is_branch(source)
264+ if (check_branch):
265+ return ('branch', check_branch)
266+
267+ log('Source is defaulting to stable release.')
268 return 'stable', source
269
270
271@@ -545,22 +558,49 @@
272 """Retrieve the Juju GUI from a branch and build a release archive."""
273 # Inject NPM packages into the cache for faster building.
274 prime_npm_cache(get_npm_cache_archive_url())
275+
276 # Create a release starting from a branch.
277 juju_gui_source_dir = os.path.join(CURRENT_DIR, 'juju-gui-source')
278- checkout_args, revno = ([], 'latest revno') if revision is None else (
279- ['--revision', revision], 'revno {}'.format(revision))
280+
281 log('Retrieving Juju GUI source checkout from {} ({}).'.format(
282- branch_url, revno))
283+ branch_url, revision))
284+
285 cmd_log(run('rm', '-rf', juju_gui_source_dir))
286- checkout_args.extend([branch_url, juju_gui_source_dir])
287- cmd_log(bzr_checkout(*checkout_args))
288+ checkout_args = [branch_url, juju_gui_source_dir]
289+ cmd_log(git_checkout(*checkout_args))
290+
291+ # If there's a revision attempt to checkout that revision.
292+ if revision:
293+ git_dir = juju_gui_source_dir + "/.git"
294+ if revision.startswith('@'):
295+ revision = revision[1:]
296+ # We have to unshallow the checkout in order to be able to 'see'
297+ # older commit hashes to check them out.
298+ cmd_log(run(
299+ 'git', '--git-dir', git_dir, '--work-tree',
300+ juju_gui_source_dir, 'fetch', '--depth', '20000'))
301+
302+ cmd_log(run(
303+ 'git', '--git-dir', git_dir, '--work-tree',
304+ juju_gui_source_dir, 'checkout', revision))
305+ else:
306+ cmd_log(run(
307+ 'git', '--git-dir', git_dir, '--work-tree',
308+ juju_gui_source_dir, 'fetch', 'origin'))
309+ cmd_log(run(
310+ 'git', '--git-dir', git_dir, '--work-tree',
311+ juju_gui_source_dir, 'checkout', '-b', revision,
312+ 'origin/' + revision))
313+
314 log('Preparing a Juju GUI release.')
315 logdir = os.path.dirname(logpath)
316+
317 fd, name = tempfile.mkstemp(prefix='make-distfile-', dir=logdir)
318 log('Output from "make distfile" sent to %s' % name)
319- with environ(NO_BZR='1'):
320- run('make', '-C', juju_gui_source_dir, 'distfile',
321- stdout=fd, stderr=fd)
322+
323+ run('make', '-C', juju_gui_source_dir, 'distfile', 'BRANCH_IS_GOOD=true',
324+ stdout=fd, stderr=fd)
325+
326 return first_path_in_dir(
327 os.path.join(juju_gui_source_dir, 'releases'))
328
329@@ -623,7 +663,7 @@
330 path = get_release_file_path()
331 log('Using a local release: {}'.format(path))
332 return path
333- # Handle "stable" and "trunk" origins.
334+ # Handle "stable"
335 if version is not None:
336 # If the user specified a version, before attempting to download the
337 # requested release from Launchpad, check if that version is already
338
339=== modified file 'server/guiserver/auth.py'
340--- server/guiserver/auth.py 2013-11-25 14:02:15 +0000
341+++ server/guiserver/auth.py 2014-01-16 20:33:25 +0000
342@@ -20,7 +20,7 @@
343
344 - User: this is a simple data structure representing a logged in or
345 anonymous user.
346- - Authentication backends (GoBackend and PythonBackend): the primary
347+ - Authentication backends (GoBackend): the primary
348 purpose of auth backends is to provide the logic to parse requests' data
349 based on the API implementation currently in use. They can also be used
350 to create authentication requests. They must implement the following
351@@ -212,69 +212,9 @@
352 Params=dict(AuthTag=username, Password=password))
353
354
355-class PythonBackend(object):
356- """Authentication backend for the Juju Python implementation.
357-
358- A login request looks like the following:
359-
360- {
361- 'request_id': 42,
362- 'op': 'login',
363- 'user': 'admin',
364- 'password': 'ADMIN-SECRET',
365- }
366-
367- A successful login response includes these fields:
368-
369- {
370- 'request_id': 42,
371- 'op': 'login',
372- 'user': 'admin',
373- 'password': 'ADMIN-SECRET',
374- 'result': True,
375- }
376-
377- A login failure response is like the following:
378-
379- {
380- 'request_id': 42,
381- 'op': 'login',
382- 'user': 'admin',
383- 'password': 'ADMIN-SECRET',
384- 'err': True,
385- }
386- """
387-
388- def get_request_id(self, data):
389- """Return the request identifier associated with the provided data."""
390- return data.get('request_id')
391-
392- def request_is_login(self, data):
393- """Return True if data represents a login request, False otherwise."""
394- op = data.get('op')
395- return (op == 'login') and ('user' in data) and ('password' in data)
396-
397- def get_credentials(self, data):
398- """Parse the provided login data and return username and password."""
399- return data['user'], data['password']
400-
401- def login_succeeded(self, data):
402- """Return True if data represents a successful login, False otherwise.
403- """
404- return data.get('result') and not data.get('err')
405-
406- def make_request(self, request_id, username, password):
407- """Create and return an authentication request."""
408- return dict(
409- request_id=request_id,
410- op='login',
411- user=username,
412- password=password)
413-
414-
415 def get_backend(apiversion):
416 """Return the auth backend instance to use for the given API version."""
417- backend_class = {'go': GoBackend, 'python': PythonBackend}[apiversion]
418+ backend_class = {'go': GoBackend}[apiversion]
419 return backend_class()
420
421
422
423=== modified file 'server/guiserver/tests/helpers.py'
424--- server/guiserver/tests/helpers.py 2013-11-22 22:26:20 +0000
425+++ server/guiserver/tests/helpers.py 2014-01-16 20:33:25 +0000
426@@ -107,44 +107,6 @@
427 Params={'Token': token})
428
429
430-class PythonAPITestMixin(object):
431- """Add helper methods for testing the Python API implementation."""
432-
433- def get_auth_backend(self):
434- """Return an authentication backend suitable for the Python API."""
435- return auth.get_backend('python')
436-
437- def make_login_request(
438- self, request_id=42, username='user', password='passwd',
439- encoded=False):
440- """Create and return a login request message.
441-
442- If encoded is set to True, the returned message will be JSON encoded.
443- """
444- data = {
445- 'request_id': request_id,
446- 'op': 'login',
447- 'user': username,
448- 'password': password,
449- }
450- return json.dumps(data) if encoded else data
451-
452- def make_login_response(
453- self, request_id=42, successful=True, encoded=False):
454- """Create and return a login response message.
455-
456- If encoded is set to True, the returned message will be JSON encoded.
457- By default, a successful response is returned. Set successful to False
458- to return an authentication failure.
459- """
460- data = {'request_id': request_id, 'op': 'login'}
461- if successful:
462- data['result'] = True
463- else:
464- data['err'] = True
465- return json.dumps(data) if encoded else data
466-
467-
468 class BundlesTestMixin(object):
469 """Add helper methods for testing the GUI server bundles support."""
470
471
472=== modified file 'server/guiserver/tests/test_auth.py'
473--- server/guiserver/tests/test_auth.py 2013-11-28 16:43:00 +0000
474+++ server/guiserver/tests/test_auth.py 2014-01-16 20:33:25 +0000
475@@ -204,12 +204,6 @@
476 self.assert_user('', '', False)
477
478
479-class TestPythonAuthMiddleware(
480- helpers.PythonAPITestMixin, AuthMiddlewareTestMixin,
481- LogTrapTestCase, unittest.TestCase):
482- pass
483-
484-
485 class BackendTestMixin(object):
486 """Include tests for the authentication backends.
487
488@@ -288,35 +282,6 @@
489 self.assertFalse(is_login, request)
490
491
492-class TestPythonBackend(
493- helpers.PythonAPITestMixin, BackendTestMixin, unittest.TestCase):
494-
495- def test_request_is_not_login(self):
496- # False is returned if the passed data is not a login request.
497- requests = (
498- {},
499- {
500- 'request_id': 42,
501- 'op': 'INVALID',
502- 'user': 'user',
503- 'password': 'passwd',
504- },
505- {
506- 'request_id': 42,
507- 'op': 'login',
508- 'password': 'passwd',
509- },
510- {
511- 'request_id': 42,
512- 'op': 'login',
513- 'user': 'user',
514- },
515- )
516- for request in requests:
517- is_login = self.backend.request_is_login(request)
518- self.assertFalse(is_login, request)
519-
520-
521 class TestAuthenticationTokenHandler(LogTrapTestCase, unittest.TestCase):
522
523 def setUp(self):
524
525=== modified file 'tests/20-functional.test'
526--- tests/20-functional.test 2014-01-15 14:49:19 +0000
527+++ tests/20-functional.test 2014-01-16 20:33:25 +0000
528@@ -40,7 +40,8 @@
529 )
530 import example
531
532-JUJU_GUI_TEST_BRANCH = 'lp:~juju-gui/juju-gui/charm-tests-branch'
533+JUJU_GUI_TEST_BRANCH = 'https://github.com/juju/juju-gui.git master'
534+
535 try:
536 admin_secret = get_admin_secret()
537 except ValueError as err:
538@@ -193,7 +194,7 @@
539 self.assertTrue(server_info['sandbox'])
540
541 def test_branch_source(self):
542- # Ensure the Juju GUI is correctly deployed from a Bazaar branch.
543+ # Ensure the Juju GUI is correctly deployed from a Git branch.
544 options = {'juju-gui-source': JUJU_GUI_TEST_BRANCH}
545 self.service_name, unit_info, _ = juju_deploy_gui(options=options)
546 hostname = unit_info['public-address']
547
548=== modified file 'tests/deploy.py'
549--- tests/deploy.py 2013-11-27 14:37:06 +0000
550+++ tests/deploy.py 2014-01-16 20:33:25 +0000
551@@ -33,14 +33,17 @@
552 )
553
554
555-rsync = command('rsync', '-a', '--exclude', '.bzr', '--exclude', '/tests')
556+rsync = command('rsync', '-a',
557+ '--exclude', '.git',
558+ '--exclude', '.bzr',
559+ '--exclude', '/tests')
560
561
562 def setup_repository(name, source, series='precise'):
563 """Create a temporary Juju repository to use for charm deployment.
564
565 Copy the charm files in source in the precise repository section, using the
566- provided charm name and excluding the virtualenv and Bazaar directories.
567+ provided charm name and excluding the virtualenv and Git directories.
568
569 Return the repository path.
570 """
571
572=== modified file 'tests/test_deploy.py'
573--- tests/test_deploy.py 2013-11-27 14:37:06 +0000
574+++ tests/test_deploy.py 2014-01-16 20:33:25 +0000
575@@ -51,10 +51,6 @@
576 self.addCleanup(shutil.rmtree, self.source)
577 # Create a file in the source dir.
578 _, self.root_file = tempfile.mkstemp(dir=self.source)
579- # Create a Bazaar repository directory with a file in it.
580- bzr_dir = os.path.join(self.source, '.bzr')
581- os.mkdir(bzr_dir)
582- tempfile.mkstemp(dir=bzr_dir)
583 # Create a tests directory including a .venv directory and a file.
584 self.tests_dir = os.path.join(self.source, 'tests')
585 venv_dir = os.path.join(self.tests_dir, '.venv')
586
587=== modified file 'tests/test_utils.py'
588--- tests/test_utils.py 2014-01-15 12:03:24 +0000
589+++ tests/test_utils.py 2014-01-16 20:33:25 +0000
590@@ -1,6 +1,6 @@
591 # This file is part of the Juju GUI, which lets users view and manage Juju
592 # environments within a graphical interface (https://launchpad.net/juju-gui).
593-# Copyright (C) 2012-2013 Canonical Ltd.
594+# Copyright (C) 2012-2014 Canonical Ltd.
595 #
596 # This program is free software: you can redistribute it and/or modify it under
597 # the terms of the GNU Affero General Public License version 3, as published by
598@@ -368,7 +368,7 @@
599 self.add('juju-gui-1.2.3.4.tgz') # Wrong version.
600 self.add('juju-gui-1.2.3.build.42.tgz') # Missing "+" separator.
601 self.add('juju-gui-1.2.3+built.42.tgz') # Typo.
602- self.add('juju-gui-1.2.3+build.42.47.tgz') # Invalid bzr revno.
603+ self.add('juju-gui-1.2.3+build.42.47.tgz') # Invalid revno.
604 self.add('juju-gui-1.2.3+build.42.bz2') # Wrong file extension again.
605 with self.mock_releases_dir():
606 with self.assert_error():
607@@ -507,12 +507,6 @@
608 self.assertEqual('http://example.com/0.1.1.tgz', url)
609 self.assertEqual('0.1.1.tgz', name)
610
611- def test_latest_trunk_release(self):
612- # Ensure the correct URL is returned for the latest trunk release.
613- url, name = get_launchpad_release(self.project, 'trunk', None)
614- self.assertEqual('http://example.com/0.1.1+build.1.tgz', url)
615- self.assertEqual('0.1.1+build.1.tgz', name)
616-
617 def test_specific_stable_release(self):
618 # Ensure the correct URL is returned for a specific version of the
619 # stable release.
620@@ -520,14 +514,6 @@
621 self.assertEqual('http://example.com/0.1.0.tgz', url)
622 self.assertEqual('0.1.0.tgz', name)
623
624- def test_specific_trunk_release(self):
625- # Ensure the correct URL is returned for a specific version of the
626- # trunk release.
627- url, name = get_launchpad_release(
628- self.project, 'trunk', '0.1.0+build.1')
629- self.assertEqual('http://example.com/0.1.0+build.1.tgz', url)
630- self.assertEqual('0.1.0+build.1.tgz', name)
631-
632 def test_series_not_found(self):
633 # A ValueError is raised if the series cannot be found.
634 with self.assertRaises(ValueError) as cm:
635@@ -665,47 +651,38 @@
636 expected = ('stable', None)
637 self.assertTupleEqual(expected, parse_source('stable'))
638
639- def test_latest_trunk_release(self):
640- # Ensure the latest trunk release is correctly parsed.
641- expected = ('trunk', None)
642- self.assertTupleEqual(expected, parse_source('trunk'))
643+ def test_latest_develop_release(self):
644+ # Ensure the latest develop branch release is correctly parsed.
645+ expected = ('develop', None)
646+ self.assertTupleEqual(expected, parse_source('develop'))
647
648- def test_stable_release(self):
649+ @mock.patch('utils.log')
650+ def test_stable_release(self, *args):
651 # Ensure a specific stable release is correctly parsed.
652 expected = ('stable', '0.1.0')
653 self.assertTupleEqual(expected, parse_source('0.1.0'))
654
655- def test_trunk_release(self):
656- # Ensure a specific trunk release is correctly parsed.
657- expected = ('trunk', '0.1.0+build.1')
658- self.assertTupleEqual(expected, parse_source('0.1.0+build.1'))
659-
660- def test_bzr_branch(self):
661- # Ensure a Bazaar branch is correctly parsed.
662- sources = ('lp:example', 'http://bazaar.launchpad.net/example')
663- for source in sources:
664- expected = ('branch', (source, None))
665- self.assertEqual(expected, parse_source(source))
666-
667- def test_bzr_branch_and_revision(self):
668- # A Bazaar branch is correctly parsed when including revision.
669- sources = ('lp:example:42', 'http://bazaar.launchpad.net/example:1')
670- for source in sources:
671- expected = ('branch', tuple(source.rsplit(':', 1)))
672+ def test_git_branch(self):
673+ # Ensure a Git branch is correctly parsed.
674+ source = 'https://github.com/juju/juju-gui.git'
675+ expected = ('branch', (source, None))
676+ self.assertEqual(expected, parse_source(source))
677+
678+ def test_git_branch_and_revision(self):
679+ # A Git branch is correctly parsed when including revision.
680+ sources = (
681+ 'https://github.com/juju/juju-gui.git test_feature',
682+ 'https://github.com/juju/juju-gui.git @de5e6',
683+ )
684+
685+ for source in sources:
686+ expected = ('branch', tuple(source.rsplit(' ', 1)))
687 self.assertEqual(expected, parse_source(source))
688
689 def test_url(self):
690 expected = ('url', 'http://example.com/gui')
691 self.assertTupleEqual(
692- expected, parse_source('url:http://example.com/gui'))
693-
694- def test_file_url(self):
695- expected = ('url', 'file:///foo/bar')
696- self.assertTupleEqual(expected, parse_source('url:/foo/bar'))
697-
698- def test_relative_file_url(self):
699- expected = ('url', 'file:///current/dir/foo/bar')
700- self.assertTupleEqual(expected, parse_source('url:foo/bar'))
701+ expected, parse_source('http://example.com/gui'))
702
703
704 class TestRenderToFile(unittest.TestCase):

Subscribers

People subscribed via source and target branches