Merge lp:~dpb/charms/trusty/landscape-client/fix-integration-tests into lp:~landscape/charms/trusty/landscape-client/trunk

Proposed by David Britton
Status: Merged
Merged at revision: 50
Proposed branch: lp:~dpb/charms/trusty/landscape-client/fix-integration-tests
Merge into: lp:~landscape/charms/trusty/landscape-client/trunk
Diff against target: 532 lines (+127/-238)
15 files modified
.bzrignore (+2/-0)
TESTING (+17/-5)
config.yaml (+16/-0)
hooks/ceph.py (+1/-1)
hooks/install.py (+0/-1)
metadata.yaml (+1/-0)
tests/00-setup (+10/-0)
tests/001_install.test (+0/-95)
tests/10-deploy-register.py (+53/-0)
tests/Makefile (+0/-8)
tests/bundles.yaml (+20/-0)
tests/lib/test-config.yaml (+0/-8)
tests/lib/test-helpers.sh (+0/-114)
tests/test.sh (+0/-6)
tests/test.yaml (+7/-0)
To merge this branch: bzr merge lp:~dpb/charms/trusty/landscape-client/fix-integration-tests
Reviewer Review Type Date Requested Status
Chad Smith Approve
Andreas Hasenack Approve
Review via email: mp+243882@code.launchpad.net

Description of the change

Get our integration tests back up to snuff. You can test like:

virtualenv bundletester
source bundletester/bin/activate
pip install bundletester
juju env <where you want to be>
bundletester

FYI -- there is nothing fancy about bundletester, it's just a runner and what ~charmers is moving toward for standardized testing of charms/bundles. You can achieve the same functionality by doing this:

make test
make lint
charm proof
./test/00-*
./test/10-*

FYI 2 -- you can see the results of testing here:

https://ci.lscape.net/view/Landscape%20Client/job/landscape-client-charm-test/

To post a comment you must log in.
53. By David Britton

add python-amulet to dependency list

54. By David Britton

