Merge lp:~bac/charms/oneiric/buildbot-slave/dynamic-relationship into lp:~yellow/charms/oneiric/buildbot-slave/trunk
- Oneiric (11.10)
- dynamic-relationship
- Merge into trunk
Proposed by
Brad Crittenden
Status: | Merged |
---|---|
Merged at revision: | 4 |
Proposed branch: | lp:~bac/charms/oneiric/buildbot-slave/dynamic-relationship |
Merge into: | lp:~yellow/charms/oneiric/buildbot-slave/trunk |
Diff against target: |
718 lines (+496/-80) 17 files modified
.bzrignore (+3/-0) config.setuplxc.yaml (+8/-0) config.yaml (+38/-12) copyright (+17/-0) hooks/buildbot-relation-changed (+43/-26) hooks/buildbot-relation-joined (+28/-0) hooks/config-changed (+0/-2) hooks/install (+91/-27) hooks/start (+0/-5) hooks/stop (+0/-7) hooks/tests.py (+51/-0) revision (+0/-1) tests/100_buildbot-slave.config.test (+72/-0) tests/200_buildbot-slave.test (+58/-0) tests/config.test.yaml (+6/-0) tests/get-unit-info (+50/-0) tests/open-port.py (+31/-0) |
To merge this branch: | bzr merge lp:~bac/charms/oneiric/buildbot-slave/dynamic-relationship |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Graham Binns (community) | Approve | ||
Yellow Squad | code | Pending | |
Review via email: mp+91739@code.launchpad.net |
Commit message
Description of the change
Clean up. Merged Francesco's clean up branch.
The files helpers.py and local.py no longer live in the buildbot slave. The One True Version is in the buildbot master. To get access to them, in the buildbot-
To post a comment you must log in.
- 12. By Brad Crittenden
-
Changes from review. Lots of clean up.
Revision history for this message
Brad Crittenden (bac) wrote : | # |
Changes made and pushed. Graham if you could do the merge to trunk that would be swell.
Turns out nothing in the test directory was actually using that helpers.py file, so removing it was a no brainer.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2012-02-07 12:39:12 +0000 |
4 | @@ -0,0 +1,3 @@ |
5 | +revision |
6 | +hooks/helpers.py |
7 | +hooks/local.py |
8 | |
9 | === added file 'config.setuplxc.yaml' |
10 | --- config.setuplxc.yaml 1970-01-01 00:00:00 +0000 |
11 | +++ config.setuplxc.yaml 2012-02-07 12:39:12 +0000 |
12 | @@ -0,0 +1,8 @@ |
13 | +buildbot-slave: |
14 | + builders: lucid_lp,lucid_db_lp |
15 | + script-retrieval-method: bzr_cat |
16 | + script-url: "http://bazaar.launchpad.net/~gmb/launchpad/neuter-setuplxc/utilities/setuplxc.py" |
17 | + script-path: setuplxc.py |
18 | + script-args: "-u launchpad-pqm -e launchpad-pqm@canonical.com -f 'Launchpad PQM' /home/launchpad-pqm/launchpad/" |
19 | + extra-repository: deb http://us.archive.ubuntu.com/ubuntu/ lucid main universe |
20 | + buildbot-pkg: buildbot/lucid |
21 | |
22 | === modified file 'config.yaml' |
23 | --- config.yaml 2012-01-30 19:09:50 +0000 |
24 | +++ config.yaml 2012-02-07 12:39:12 +0000 |
25 | @@ -1,17 +1,43 @@ |
26 | options: |
27 | + script-retrieval-method: |
28 | + description: | |
29 | + How the script is retrieved. You can use bzr, brz_cat, git, |
30 | + mercurial or wget. |
31 | + type: string |
32 | + default: bzr |
33 | + script-url: |
34 | + description: | |
35 | + The url where this script lives. |
36 | + type: string |
37 | + script-path: |
38 | + description: | |
39 | + The path of the script that will be executed. |
40 | + type: string |
41 | + script-args: |
42 | + description: | |
43 | + The script arguments. |
44 | + type: string |
45 | + builders: |
46 | + description: | |
47 | + The builders that this slave should be a part of. Builders must be |
48 | + comma-separated. |
49 | + type: string |
50 | + buildbot-pkg: |
51 | + description: | |
52 | + The package name, possibly with versioning information, to be |
53 | + installed for buildbot. Example values are 'buildbot', |
54 | + 'buildbot/lucid', or 'buildbot=0.7.9'. |
55 | + type: string |
56 | + default: buildbot |
57 | + extra-repository: |
58 | + description: | |
59 | + The full line to be inserted into an apt sources.list for a repository. |
60 | + If called multiple times the new repository will be added but |
61 | + ones added previously will not be removed. An example would be: |
62 | + deb http://us.archive.ubuntu.com/ubuntu/ lucid main universe |
63 | + type: string |
64 | installdir: |
65 | description: | |
66 | The directory where the Buildbot slave will be installed. |
67 | type: string |
68 | - default: /tmp/buildbot |
69 | - name: |
70 | - description: | |
71 | - The name of this slave. |
72 | - type: string |
73 | - default: example-slave |
74 | - passwd: |
75 | - description: | |
76 | - The password of this slave. |
77 | - type: string |
78 | - default: pass |
79 | - |
80 | + default: /tmp/buildslave |
81 | |
82 | === added file 'copyright' |
83 | --- copyright 1970-01-01 00:00:00 +0000 |
84 | +++ copyright 2012-02-07 12:39:12 +0000 |
85 | @@ -0,0 +1,17 @@ |
86 | +Format: http://dep.debian.net/deps/dep5/ |
87 | + |
88 | +Files: * |
89 | +Copyright: Copyright 2012, Canonical Ltd., All Rights Reserved. |
90 | +License: GPL-3 |
91 | + This program is free software: you can redistribute it and/or modify |
92 | + it under the terms of the GNU General Public License as published by |
93 | + the Free Software Foundation, either version 3 of the License, or |
94 | + (at your option) any later version. |
95 | + . |
96 | + This program is distributed in the hope that it will be useful, |
97 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
98 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
99 | + GNU General Public License for more details. |
100 | + . |
101 | + You should have received a copy of the GNU General Public License |
102 | + along with this program. If not, see <http://www.gnu.org/licenses/>. |
103 | |
104 | === modified file 'hooks/buildbot-relation-changed' |
105 | --- hooks/buildbot-relation-changed 2012-01-31 01:50:27 +0000 |
106 | +++ hooks/buildbot-relation-changed 2012-02-07 12:39:12 +0000 |
107 | @@ -1,26 +1,43 @@ |
108 | -#!/bin/bash |
109 | -# This must be renamed to the name of the relation. The goal here is to |
110 | -# affect any change needed by relationships being formed, modified, or broken |
111 | -# This script should be idempotent. |
112 | -juju-log $JUJU_REMOTE_UNIT modified its settings |
113 | - |
114 | -BUILDBOT_DIR=`config-get installdir` |
115 | -NAME=`config-get name` |
116 | -PASSWD=`config-get passwd` |
117 | -HOST=`relation-get private-address` |
118 | - |
119 | -juju-log "--> stop" |
120 | -# The exit code is 0 even if the buildslave was not running. |
121 | -buildslave stop $BUILDBOT_DIR |
122 | -juju-log "<-- stop" |
123 | - |
124 | -juju-log "--> create .tac" |
125 | -if [ -e $BUILDBOT_DIR/buildbot.tac ]; then |
126 | - rm $BUILDBOT_DIR/buildbot.tac |
127 | -fi |
128 | -buildslave create-slave $BUILDBOT_DIR $HOST $NAME $PASSWD |
129 | -juju-log "<-- create .tac" |
130 | - |
131 | -juju-log "--> start" |
132 | -buildslave start $BUILDBOT_DIR |
133 | -juju-log "<-- start" |
134 | +#!/usr/bin/env python |
135 | + |
136 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
137 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
138 | + |
139 | +import sys |
140 | + |
141 | +from helpers import ( |
142 | + get_config, |
143 | + log, |
144 | + relation_get, |
145 | + ) |
146 | +from local import ( |
147 | + buildslave_start, |
148 | + buildslave_stop, |
149 | + create_slave, |
150 | + ) |
151 | + |
152 | + |
153 | +def restart_buildslave(name, passwd, host, buildbot_dir): |
154 | + log('Stopping buildbot slave.') |
155 | + buildslave_stop() |
156 | + log('Creating buildbot slave: {}@{} (passwd={}).'.format( |
157 | + name, host, passwd)) |
158 | + create_slave(name, passwd, host=host, buildbot_dir=buildbot_dir) |
159 | + log('Starting buildbot slave.') |
160 | + return buildslave_start() |
161 | + |
162 | + |
163 | +def main(): |
164 | + name = relation_get('name') |
165 | + passwd = relation_get('passwd') |
166 | + if name and passwd: |
167 | + # We heard back from the master and we are ready to start. |
168 | + config = get_config() |
169 | + buildbot_dir = config.get('installdir') |
170 | + host = relation_get('private-address') |
171 | + sys.exit(restart_buildslave(name, passwd, host, buildbot_dir)) |
172 | + |
173 | + |
174 | +if __name__ == '__main__': |
175 | + log('BUILDBOT-RELATION-CHANGED HOOK:') |
176 | + main() |
177 | |
178 | === added file 'hooks/buildbot-relation-joined' |
179 | --- hooks/buildbot-relation-joined 1970-01-01 00:00:00 +0000 |
180 | +++ hooks/buildbot-relation-joined 2012-02-07 12:39:12 +0000 |
181 | @@ -0,0 +1,28 @@ |
182 | +#!/usr/bin/env python |
183 | + |
184 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
185 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
186 | + |
187 | +from helpers import ( |
188 | + get_config, |
189 | + log, |
190 | + relation_set, |
191 | + ) |
192 | + |
193 | + |
194 | +def send_builders(builders): |
195 | + log('Sending builders to the master: {}'.format(builders)) |
196 | + relation_set(builders=builders) |
197 | + |
198 | + |
199 | +def main(): |
200 | + config = get_config() |
201 | + builders = config.get('builders') |
202 | + if builders: |
203 | + # This is the first step of the handshake. |
204 | + send_builders(builders) |
205 | + |
206 | + |
207 | +if __name__ == '__main__': |
208 | + log('BUILDBOT-RELATION-JOINED HOOK:') |
209 | + main() |
210 | |
211 | === added file 'hooks/config-changed' |
212 | --- hooks/config-changed 1970-01-01 00:00:00 +0000 |
213 | +++ hooks/config-changed 2012-02-07 12:39:12 +0000 |
214 | @@ -0,0 +1,47 @@ |
215 | +#!/usr/bin/env python |
216 | + |
217 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
218 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
219 | + |
220 | +from helpers import ( |
221 | + apt_get_install, |
222 | + command, |
223 | + DictDiffer, |
224 | + get_config, |
225 | + install_extra_repository, |
226 | + log, |
227 | + ) |
228 | +from local import ( |
229 | + config_json, |
230 | + create_slave, |
231 | + ) |
232 | + |
233 | + |
234 | +def main(): |
235 | + |
236 | + config = get_config() |
237 | + prev_config = config_json.get() |
238 | + |
239 | + diff = DictDiffer(config, prev_config) |
240 | + log("Differences:") |
241 | + log(str(diff)) |
242 | + |
243 | + buildbot_pkg = config.get('buildbot-pkg') |
244 | + extra_repo = config.get('extra-repository') |
245 | + buildbot_dir = config.get('installdir') |
246 | + |
247 | + if extra_repo and 'extra-repository' in diff.added_or_changed: |
248 | + install_extra_repository(extra_repo) |
249 | + |
250 | + if buildbot_pkg and 'buildbot-pkg' not in diff.unchanged: |
251 | + log('Installing ' + buildbot_pkg) |
252 | + apt_get_install(buildbot_pkg) |
253 | + log('Creating initial buildbot slave in ' + buildbot_dir) |
254 | + create_slave('temporary', 'temporary', buildbot_dir=buildbot_dir) |
255 | + |
256 | + config_json.set(config) |
257 | + |
258 | + |
259 | +if __name__ == '__main__': |
260 | + log('CONFIG-CHANGED HOOK:') |
261 | + main() |
262 | |
263 | === removed file 'hooks/config-changed' |
264 | --- hooks/config-changed 2012-01-30 19:09:50 +0000 |
265 | +++ hooks/config-changed 1970-01-01 00:00:00 +0000 |
266 | @@ -1,2 +0,0 @@ |
267 | -#!/bin/bash |
268 | -# Hook for handling config changes. |
269 | |
270 | === modified file 'hooks/install' |
271 | --- hooks/install 2012-01-31 01:50:27 +0000 |
272 | +++ hooks/install 2012-02-07 12:39:12 +0000 |
273 | @@ -1,27 +1,91 @@ |
274 | -#!/bin/bash |
275 | -# Here do anything needed to install the service |
276 | -# i.e. apt-get install -y foo or bzr branch http://myserver/mycode /srv/webroot |
277 | -set -eux # -x for verbose logging to juju debug-log |
278 | - |
279 | -juju-log "--> install packages" |
280 | -BUILDBOT_DIR=`config-get installdir` |
281 | -apt-get install -y buildbot |
282 | -mkdir -p $BUILDBOT_DIR |
283 | -juju-log "<-- install packages" |
284 | - |
285 | -juju-log "--> create slave" |
286 | -NAME=`config-get name` |
287 | -PASSWD=`config-get passwd` |
288 | - |
289 | -# We set HOST to localhost for now because we can't get the actual host |
290 | -# until we're joined to the buildbot-master instance. |
291 | -HOST="localhost" |
292 | - |
293 | -juju-log "buildslave create-slave $BUILDBOT_DIR $HOST $NAME $PASSWD" |
294 | -buildslave create-slave $BUILDBOT_DIR $HOST $NAME $PASSWD |
295 | -juju-log "<-- create slave" |
296 | - |
297 | -# This is where we would set info/admin and info/host. Not sure what |
298 | -# is pertinent, but the default is a bit lame in the juju case. |
299 | - |
300 | -# This is where we would run something like setuplxc. |
301 | +#!/usr/bin/env python |
302 | + |
303 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
304 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
305 | + |
306 | +from helpers import ( |
307 | + apt_get_install, |
308 | + command, |
309 | + get_config, |
310 | + log, |
311 | + run, |
312 | + ) |
313 | +import os |
314 | +import shlex |
315 | +import subprocess |
316 | +import sys |
317 | +import tempfile |
318 | + |
319 | + |
320 | +bzr = command('bzr') |
321 | + |
322 | + |
323 | +def bzr_fetch(source, path): |
324 | + apt_get_install('bzr') |
325 | + target = tempfile.mktemp() |
326 | + bzr('branch', source, target) |
327 | + return os.path.join(target, path) |
328 | + |
329 | + |
330 | +def bzr_cat(source, path): |
331 | + apt_get_install('bzr') |
332 | + content = bzr('--no-plugins', 'cat', source) |
333 | + target = os.path.join('/tmp', path) |
334 | + with open(target, 'w') as f: |
335 | + f.write(content) |
336 | + return target |
337 | + |
338 | + |
339 | +def wget(source, path): |
340 | + target = os.path.join('/tmp', path) |
341 | + command('wget', '-O', target, source) |
342 | + return target |
343 | + |
344 | + |
345 | +def hg_fetch(source, target): |
346 | + apt_get_install('mercurial') |
347 | + target = tempfile.mktemp() |
348 | + command('hg', 'clone', source, target) |
349 | + return os.path.join(target, path) |
350 | + |
351 | + |
352 | +def git_fetch(source, target): |
353 | + apt_get_install('git') |
354 | + target = tempfile.mktemp() |
355 | + command('git', 'clone', source, target) |
356 | + return os.path.join(target, path) |
357 | + |
358 | + |
359 | +METHODS = { |
360 | + 'bzr': bzr_fetch, |
361 | + 'bzr_cat': bzr_cat, |
362 | + 'wget': wget, |
363 | + 'hg': hg_fetch, |
364 | + 'git': git_fetch, |
365 | + } |
366 | + |
367 | + |
368 | +def handle_script(retrieve, url, path, args): |
369 | + log('Retrieving script: {}.'.format(url)) |
370 | + script = retrieve(url, path) |
371 | + log('Changing script mode.') |
372 | + command('chmod', '+x', script) |
373 | + log('Executing script: {}.'.format(script)) |
374 | + return subprocess.call([script] + shlex.split(str(args))) |
375 | + |
376 | + |
377 | +def main(): |
378 | + |
379 | + config = get_config() |
380 | + method = config.get('script-retrieval-method') |
381 | + url = config.get('script-url') |
382 | + path = config.get('script-path') |
383 | + args = config.get('script-args') |
384 | + retrieve = METHODS.get(method) |
385 | + if retrieve and url and path: |
386 | + sys.exit(handle_script(retrieve, url, path, args)) |
387 | + |
388 | + |
389 | +if __name__ == '__main__': |
390 | + log('INSTALL HOOK:') |
391 | + main() |
392 | |
393 | === removed file 'hooks/start' |
394 | --- hooks/start 2012-01-30 19:09:50 +0000 |
395 | +++ hooks/start 1970-01-01 00:00:00 +0000 |
396 | @@ -1,5 +0,0 @@ |
397 | -#!/bin/bash |
398 | -# Here put anything that is needed to start the service. |
399 | -# Note that currently this is run directly after install |
400 | -# i.e. 'service apache2 start' |
401 | - |
402 | |
403 | === removed file 'hooks/stop' |
404 | --- hooks/stop 2012-01-30 19:09:50 +0000 |
405 | +++ hooks/stop 1970-01-01 00:00:00 +0000 |
406 | @@ -1,7 +0,0 @@ |
407 | -#!/bin/bash |
408 | -# This will be run when the service is being torn down, allowing you to disable |
409 | -# it in various ways.. |
410 | -# For example, if your web app uses a text file to signal to the load balancer |
411 | -# that it is live... you could remove it and sleep for a bit to allow the load |
412 | -# balancer to stop sending traffic. |
413 | -# rm /srv/webroot/server-live.txt && sleep 30 |
414 | |
415 | === added file 'hooks/tests.py' |
416 | --- hooks/tests.py 1970-01-01 00:00:00 +0000 |
417 | +++ hooks/tests.py 2012-02-07 12:39:12 +0000 |
418 | @@ -0,0 +1,51 @@ |
419 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
420 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
421 | + |
422 | +from subprocess import CalledProcessError |
423 | +import unittest |
424 | + |
425 | +from helpers import command |
426 | + |
427 | + |
428 | +class TestCommand(unittest.TestCase): |
429 | + |
430 | + def test_simple_command(self): |
431 | + # Creating a simple command (ls) works and running the command |
432 | + # produces a string. |
433 | + ls = command('/bin/ls') |
434 | + self.assertIsInstance(ls(), str) |
435 | + |
436 | + def test_arguments(self): |
437 | + # Arguments can be passed to commands. |
438 | + ls = command('/bin/ls') |
439 | + self.assertIn('Usage:', ls('--help')) |
440 | + |
441 | + def test_missing_executable(self): |
442 | + # If the command does not exist, an OSError (No such file or |
443 | + # directory) is raised. |
444 | + bad = command('this command does not exist') |
445 | + with self.assertRaises(OSError) as info: |
446 | + bad() |
447 | + self.assertEqual(2, info.exception.errno) |
448 | + |
449 | + def test_error(self): |
450 | + # If the command returns a non-zero exit code, an exception is raised. |
451 | + ls = command('/bin/ls') |
452 | + with self.assertRaises(CalledProcessError): |
453 | + ls('--not a valid switch') |
454 | + |
455 | + def test_baked_in_arguments(self): |
456 | + # Arguments can be passed when creating the command as well as when |
457 | + # executing it. |
458 | + ll = command('/bin/ls', '-l') |
459 | + self.assertIn('rw', ll()) # Assumes a file is r/w in the pwd. |
460 | + self.assertIn('Usage:', ll('--help')) |
461 | + |
462 | + def test_quoting(self): |
463 | + # There is no need to quote special shell characters in commands. |
464 | + ls = command('/bin/ls') |
465 | + ls('--help', '>') |
466 | + |
467 | + |
468 | +if __name__ == '__main__': |
469 | + unittest.main() |
470 | |
471 | === removed file 'revision' |
472 | --- revision 2012-01-31 01:50:27 +0000 |
473 | +++ revision 1970-01-01 00:00:00 +0000 |
474 | @@ -1,1 +0,0 @@ |
475 | -19 |
476 | |
477 | === added directory 'tests' |
478 | === added file 'tests/100_buildbot-slave.config.test' |
479 | --- tests/100_buildbot-slave.config.test 1970-01-01 00:00:00 +0000 |
480 | +++ tests/100_buildbot-slave.config.test 2012-02-07 12:39:12 +0000 |
481 | @@ -0,0 +1,72 @@ |
482 | +#!/bin/sh |
483 | + |
484 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
485 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
486 | + |
487 | +set -e |
488 | + |
489 | +teardown() { |
490 | + juju destroy-service buildbot-slave |
491 | + if [ -n "$datadir" ] ; then |
492 | + if [ -f $datadir/passed ]; then |
493 | + rm -r $datadir |
494 | + else |
495 | + echo $datadir preserved |
496 | + fi |
497 | + fi |
498 | +} |
499 | +trap teardown EXIT |
500 | + |
501 | +juju deploy --repository=$PWD/../ local:buildbot-slave |
502 | +juju expose buildbot-slave |
503 | + |
504 | +for try in `seq 1 600` ; do |
505 | + slave_host=`juju status | tests/get-unit-info buildbot-slave public-address` |
506 | + if [ -z "$slave_host" ] ; then |
507 | + sleep 1 |
508 | + else |
509 | + break |
510 | + fi |
511 | +done |
512 | + |
513 | +if [ -z "$slave_host" ] ; then |
514 | + echo ERROR: status timed out |
515 | + exit 1 |
516 | +fi |
517 | + |
518 | +datadir=`mktemp -d ${TMPDIR:-/tmp}/wget.test.XXXXXXX` |
519 | +echo INFO: datadir=$datadir |
520 | + |
521 | +#slave_connected=$( |
522 | +# wget --tries=100 --timeout=6 http://$slave_host:9000 -O - \ |
523 | +# -a $datadir/wget.log | grep -q 'UP!') |
524 | + |
525 | +assert_is_listening() { |
526 | + local port=$1 |
527 | + listening="" |
528 | + for try in `seq 1 10` ; do |
529 | + if ! nc $slave_host $port < /dev/null ; then |
530 | + continue |
531 | + fi |
532 | + listening="yes" |
533 | + break |
534 | + done |
535 | + |
536 | + if [ -z "$listening" ] ; then |
537 | + echo "FAIL: not listening on port $port after 10 retries" |
538 | + return 1 |
539 | + else |
540 | + echo "PASS: listening on port $port" |
541 | + return 0 |
542 | + fi |
543 | +} |
544 | + |
545 | +assert_is_listening 9000 |
546 | + |
547 | +touch $datadir/passed |
548 | + |
549 | +trap - EXIT |
550 | +teardown |
551 | + |
552 | +echo INFO: PASS |
553 | +exit 0 |
554 | |
555 | === added file 'tests/200_buildbot-slave.test' |
556 | --- tests/200_buildbot-slave.test 1970-01-01 00:00:00 +0000 |
557 | +++ tests/200_buildbot-slave.test 2012-02-07 12:39:12 +0000 |
558 | @@ -0,0 +1,58 @@ |
559 | +#!/bin/sh |
560 | + |
561 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
562 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
563 | + |
564 | +set -e |
565 | + |
566 | +teardown() { |
567 | + juju destroy-service buildbot-slave |
568 | + if [ -n "$datadir" ] ; then |
569 | + if [ -f $datadir/passed ]; then |
570 | + rm -r $datadir |
571 | + else |
572 | + echo $datadir preserved |
573 | + fi |
574 | + fi |
575 | +} |
576 | +trap teardown EXIT |
577 | + |
578 | + |
579 | +juju deploy buildbot-master |
580 | +juju deploy buildbot-slave |
581 | +juju add-relation buildbot-slave buildbot-master |
582 | +juju expose buildbot-master |
583 | + |
584 | +for try in `seq 1 600` ; do |
585 | + master_host=`juju status | tests/get-unit-info buildbot-master public-address` |
586 | + if [ -z "$master_host" ] ; then |
587 | + sleep 1 |
588 | + else |
589 | + break |
590 | + fi |
591 | +done |
592 | + |
593 | +if [ -z "$master_host" ] ; then |
594 | + echo ERROR: status timed out |
595 | + exit 1 |
596 | +fi |
597 | + |
598 | +datadir=`mktemp -d ${TMPDIR:-/tmp}/wget.test.XXXXXXX` |
599 | +echo INFO: datadir=$datadir |
600 | + |
601 | +slave_connected=$( |
602 | + wget --tries=100 --timeout=6 http://$master_host:8010/buildslaves -O - \ |
603 | + -a $datadir/wget.log | grep -q 'Idle') |
604 | + |
605 | +if [ -z $slave_connected ]; then |
606 | + echo "ERROR: The slave is not connected after 600 seconds." |
607 | + exit 1 |
608 | +fi |
609 | + |
610 | +touch $datadir/passed |
611 | + |
612 | +trap - EXIT |
613 | +teardown |
614 | + |
615 | +echo INFO: PASS |
616 | +exit 0 |
617 | |
618 | === added file 'tests/config.test.yaml' |
619 | --- tests/config.test.yaml 1970-01-01 00:00:00 +0000 |
620 | +++ tests/config.test.yaml 2012-02-07 12:39:12 +0000 |
621 | @@ -0,0 +1,6 @@ |
622 | +buildbot-slave: |
623 | + installdir: /tmp/buildbot |
624 | + name: example-slave |
625 | + passwd: pass |
626 | + script-retrieval-method: bzr |
627 | + script-url: "http://bazaar.launchpad.net/~gmb/charms/oneiric/buildbot-slave/look-we-have-tests/tests/open-port.py" |
628 | |
629 | === added file 'tests/get-unit-info' |
630 | --- tests/get-unit-info 1970-01-01 00:00:00 +0000 |
631 | +++ tests/get-unit-info 2012-02-07 12:39:12 +0000 |
632 | @@ -0,0 +1,50 @@ |
633 | +#!/usr/bin/python |
634 | + |
635 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
636 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
637 | + |
638 | +# machines: |
639 | +# 0: {dns-name: ec2-50-17-84-127.compute-1.amazonaws.com, instance-id: i-8c5c3fec} |
640 | +# 1: {dns-name: ec2-184-73-102-113.compute-1.amazonaws.com, instance-id: i-14a2c174} |
641 | +# 2: {dns-name: ec2-75-101-184-93.compute-1.amazonaws.com, instance-id: i-e0a2c180} |
642 | +# services: |
643 | +# mysql: |
644 | +# charm: local:mysql-11 |
645 | +# relations: {db: wordpress} |
646 | +# units: |
647 | +# mysql/0: |
648 | +# machine: 2 |
649 | +# relations: |
650 | +# db: {state: up} |
651 | +# state: started |
652 | +# wordpress: |
653 | +# charm: local:wordpress-31 |
654 | +# exposed: true |
655 | +# relations: {db: mysql} |
656 | +# units: |
657 | +# wordpress/0: |
658 | +# machine: 1 |
659 | +# open-ports: [] |
660 | +# relations: {} |
661 | +# state: null |
662 | + |
663 | +import yaml |
664 | +import sys |
665 | +from subprocess import Popen, PIPE |
666 | + |
667 | + |
668 | +def main(): |
669 | + d = yaml.safe_load(Popen(['juju','status'],stdout=PIPE).stdout) |
670 | + srv = d.get("services", {}).get(sys.argv[1]) |
671 | + if srv is None: |
672 | + return |
673 | + units = srv.get("units", {}) |
674 | + if units is None: |
675 | + return |
676 | + item = units.items()[0][1].get(sys.argv[2]) |
677 | + if item is None: |
678 | + return |
679 | + print item |
680 | + |
681 | +if __name__ == "__main__": |
682 | + main() |
683 | |
684 | === added file 'tests/open-port.py' |
685 | --- tests/open-port.py 1970-01-01 00:00:00 +0000 |
686 | +++ tests/open-port.py 2012-02-07 12:39:12 +0000 |
687 | @@ -0,0 +1,31 @@ |
688 | +#!/usr/bin/env python |
689 | + |
690 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
691 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
692 | + |
693 | +# A little python script to open a port on the buildslave so that we can |
694 | +# test that it's actually deployed successfully. |
695 | + |
696 | +import subprocess |
697 | +import SimpleHTTPServer |
698 | +import SocketServer |
699 | + |
700 | +PORT = 9000 |
701 | + |
702 | +simple_html = """ |
703 | +<html> |
704 | + <head> |
705 | + <title>Here's some HTML</title> |
706 | + </head> |
707 | + <body><p>The slave is UP!</p></body> |
708 | +</html> |
709 | +""" |
710 | + |
711 | +with open('/tmp/index.html', 'w') as index_file: |
712 | + index_file.write(simple_html) |
713 | + |
714 | +subprocess.call(['open-port', '9000/TCP']) |
715 | +Handler = SimpleHTTPServer.SimpleHTTPRequestHandler |
716 | +httpd = SocketServer.TCPServer(("", PORT), Handler) |
717 | +#httpd.serve_forever() |
718 | +print "HERE I AM!!!" |
Thanks for putting this MP together Brad. Here's my comments / TODO list. I figure we should merge lp:~bac/charms/oneiric/buildbot-slave/dynamic-relationship into ~yellow/.../trunk and then fix these things up, so I'm going to mark the MP approved.
TODO list (slave):
[1] Pickle stuff needs removing from hooks/config- changed.
[2]
243 + if buildbot_pkg and 'buildbot-pkg' not in diff.unchanged:
I really hate this double-neg pattern. We should use:
if buildbot_pkg and 'buildbot-pkg' in diff.added_ or_changed:
...
(unchanged is a micro-optimisation, AIUI, but added_or_changed is so much clearer to me).
[3] Copyright info still needs to be added to every file after the #!.
[4]
IGNORE THIS POINT. I realised it was nonsense, but can't be bothered to renumber ;).
[5]
681 +from subprocess import CalledProcessError
682 +
Nit: imports not in alphabetical order.
[6]
309 + get('installdir ')
310 +log('INSTALL HOOK:')
311 +config = get_config()
312 +
313 +bzr_ = command('bzr')
314 +
315 +buildbot_dir = config.
316 +
These should go in the __name__ == '__main__' block or in main().
`config` should be passed as a parameter to functions as necessary.
[7]
317 +def bzr(source, path): install( 'bzr')
318 + apt_get_
319 + target = tempfile.mktemp()
320 + bzr('branch', source, target)
Line 320 is going to blow up. We also have a bzr_ command defined at
line 313 for actual bzr commands. We should rename bzr() to bzr_fetch()
or something (and rename all the other fetch functions, too, come to
that).
[8]
416 +class testCommand( unittest. TestCase) :
Should be TestCommand.
[9]
424 + def testArguments( self):
This may be a silly time to raise coding standards complaints, but we
seem to be sticking with PEP8 most places. Why not do it here too,
rather than using LP/Zope's hybrid standards? You just know that some
non-LP developer is going to complain about this somewhere down the
line...
[10]
459 === removed file 'revision'
Will Juju let us get away with this?
[11]
466 === added file 'tests/ 100_buildbot- slave.config. test' 200_buildbot- slave.test'
540 === added file 'tests/
(We knew this already but) these need to be Pythonised. Also, last we
checked, they don't actually work, let alone fail.
[12]
662 === added file 'tests/helpers.py'
We probably need a better way of getting necessary helpers into tests/
than just having a copy of helpers.py there. Another symlink mebbe?