Affected files (+96, -1 lines):
A [revision details]
M quickstart/app.py
M quickstart/manage.py
M quickstart/tests/helpers.py
M quickstart/tests/test_app.py
+def ensure_dependencies():
+ """Ensure that Juju and LXC are installed.
+
+ If juju is not found in the PATH, then add the juju stable PPA and
install
+ both juju and lxc.
+
+ Return when juju is available.
+ Raise a ProgramExit if an error occurs installing.
+ """
+ retcode = utils.call('juju', 'version')[0]
+ retcode += utils.call('lxc-ls')[0]
+ if retcode > 0:
+ cmds = [
+ ['apt-add-repository', '-y', 'ppa:juju/stable'],
+ ['apt-get', 'update'],
+ ['apt-get', 'install', '-y', 'juju-core', 'lxc']
+ ]
+ for cmd in cmds:
+ cmd.insert(0, 'sudo')
+ retcode, _, error = utils.call(*cmd)
+ if retcode:
+ raise ProgramExit(error)
+ # XXX Makyo #1247214:
+ # Here, we should guide the user through cloud credentials and
+ # juju init.
+ raise ProgramExit('Juju is now installed; please run the same
juju '
+ 'quickstart command again to proceed.')
+
+
def bootstrap(env_name, is_local=False, debug=False):
"""Bootstrap the Juju environment with the given name.
class CallTestsMixin(object):
- """Easily use the quickstart.utils.call function."""
+ """Easily use the quickstart.utils.call and
+ quickstart.utils.sudo_call functions."""
def patch_call(self, retcode, output='', error=''):
"""Patch the quickstart.utils.call function."""
Reviewers: mp+196011_ code.launchpad. net,
Message:
Please take a look.
Description:
Ensure juju and lxc are installed
To test: make check
To QA:
- Create an lxc or vm without juju installed
- Clone this branch
- Run `make sysdeps`
- Run `make run`
It should install juju, lxc, and dependencies, then prompt you to run
again after initializing your juju environments.
https:/ /code.launchpad .net/~makyo/ juju-quickstart /ensure- juju-lxc/ +merge/ 196011
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/29980043/
Affected files (+96, -1 lines): manage. py tests/helpers. py tests/test_ app.py
A [revision details]
M quickstart/app.py
M quickstart/
M quickstart/
M quickstart/
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 self.message)
=== modified file 'quickstart/app.py'
--- quickstart/app.py 2013-11-20 11:35:30 +0000
+++ quickstart/app.py 2013-11-20 20:36:24 +0000
@@ -45,6 +45,35 @@
return 'juju-quickstart: error: {}'.format(
+def ensure_ dependencies( ): 'lxc-ls' )[0] repository' , '-y', 'ppa:juju/stable'],
+ """Ensure that Juju and LXC are installed.
+
+ If juju is not found in the PATH, then add the juju stable PPA and
install
+ both juju and lxc.
+
+ Return when juju is available.
+ Raise a ProgramExit if an error occurs installing.
+ """
+ retcode = utils.call('juju', 'version')[0]
+ retcode += utils.call(
+ if retcode > 0:
+ cmds = [
+ ['apt-add-
+ ['apt-get', 'update'],
+ ['apt-get', 'install', '-y', 'juju-core', 'lxc']
+ ]
+ for cmd in cmds:
+ cmd.insert(0, 'sudo')
+ retcode, _, error = utils.call(*cmd)
+ if retcode:
+ raise ProgramExit(error)
+ # XXX Makyo #1247214:
+ # Here, we should guide the user through cloud credentials and
+ # juju init.
+ raise ProgramExit('Juju is now installed; please run the same
juju '
+ 'quickstart command again to proceed.')
+
+
def bootstrap(env_name, is_local=False, debug=False):
"""Bootstrap the Juju environment with the given name.
Index: quickstart/ manage. py manage. py' manage. py 2013-11-20 11:35:30 +0000 manage. py 2013-11-20 20:30:08 +0000 version) ) dependencies( ) 'bootstrapping the {} environment (type: {})'.format(
options. env_name, options.env_type))
=== modified file 'quickstart/
--- quickstart/
+++ quickstart/
@@ -218,6 +218,8 @@
def run(options):
"""Run the application."""
print('juju quickstart v{}'.format(
+ print('ensuring juju and lxc are installed')
+ app.ensure_
print(
is_local = options.env_type == 'local'
Index: quickstart/ tests/helpers. py tests/helpers. py' tests/helpers. py 2013-11-18 11:42:15 +0000 tests/helpers. py 2013-11-20 20:30:08 +0000
=== modified file 'quickstart/
--- quickstart/
+++ quickstart/
@@ -85,7 +85,8 @@
class CallTestsMixin( object) : utils.call function.""" utils.call and utils.sudo_ call functions."""
- """Easily use the quickstart.
+ """Easily use the quickstart.
+ quickstart.
def patch_call(self, retcode, output='', error=''): utils.call function."""
"""Patch the quickstart.
Index: quickstart/ tests/test_ app.py tests/test_ app.py' tests/test_ app.py 2013-11-20 11:35:30 +0000 tests/test_ app.py 2013-11-20 20:36:24 +0000 EnvError( {'Error' : message})
=== modified file 'quickstart/
--- quickstart/
+++ quickstart/
@@ -61,6 +61,67 @@
return jujuclient.
+class TestEnsureDepen dencies( CallTestsMixin, ProgramExitTest sMixin, unittest.TestCase): dependencies( self, call_effects): multiple_ calls(call_ effects) as mock_call: dependencies( ) install( self): program_ exit('Juju is now installed; please run ensure_ dependencies( l(call. call_count, 5) has_calls( [ 'lxc-ls' ), repository' , '-y', no_install( self): ensure_ dependencies( l(call. call_count, 2) program_ exit('install failure'): ensure_ dependencies( l(call. call_count, 3)
helpers. CallTestsMixin, ProgramExitTest sMixin, unittest.TestCase):
+ helpers.
+
+ def call_ensure_
+ with self.patch_
+ app.ensure_
+ return mock_call
+
+ def test_success_
+ # XXX Makyo #1247214:
+ # Here, we should guide the user through cloud credentials and
+ # juju init.
+ with self.assert_
the '
+ 'same juju quickstart command again
to '
+ 'proceed.'):
+ call = self.call_
+ [
+ (127, '', 'no juju'),
+ (127, '', 'no lxc'),
+ (0, 'add repo', ''),
+ (0, 'update', ''),
+ (0, 'install', ''),
+ ]
+ )
+ self.assertEqua
+ call.assert_
+ mock.call('juju', 'version'),
+ mock.call(
+ mock.call('sudo', 'apt-add-
+ 'ppa:juju/stable'),
+ mock.call('sudo', 'apt-get', 'update'),
+ mock.call('sudo', 'apt-get', 'install', '-y', 'juju-core',
+ 'lxc'),
+ ])
+
+ def test_success_
+ call = self.call_
+ [
+ (0, '1.16', ''),
+ (0, '', ''),
+ (0, 'add repo', ''),
+ (0, 'update', ''),
+ (0, 'install', ''),
+ ]
+ )
+ self.assertEqua
+
+ def test_failure(self):
+ with self.assert_
+ call = self.call_
+ [
+ (127, '', ''),
+ (127, '', ''),
+ (1, 'add repo', 'install failure'),
+ (1, 'update', 'uh-oh'),
+ (1, 'install', 'oh no'),
+ ]
+ )
+ self.assertEqua
+
+
@mock_print
class TestBootstrap(