Merge lp:~benji/lpsetup/bug-1020734-first-integration-test into lp:lpsetup

Proposed by Benji York
Status: Merged
Approved by: Benji York
Approved revision: 53
Merged at revision: 48
Proposed branch: lp:~benji/lpsetup/bug-1020734-first-integration-test
Merge into: lp:lpsetup
Diff against target: 200 lines (+126/-7)
6 files modified
README.rst (+13/-0)
lpsetup/handlers.py (+1/-1)
lpsetup/settings.py (+2/-1)
lpsetup/subcommands/inithost.py (+4/-3)
lpsetup/subcommands/initrepo.py (+1/-2)
lpsetup/tests/integration/non-lxc.py (+105/-0)
To merge this branch: bzr merge lp:~benji/lpsetup/bug-1020734-first-integration-test
Reviewer Review Type Date Requested Status
Gary Poster (community) Approve
Review via email: mp+114044@code.launchpad.net

Commit message

Add a first integration test.

Description of the change

This is a first cut at an integration test for lpsetup that uses juju to provision a clean EC2 instance and then uses that instance to run a test.

This first cut only tests init-host because I couldn't get init-repo to work yet. That is either a bug in init-repo or a deficiency in the test setup, either way I wanted to get this test landed and we can address testing init-repo separately.

See the README for instructions on running the test.

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

Yay! Thank you! The following are random thoughts while looking at the
code. We can address all of them later, I think (post-landing) but I'd
like to address them one way or another. Maybe #1 should be addressed now.

1) I'm not sure how we can run this in tarmac as is; it will need to
transfer the branch as currently tested over to the other machine, and
not a particular branch. Maybe juju scp -r [the current code tree, as
calculated in the test by os.path fun with __file__] would be better for
transferring the code? Once we have that ironed out, and this branch
landed, I'd really like a new card that hooks up the integration test on
tarmac to be created and started ASAP.

2) I understand why python-shelltoolbox is needed but not why apache is
needed. Shouldn't lpsetup get apache?

3) I'm not sure why you have to set up bzr whoami, and I think lpsetup
is supposed to be able to do that. The test should probably take a
non-root user as argument, though. We can do that as a next step, though.

4) We can refine the time.sleep(30) later.

5) The lxc story will need to have lp-lxc-ip installed. I'd suggest
making the setup run python setup.py install, and then have the test run
the lp-setup from the environment.

6) The lxc story also will need to install lpsetup in the lxc container.
 Normally that is done from the PPA, but we can't do that here, because
that would not test the branch that we currently are running. Since the
home directories are shared in the host and the directory, I think we
could have an option to initlxc that passes a directory, and means
"instead of getting the PPA in the container, use python setup.py
install [this directory]".

#6 runs counter to what I wrote in my previous email about this, but
there are many upsides to your alternative approach and I think we ought
to stick with it.

Thanks again!

Revision history for this message
Gary Poster (gary) :
review: Approve
Revision history for this message
Benji York (benji) wrote :

> 1) I'm not sure how we can run this in tarmac as is; it will need to
> transfer the branch as currently tested over to the other machine, and
> not a particular branch. Maybe juju scp -r [the current code tree, as
> calculated in the test by os.path fun with __file__] would be better for
> transferring the code?

Good idea. Done.

> Once we have that ironed out, and this branch
> landed, I'd really like a new card that hooks up the integration test on
> tarmac to be created and started ASAP.

I have created a card ("Tarmac should run the integration tests"), but
because of the SSH-needs-desperately-to-ask-yes-or-no-questions issue we
talked about earlier, it may be tricky.

> 2) I understand why python-shelltoolbox is needed but not why apache is
> needed. Shouldn't lpsetup get apache?

It should, and now it does (apache2.2-common, that is).

> 3) I'm not sure why you have to set up bzr whoami, and I think lpsetup
> is supposed to be able to do that. The test should probably take a
> non-root user as argument, though. We can do that as a next step, though.

This was so the test takes the most common path through lpsetup. As we
discussed, I moved the whomai setup into the test function, which makes
more sense.

> 4) We can refine the time.sleep(30) later.

I guess we're... <puts on sunglasses> hitting the snooze bar.

> 5) The lxc story will need to have lp-lxc-ip installed. I'd suggest
> making the setup run python setup.py install, and then have the test run
> the lp-setup from the environment.
>
> 6) The lxc story also will need to install lpsetup in the lxc container.
> Normally that is done from the PPA, but we can't do that here, because
> that would not test the branch that we currently are running. Since the
> home directories are shared in the host and the directory, I think we
> could have an option to initlxc that passes a directory, and means
> "instead of getting the PPA in the container, use python setup.py
> install [this directory]".
>
> #6 runs counter to what I wrote in my previous email about this, but
> there are many upsides to your alternative approach and I think we ought
> to stick with it.