change logic in 00-setup, add amulet to test.yaml (which I don't think is used, but the instructions say to update)

55. By David Britton

allow overriding origin, it was so small, I'm including it.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

A few comments inline. I'm not very fond of using staging as a test bed for this, but right now I don't have a better idea other than deploying lds for real, which is out of scope for this.

review: Approve
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

I wonder, however, if #is won't complain about us temporarily having root on whatever machine or container that is running this. This could be a big nono.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

If we proceed with staging as is, I'd suggest to create another admin there, with very strict permissions (i.e., only to reject computers), and use those credentials in the jenkins cleanup job.

Revision history for this message
David Britton (dpb) wrote :

> If we proceed with staging as is, I'd suggest to create another admin there,
> with very strict permissions (i.e., only to reject computers), and use those
> credentials in the jenkins cleanup job.

This part is done, thanks. Agreed that this is not the best approach (using staging), but other than deploying LDS alongside the client for the integration test (which would make it a much longer and more complicated process), I can't see another good option for actually testing it can register.

As we saw with the recent breakage, registering is the only way to test some of the recent juju-info integration stuff.

Revision history for this message
David Britton (dpb) :
56. By David Britton

andreas[diff]: adding flake8, landscape-common, increasing timeouts

57. By David Britton

andreas[diff]: Added comment about how amulet works with charm:landscape-client

Revision history for this message
Chad Smith (chad.smith) wrote :

+1 on this branch with 2 minor comments.
Also we shouldn't have related the branch to lp:1399314 right? That bug is a landscape-server charm issue.

review: Approve
58. By David Britton

remove mention of bundltester from TESTING.

59. By David Britton

blackboxsw[diff]: explination for env var added to 'TESTING'

60. By David Britton

blackboxsw[diff]: remove useless tail, add s to succes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2014-07-16 08:42:43 +0000
3+++ .bzrignore 2014-12-17 23:25:40 +0000
4@@ -1,1 +1,3 @@
5 bin/
6+.venv
7+hooks/_trial_temp
8
9=== modified file 'TESTING'
10--- TESTING 2013-04-29 20:40:39 +0000
11+++ TESTING 2014-12-17 23:25:40 +0000
12@@ -1,5 +1,17 @@
13-Simple end-to-end testing can be performed by:
14-
15- cd tests
16- make build
17- ./test.sh
18+Simple end-to-end testing can be performed by running the files in order:
19+
20+ ./tests/00-*
21+ ./tests/10-*
22+ ...
23+
24+Environment overrides for end-to-end testing:
25+
26+ LANDSCAPE_CLIENT_CHARM_ORIGIN - will override the 'origin' juju config
27+
28+Also other tests are available and should pass:
29+
30+ make lint
31+ make test
32+ charm proof
33+
34+Enjoy!
35
36=== modified file 'config.yaml'
37--- config.yaml 2014-10-08 09:28:05 +0000
38+++ config.yaml 2014-12-17 23:25:40 +0000
39@@ -14,25 +14,30 @@
40 The directory to store data files in (default:
41 '/var/lib/landscape/client/').
42 type: string
43+ default:
44 log-dir:
45 description: |
46 The directory to write log files to (default:
47 '/var/log/landscape').
48 type: string
49+ default:
50 log-level:
51 description: |
52 One of debug, info, warning, error or critical.
53 type: string
54+ default:
55 url:
56 description: |
57 The message server URL to connect to. Normally
58 https://fqdn/message-system.
59 type: string
60+ default:
61 ping-url:
62 description: |
63 The ping server URL to perform lightweight exchange initiation with.
64 Normally http://fqdn/ping.
65 type: string
66+ default:
67 ssl-public-key:
68 description: |
69 The CA certificate to verify the server certificate with. This can be
70@@ -40,44 +45,55 @@
71 prefixed with "base64:". This config is only used if the message server
72 URL given above starts with https.
73 type: string
74+ default:
75 account-name:
76 description: |
77 The account this computer belongs to.
78 type: string
79+ default:
80 registration-key:
81 description: |
82 The account-wide key used for registering clients.
83 type: string
84+ default:
85 exchange-interval:
86 description: |
87 The number of seconds between server exchanges.
88 type: int
89+ default:
90 urgent-exchange-interval:
91 description: |
92 The number of seconds between urgent server exchanges.
93 type: int
94+ default:
95 ping-interval:
96 description: |
97 The number of seconds between pings.
98 type: int
99+ default:
100 http-proxy:
101 description: |
102 The URL of the HTTP proxy, if one is needed.
103 type: string
104+ default:
105 https-proxy:
106 description: |
107 The URL of the HTTPS proxy, if one is needed.
108 type: string
109+ default:
110 tags:
111 description: |
112 Comma separated list of tag names to be sent to the server.
113 type: string
114+ default:
115 script-users:
116 description: |
117 A comma-separated list of users to allow scripts to run. To allow
118 scripts to be run by any user, enter: ALL
119 type: string
120+ default:
121 include-manager-plugins:
122 description: |
123 A comma-separated list of manager plugins to load.
124 type: string
125+ default:
126
127=== modified file 'hooks/ceph.py'
128--- hooks/ceph.py 2013-11-19 12:39:44 +0000
129+++ hooks/ceph.py 2014-12-17 23:25:40 +0000
130@@ -1,7 +1,7 @@
131 import os
132 from subprocess import check_output
133
134-from common import LandscapeBroker, chown
135+from common import chown
136
137
138 CEPH_CLIENT_DIR = "ceph-client"
139
140=== modified file 'hooks/install.py'
141--- hooks/install.py 2014-08-28 12:13:31 +0000
142+++ hooks/install.py 2014-12-17 23:25:40 +0000
143@@ -46,7 +46,6 @@
144 data_path])
145
146
147-
148 def build_from_launchpad(url):
149 """The charm will install the code from the passed lp branch.
150 """
151
152=== modified file 'metadata.yaml'
153--- metadata.yaml 2014-01-28 17:53:33 +0000
154+++ metadata.yaml 2014-12-17 23:25:40 +0000
155@@ -7,6 +7,7 @@
156 account. This package provides the Landscape client and requires a
157 Landscape account.
158 subordinate: true
159+tags: [ ops, monitoring ]
160 requires:
161 container:
162 interface: juju-info
163
164=== added file 'tests/00-setup'
165--- tests/00-setup 1970-01-01 00:00:00 +0000
166+++ tests/00-setup 2014-12-17 23:25:40 +0000
167@@ -0,0 +1,10 @@
168+#!/bin/bash -xe
169+
170+# Check if amulet is installed before adding repository and updating apt-get.
171+if ! dpkg -s amulet; then
172+ sudo add-apt-repository -y ppa:juju/stable
173+ sudo apt-get update
174+ sudo apt-get install -y amulet python-flake8 landscape-common
175+fi
176+
177+# Install any additional python packages or software here.
178
179=== removed file 'tests/001_install.test'
180--- tests/001_install.test 2013-03-06 21:29:16 +0000
181+++ tests/001_install.test 1970-01-01 00:00:00 +0000
182@@ -1,95 +0,0 @@
183-#!/bin/bash -eu
184-
185-source lib/test-helpers.sh
186-
187-test_setup() {
188- echo "INFO: Setup Test Environment"
189- juju deploy ubuntu
190- juju deploy --repository . local:landscape-client
191- juju add-relation ubuntu landscape-client
192-}
193-
194-teardown() {
195- echo "INFO: Starting Teardown"
196- juju destroy-service ubuntu || /bin/true
197- juju destroy-service landscape-client || /bin/true
198-}
199-
200-assert_command_on_unit() {
201- # Assert the command succeeds on the unit
202- # $1 = unit to contact
203- # $2 = command
204- if ! juju ssh $1 "$2"; then
205- error "CMD: $2 failed in $(diagnose)"
206- exit 1
207- fi
208-}
209-
210-run_command_on_unit() {
211- juju ssh $1 "$2"
212-}
213-
214-assert_config() {
215- # $1 = config
216- # $2 and on = list of strings to run through egrep
217- config=$1
218- shift
219- while [ $# -gt 0 ]; do
220- if ! echo "$config" | egrep "$1"; then
221- error "Config incorrect or missing: $1\n$(diagnose)"
222- exit 1
223- fi
224- shift
225- done
226-}
227-
228-
229-start-test "landscape-client add relation verify deploy"
230-
231-teardown
232-test_setup
233-
234-# Ensure ubuntu started, and landscape-client is related without error
235-jitsu watch --failfast \
236- ubuntu --state=started -r "ubuntu landscape-client" \
237- landscape-client --state=started
238-
239-
240-# Ensure all ubuntu service units look as expected (unregistered)
241-for i in $(jitsu get-service-info ubuntu public-address); do
242- unit=$(echo $i | cut -d: -f1)
243- host=$(echo $i | cut -d: -f2)
244- assert_command_on_unit $unit "ps -ef | grep -v /usr/bin/landscape-client"
245- assert_command_on_unit $unit "test -e /etc/landscape/client.conf"
246- assert_command_on_unit $unit "sudo cat /etc/landscape/client.conf"
247- assert_command_on_unit $unit "sudo grep computer_title /etc/landscape/client.conf | grep $unit"
248-done
249-
250-# Set appropriate config for testing
251-juju set --config lib/test-config.yaml landscape-client
252-
253-# We expect error since we aren't actually going to register the client
254-jitsu watch \
255- landscape-client --state=configure-error
256-
257-# Ensure all ubuntu service units look as expected (registration-attempt)
258-for i in $(jitsu get-service-info ubuntu public-address); do
259- unit=$(echo $i | cut -d: -f1)
260- host=$(echo $i | cut -d: -f2)
261- assert_command_on_unit $unit "ps -ef | grep -v /usr/bin/landscape-client"
262- assert_command_on_unit $unit "test -e /etc/landscape/client.conf"
263- config=$(run_command_on_unit $unit "sudo cat /etc/landscape/client.conf")
264- assert_config "$config" \
265- "ping_url = http://foo.example.com/ping" \
266- "data_path = /var/lib/landscape/client" \
267- "computer_title = $unit" \
268- "tags = foo,bar,baz" \
269- "registration_password = foo-registration-key" \
270- "url = https://foo.example.com/message-system" \
271- "include_manager_plugins = ScriptExecution" \
272- "script_users = ALL" \
273- "registration_key = foo-registration-key" \
274- "account_name = foo-account-name"
275-done
276-
277-end-test "Deployed Successfully"
278
279=== added file 'tests/10-deploy-register.py'
280--- tests/10-deploy-register.py 1970-01-01 00:00:00 +0000
281+++ tests/10-deploy-register.py 2014-12-17 23:25:40 +0000
282@@ -0,0 +1,53 @@
283+#!/usr/bin/env python3
284+
285+# This amulet test deploys the bundles.yaml file in this directory.
286+
287+import os
288+import unittest
289+import yaml
290+import amulet
291+import time
292+
293+seconds_to_wait = 1200
294+
295+
296+class BundleTest(unittest.TestCase):
297+ """Create a class for testing the charm in the unit test framework."""
298+ @classmethod
299+ def setUpClass(cls):
300+ """Set up an amulet deployment using the bundle."""
301+ origin = os.environ.get('LANDSCAPE_CLIENT_CHARM_ORIGIN', None)
302+ d = amulet.Deployment()
303+ bundle_path = os.path.join(os.path.dirname(__file__), 'bundles.yaml')
304+ with open(bundle_path, 'r') as bundle_file:
305+ contents = yaml.safe_load(bundle_file)
306+ d.load(contents)
307+ if origin is not None:
308+ d.configure("landscape-client", {"origin": origin})
309+ d.setup(seconds_to_wait)
310+ d.sentry.wait(seconds_to_wait)
311+ cls.d = d
312+
313+ def test_deployed(self):
314+ """Test to see if the bundle deployed successfully."""
315+ self.assertTrue(self.d.deployed)
316+
317+ def test_wait_for_success_in_log(self):
318+ """landscape-client should successfully register."""
319+ logfile = "/var/log/juju/unit-landscape-client*.log"
320+ grep = "grep 'System successfully registered'"
321+ # Only principal units are addressable in this way.
322+ for i in range(20):
323+ result = self.d.sentry.unit['ubuntu/0'].run(
324+ "%s %s" % (grep, logfile))
325+ if result[1] != 0:
326+ time.sleep(10)
327+ else:
328+ # success, fall through
329+ break
330+ else:
331+ raise AssertionError("Could not verify registration of the client")
332+
333+
334+if __name__ == '__main__':
335+ unittest.main()
336
337=== removed file 'tests/Makefile'
338--- tests/Makefile 2013-03-06 21:29:16 +0000
339+++ tests/Makefile 1970-01-01 00:00:00 +0000
340@@ -1,8 +0,0 @@
341-build:
342- @mkdir -p precise
343- @test -e precise/landscape-client || ln -sf ../ precise/landscape-client
344- @echo "- Checking juju status, to make sure juju bootstrap has been done"
345- @juju status > /dev/null 2>/dev/null
346-
347-test:
348- ./install-test
349
350=== added file 'tests/bundles.yaml'
351--- tests/bundles.yaml 1970-01-01 00:00:00 +0000
352+++ tests/bundles.yaml 2014-12-17 23:25:40 +0000
353@@ -0,0 +1,20 @@
354+trusty:
355+ series: trusty
356+ services:
357+ landscape-client:
358+ # Amulet will replace this 'charm: landscape-client' with the branch
359+ # that is currently under test on your local system.
360+ charm: landscape-client
361+ options:
362+ account-name: charm-testing
363+ registration-key: testsaregood
364+ tags: testing,foo,tag
365+ ping-url: http://staging.landscape.canonical.com/ping
366+ url: https://staging.landscape.canonical.com/message-system
367+
368+ ubuntu:
369+ charm: cs:trusty/ubuntu
370+ num_units: 1
371+
372+ relations:
373+ - [ "landscape-client", "ubuntu" ]
374
375=== removed directory 'tests/lib'
376=== removed file 'tests/lib/test-config.yaml'
377--- tests/lib/test-config.yaml 2013-03-06 21:29:16 +0000
378+++ tests/lib/test-config.yaml 1970-01-01 00:00:00 +0000
379@@ -1,8 +0,0 @@
380-landscape-client:
381- account-name: foo-account-name
382- registration-key: foo-registration-key
383- tags: foo,bar,baz
384- ping-url: http://foo.example.com/ping
385- url: https://foo.example.com/message-system
386- script-users: ALL
387- include-manager-plugins: ScriptExecution
388
389=== removed file 'tests/lib/test-helpers.sh'
390--- tests/lib/test-helpers.sh 2013-04-26 21:21:18 +0000
391+++ tests/lib/test-helpers.sh 1970-01-01 00:00:00 +0000
392@@ -1,114 +0,0 @@
393-#!/bin/bash
394-
395-set -eu
396-
397-# Test setup
398-readonly TEST_NAME=$0
399-
400-# Test counts. Neither skips or errors are necessarily fatal.
401-SKIPS=0
402-ERRORS=0
403-UNHANDLED=0
404-
405-
406-function info() {
407- echo "INFO: $@"
408-}
409-
410-function ok() {
411- echo "PASS: $@"
412-}
413-
414-function skip() {
415- echo "SKIP: $@"
416- (( SKIPS +=1 ))
417-}
418-
419-function error() {
420- echo "FAIL: $@"
421- (( ERRORS += 1 ))
422-}
423-
424-
425-function start-test() {
426- readonly DATADIR=$(mktemp -d --tmpdir "${TEST_NAME}.XXXXXXX")
427- info "Executing ${TEST_NAME} with results in $DATADIR: $1"
428- setup
429- trap trapped-teardown EXIT TERM INT
430-}
431-
432-function setup() {
433- # Empty, override in actual test as needed
434- true
435-}
436-
437-
438-function end-test() {
439- info "Completed test $TEST_NAME"
440- trap - EXIT
441- test-teardown
442-}
443-
444-
445-function teardown() {
446- # Empty, override in actual test as needed
447- true
448-}
449-
450-
451-function test-teardown() {
452- teardown
453-
454- if [[ "$ERRORS" -gt 0 ]] ; then
455- TEST_RESULT=1
456- elif [[ "$SKIPS" -gt 0 ]] ; then
457- TEST_RESULT=100
458- touch $DATADIR/passed
459- else
460- TEST_RESULT=0
461- touch $DATADIR/passed
462- fi
463-
464- if [ -n "$DATADIR" ] ; then
465- if [ -f $DATADIR/passed ]; then
466- info "Passed test results for ${TEST_NAME} in ${DATADIR}, skips=${SKIPS}"
467- # rm -r $DATADIR
468- else
469- info "Failed test results for ${TEST_NAME} in ${DATADIR}, errors=${ERRORS}, skips=${SKIPS}"
470- if [ -f $DATADIR/wget.log ] ; then
471- info "BEGIN wget.log"
472- cat $DATADIR/wget.log
473- info "END wget.log"
474- fi
475- fi
476- fi
477- exit $TEST_RESULT
478-}
479-
480-
481-function diagnose() {
482- # Unpack the caller info to get some useful diagnostics for
483- # tracing any assertion issues
484- local data=( $(caller 1) )
485- local lineno=${data[0]}
486- local function_name=${data[1]}
487- local script_name=${data[2]}
488- echo "function $function_name at line $lineno ($script_name)"
489-}
490-
491-function trapped-teardown() {
492- (( UNHANDLED += 1 ))
493- error "Untrapped error in $(diagnose)"
494- test-teardown
495-}
496-
497-function assert() {
498- # The assert function takes two args, such as:
499- # assert "what we are asserting" "non empty result passes"
500- # If the second arg is empty or undefined, the assertion fails
501- if [[ "$#" -lt 2 || -z "$2" ]] ; then
502- error "$1, assertion failed in $(diagnose)"
503- else
504- ok "$1"
505- fi
506-}
507
508=== removed directory 'tests/precise'
509=== removed symlink 'tests/precise/landscape-client'
510=== target was u'../..'
511=== removed file 'tests/test.sh'
512--- tests/test.sh 2013-04-26 21:24:37 +0000
513+++ tests/test.sh 1970-01-01 00:00:00 +0000
514@@ -1,6 +0,0 @@
515-#!/bin/bash -e
516-
517-DIR="$( cd "$( dirname "$0" )" && pwd )"
518-cd $DIR
519-
520-run-parts -v --exit-on-error --regex '^.*\.test$' .
521
522=== added file 'tests/test.yaml'
523--- tests/test.yaml 1970-01-01 00:00:00 +0000
524+++ tests/test.yaml 2014-12-17 23:25:40 +0000
525@@ -0,0 +1,7 @@
526+packages:
527+ - python-psutil
528+ - amulet
529+ - python3-amulet
530+ - python-amulet
531+ - landscape-common
532+ - python-flake8

Subscribers

People subscribed via source and target branches

to all changes: