yellow team mailing list archive
-
yellow team
-
Mailing list archive
-
Message #00648
[Merge] lp:~frankban/lpsetup/yellow-ppa into lp:lpsetup
Francesco Banconi has proposed merging lp:~frankban/lpsetup/yellow-ppa into lp:lpsetup.
Requested reviews:
Launchpad Yellow Squad (yellow)
For more details, see:
https://code.launchpad.net/~frankban/lpsetup/yellow-ppa/+merge/100102
== Changes ==
Updated `lxc-install` subcommand to add the yellow ppa repository in the container.
This is required because we want to install lpsetup (and python-shell-toolbox as a dependency) inside the container.
The helper function `apt_get_install` is now called passing caller=call. This way the output is actually printed to the terminal.
Added a dynamic dispatcher to StepsBasedSubCommand. If a sub command defines a step `mystep`, the dispatcher tries to run the step invoking `subcommand.call_mystep(namespace, step, args)`. If a method named `call_[step name]` is not defined, a default step runner is used. This way, a sub command can easily wrap or override the provided steps. This can be useful in the future, for example, having a step that can or can not be run based on a sub command option.
== Tests ==
$ bin/test
Running zope.testrunner.layer.UnitTests tests:
Set up zope.testrunner.layer.UnitTests in 0.000 seconds.
Ran 39 tests with 0 failures and 0 errors in 0.026 seconds.
Tearing down left over layers:
Tear down zope.testrunner.layer.UnitTests in 0.000 seconds.
--
https://code.launchpad.net/~frankban/lpsetup/yellow-ppa/+merge/100102
Your team Launchpad Yellow Squad is requested to review the proposed merge of lp:~frankban/lpsetup/yellow-ppa into lp:lpsetup.
=== modified file 'lpsetup/argparser.py'
--- lpsetup/argparser.py 2012-03-22 10:39:05 +0000
+++ lpsetup/argparser.py 2012-03-30 11:06:25 +0000
@@ -394,6 +394,24 @@
>>> trace
['step1 received eggs']
+
+ A dynamic dispatcher takes care of running the steps. This way, a
+ sub command can easily wrap or override the provided steps, defining a
+ method named 'call_[step name]'::
+
+ >>> trace = []
+
+ >>> class DynamicSubCommand(SubCommand):
+ ... def call_step1(self, namespace, step, args):
+ ... trace.append('running step')
+ ... step(*args)
+
+ >>> parser = ArgumentParser()
+ >>> _ = parser.register_subcommand('sub', DynamicSubCommand)
+ >>> namespace = parser.parse_args('sub --foo eggs --bar spam'.split())
+ >>> namespace.main(namespace)
+ >>> trace
+ ['running step', 'step1 received eggs', 'step2 received eggs and spam']
"""
steps = ()
@@ -441,15 +459,22 @@
'--skip-steps', nargs='+', choices=self._step_names,
help='Skip one or more internal functions.')
+ def _call_step(self, namespace, step, args):
+ """Default callable used to run a `step`, using given `args`."""
+ return step(*args)
+
def handle(self, namespace):
skip_steps = namespace.skip_steps or []
step_names = filter(
lambda step_name: step_name not in skip_steps,
namespace.steps or self._step_names)
+ default_step_runner = self._call_step
for step_name in step_names:
step, arg_names = self._steps[step_name]
args = [getattr(namespace, i) for i in arg_names]
+ step_runner = getattr(
+ self, 'call_' + step_name, default_step_runner)
try:
- step(*args)
+ step_runner(namespace, step, args)
except subprocess.CalledProcessError as err:
return err
=== modified file 'lpsetup/settings.py'
--- lpsetup/settings.py 2012-03-16 17:03:20 +0000
+++ lpsetup/settings.py 2012-03-30 11:06:25 +0000
@@ -56,6 +56,7 @@
)
LP_SOURCE_DEPS = (
'http://bazaar.launchpad.net/~launchpad/lp-source-dependencies/trunk')
+LPSETUP_PPA = 'ppa:yellow/ppa'
LXC_CONFIG_TEMPLATE = '/etc/lxc/local.conf'
LXC_GUEST_ARCH = 'i386'
LXC_GUEST_CHOICES = ('lucid', 'oneiric', 'precise')
=== modified file 'lpsetup/subcommands/install.py'
--- lpsetup/subcommands/install.py 2012-03-22 10:48:50 +0000
+++ lpsetup/subcommands/install.py 2012-03-30 11:06:25 +0000
@@ -118,7 +118,7 @@
"""Initialize host machine."""
# Install necessary deb packages. This requires Oneiric or later.
call('apt-get', 'update')
- apt_get_install(*BASE_PACKAGES)
+ apt_get_install(*BASE_PACKAGES, caller=call)
# Create the user (if he does not exist).
if not user_exists(user):
call('useradd', '-m', '-s', '/bin/bash', '-U', user)
@@ -181,7 +181,7 @@
call("echo 'mountall hold' | dpkg --set-selections", shell=True)
call('apt-get', 'update')
# Install base and Launchpad deb packages.
- apt_get_install(*LP_PACKAGES, LANG='C')
+ apt_get_install(*LP_PACKAGES, LANG='C', caller=call)
def setup_launchpad(user, dependencies_dir, directory, valid_ssh_keys):
=== modified file 'lpsetup/subcommands/lxcinstall.py'
--- lpsetup/subcommands/lxcinstall.py 2012-03-22 17:28:04 +0000
+++ lpsetup/subcommands/lxcinstall.py 2012-03-30 11:06:25 +0000
@@ -31,6 +31,7 @@
from lpsetup.settings import (
BASE_PACKAGES,
DHCP_FILE,
+ LPSETUP_PPA,
LXC_CONFIG_TEMPLATE,
LXC_GUEST_ARCH,
LXC_GUEST_CHOICES,
@@ -57,7 +58,7 @@
for parallel testing using ephemeral instances.
"""
# Install necessary deb packages.
- apt_get_install(*LXC_PACKAGES)
+ apt_get_install(*LXC_PACKAGES, caller=call)
# XXX 2012-02-02 gmb bug=925024:
# These calls need to be removed once the lxc vs. apparmor bug
# is resolved, since having apparmor enabled for lxc is very
@@ -116,10 +117,16 @@
break
-def initialize_lxc(lxc_name, ssh_key_path):
+def initialize_lxc(lxc_name, ssh_key_path, lxc_os):
"""Initialize LXC container."""
base_packages = list(BASE_PACKAGES) + ['lpsetup']
sshcall = ssh(lxc_name, key=ssh_key_path)
+ args = {
+ 'assume_yes': '' if lxc_os == 'lucid' else '-y',
+ 'repository': LPSETUP_PPA,
+ }
+ sshcall('apt-add-repository {assume_yes} {repository}'.format(**args))
+ sshcall('apt-get clean && apt-get update')
sshcall(
'DEBIAN_FRONTEND=noninteractive '
'apt-get install -y ' + ' '.join(base_packages))
@@ -158,7 +165,7 @@
(wait_for_lxc,
'lxc_name', 'ssh_key_path'),
(initialize_lxc,
- 'lxc_name', 'ssh_key_path'),
+ 'lxc_name', 'ssh_key_path', 'lxc_os'),
(setup_launchpad_lxc,
'user', 'dependencies_dir', 'directory',
'valid_ssh_keys', 'ssh_key_path', 'lxc_name'),
=== modified file 'lpsetup/tests/examples.py'
--- lpsetup/tests/examples.py 2012-03-22 10:56:14 +0000
+++ lpsetup/tests/examples.py 2012-03-30 11:06:25 +0000
@@ -67,3 +67,12 @@
(bad_step, 'foo'),
(step2, 'foo', 'bar'),
)
+
+
+class DynamicStepsBasedSubCommand(StepsBasedSubCommand):
+ """An example steps based sub command (using internal step dispatcher)."""
+
+ def call_step1(self, namespace, step, args):
+ print 'running step1 with {args} while bar is {bar}'.format(
+ args=','.join(args), bar=namespace.bar)
+ step(*args)
=== modified file 'lpsetup/tests/test_argparser.py'
--- lpsetup/tests/test_argparser.py 2012-03-22 10:56:14 +0000
+++ lpsetup/tests/test_argparser.py 2012-03-30 11:06:25 +0000
@@ -188,3 +188,20 @@
error = self.parse_and_call_main('--foo eggs')
self.assertEqual(1, error.returncode)
self.check_output(['step1 received eggs'], output)
+
+
+class DynamicStepsBasedSubCommandTest(SubCommandTestMixin, unittest.TestCase):
+
+ sub_command_class = examples.DynamicStepsBasedSubCommand
+
+ def test_dynamic_dispatcher(self):
+ # The test runner calls a function named 'call_[step name]' if it is
+ # defined.
+ with capture_output() as output:
+ self.parse_and_call_main('--foo eggs --bar spam')
+ expected = [
+ 'running step1 with eggs while bar is spam',
+ 'step1 received eggs',
+ 'step2 received eggs and spam'
+ ]
+ self.check_output(expected, output)