The above has been moved to a new "Make LXC integration test" card.

Revision history for this message
Launchpad QA Bot (lpqabot) wrote :

The attempt to merge lp:~benji/lpsetup/bug-1020734-first-integration-test into lp:lpsetup failed. Below is the output from the failed tests.

./lpsetup/tests/integration/non-lxc.py
      11: 'STDOUT' imported but unused
      18: E302 expected 2 blank lines, found 1
      24: E302 expected 2 blank lines, found 1
./lpsetup/subcommands/initrepo.py
      18: 'LP_SSH_REPO' imported but unused

53. By Benji York

fix lint

Revision history for this message
Gary Poster (gary) wrote :

Benji and I have verified that juju ssh can take the arguments we need, so we can address the tarmac story in the future without too much trouble, it seems. Example:

$ juju ssh -t -t -o 'StrictHostKeyChecking=no' -o 'UserKnownHostsFile=/dev/null' 2

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README.rst'
2--- README.rst 2012-07-03 18:02:41 +0000
3+++ README.rst 2012-07-10 16:18:18 +0000
4@@ -44,6 +44,19 @@
5 nosetests
6
7
8+Integration tests
9+~~~~~~~~~~~~~~~~~
10+
11+Integration tests can be found in lpsetup/tests/integration. They
12+require the "ubuntu" juju charm which, at the time of this writing, is
13+not available in the charm store. Check it out into the local juju
14+charm repository from lp:~charmers/charms/precise/ubuntu/trunk.
15+
16+The integration tests use a juju environment named "lpsetup-testing" so
17+you must create an appropriately configured juju environment with that
18+name before running the tests.
19+
20+
21 Linting
22 ~~~~~~~
23
24
25=== modified file 'lpsetup/handlers.py'
26--- lpsetup/handlers.py 2012-07-06 19:18:58 +0000
27+++ lpsetup/handlers.py 2012-07-10 16:18:18 +0000
28@@ -255,7 +255,7 @@
29 def handle_source(namespace):
30 """Handle the --source and --use-http options."""
31 # If a source has been provided, then there is nothing else to do.
32- if namespace.source:
33+ if namespace.source is not None:
34 return
35 if namespace.use_http:
36 namespace.source = LP_HTTP_REPO
37
38=== modified file 'lpsetup/settings.py'
39--- lpsetup/settings.py 2012-07-09 14:40:11 +0000
40+++ lpsetup/settings.py 2012-07-10 16:18:18 +0000
41@@ -12,7 +12,8 @@
42 'ppa:launchpad/ppa',
43 'ppa:bzr/ppa',
44 )
45-BASE_PACKAGES = ['ssh', 'bzr']
46+# a2enmod requires apache2.2-common
47+BASE_PACKAGES = ['ssh', 'bzr', 'apache2.2-common']
48 CHECKOUT_DIR = '~/launchpad/lp-branches'
49 DEPENDENCIES_DIR = '~/launchpad/lp-sourcedeps'
50 HOSTS_CONTENT = (
51
52=== modified file 'lpsetup/subcommands/inithost.py'
53--- lpsetup/subcommands/inithost.py 2012-07-09 11:36:53 +0000
54+++ lpsetup/subcommands/inithost.py 2012-07-10 16:18:18 +0000
55@@ -201,9 +201,10 @@
56
57 # Create Apache document roots, to avoid warnings.
58 mkdirs(*LP_APACHE_ROOTS)
59- # Set up Apache modules.
60- for module in LP_APACHE_MODULES.split():
61- call('a2enmod', module)
62+
63+ # Set up Apache modules.
64+ for module in LP_APACHE_MODULES.split():
65+ call('a2enmod', module)
66
67 # Set up container hosts file.
68 lines = [get_file_header()]
69
70=== modified file 'lpsetup/subcommands/initrepo.py'
71--- lpsetup/subcommands/initrepo.py 2012-07-05 18:38:51 +0000
72+++ lpsetup/subcommands/initrepo.py 2012-07-10 16:18:18 +0000
73@@ -20,7 +20,6 @@
74 LP_BRANCH_NAME,
75 LP_BZR_LOCATIONS,
76 LP_CHECKOUT_NAME,
77- LP_SSH_REPO,
78 )
79 from lpsetup.utils import (
80 call,
81@@ -85,7 +84,7 @@
82 def add_arguments(self, parser):
83 super(SubCommand, self).add_arguments(parser)
84 parser.add_argument(
85- '--source', default=LP_SSH_REPO,
86+ '--source', default=None,
87 help='Location from which to retrieve Launchpad source. Default '
88 'is lp:launchpad (if --use-http is false), otherwise '
89 'http://bazaar.launchpad.net/~launchpad-pqm/launchpad/devel.')
90
91=== added directory 'lpsetup/tests/integration'
92=== added file 'lpsetup/tests/integration/non-lxc.py'
93--- lpsetup/tests/integration/non-lxc.py 1970-01-01 00:00:00 +0000
94+++ lpsetup/tests/integration/non-lxc.py 2012-07-10 16:18:18 +0000
95@@ -0,0 +1,105 @@
96+#!/usr/bin/env python
97+# Copyright 2012 Canonical Ltd. This software is licensed under the
98+# GNU Affero General Public License version 3 (see the file LICENSE).
99+
100+"""A simple, end-to-end integration test."""
101+
102+import os
103+import sys
104+import time
105+
106+from subprocess import (
107+ check_call,
108+ Popen,
109+ PIPE,
110+ )
111+
112+
113+def banner(s):
114+ width = 70
115+ print '*' * width
116+ print '* ' + s.ljust(width - 4) + ' *'
117+ print '*' * width
118+
119+
120+def on_remote(args):
121+ if type(args) == str:
122+ args = args.split()
123+
124+ check_call('juju ssh 1 -e lpsetup-testing'.split() + list(args))
125+
126+
127+def check_environment():
128+ """Be sure the test environment doesn't exist."""
129+ banner('Checking test environment.')
130+ # We want to be really sure we do not clobber an already-existing juju
131+ # environment. Therefore we make sure one doesn't exist before
132+ # bootstrapping.
133+ code = os.system('juju status -e lpsetup-testing')
134+ if code == 0:
135+ # The "juju status" should have failed.
136+ raise RuntimeError('A juju environment unexpectedly exists.')
137+
138+
139+def set_up():
140+ """Set up a juju-managed instance to run the tests on."""
141+ banner('Setting up the test environment.')
142+ check_call('juju bootstrap -e lpsetup-testing'.split())
143+ # XXX The "ubuntu" charm is broken, so it has to be loaded from the local
144+ # repository. Get it from lp:~charmers/charms/precise/ubuntu/trunk.
145+ check_call('juju deploy local:ubuntu --repository ~/juju-charms'
146+ ' -e lpsetup-testing --constraints instance-type=m1.large'.split())
147+
148+ start_time = time.time()
149+ while time.time() - start_time < 600:
150+ process = Popen('juju status -e lpsetup-testing'.split(), stdout=PIPE)
151+ stdout, stderr = process.communicate()
152+ if 'instance-state: running' in stdout:
153+ break
154+ else:
155+ raise RuntimeError('starting the instance took too long')
156+
157+ # Even though the instance-state is "running", it's still not ready, so
158+ # wait a little while before continuing.
159+ time.sleep(30)
160+
161+ on_remote('sudo apt-add-repository --yes ppa:yellow/ppa')
162+ on_remote('sudo apt-get update')
163+ on_remote('sudo apt-get install python-shelltoolbox')
164+ check_call('juju scp -e lpsetup-testing -r . 1:lpsetup'.split())
165+
166+
167+def do_test():
168+ """Run an end-to-end integration tests of the non-LXC lpsetup story."""
169+ banner('Running (non-LXC) integration test.')
170+ # Since the most common scenario is to have bzr whoami setup, we do that
171+ # instead of providing the arguments directly to lpsetup.
172+ on_remote(('bzr', 'whoami', '"Not A Real Person <no@example.com>"'))
173+ on_remote('cd lpsetup; ./lp-setup init-host'.split())
174+
175+
176+def tear_down():
177+ banner('Cleaning up.')
178+ code = os.system('juju destroy-environment -e lpsetup-testing')
179+ if code != 0:
180+ raise RuntimeError('Destroying the test juju environment failed.')
181+
182+
183+def main():
184+ check_environment()
185+ try:
186+ set_up()
187+ try:
188+ do_test()
189+ except:
190+ banner('Test failed. Sorry.')
191+ return 1
192+ else:
193+ banner('Test succeeded.')
194+ return 0
195+ finally:
196+ tear_down()
197+
198+
199+if __name__ == '__main__':
200+ sys.exit(main())

Subscribers

People subscribed via source and target branches

to all changes: