Merge lp:~hloeung/jenkins-agent-charm/reactive-rewrite into lp:jenkins-agent-charm
- reactive-rewrite
- Merge into trunk
Proposed by
Haw Loeung
Status: | Merged |
---|---|
Approved by: | Tom Haddon |
Approved revision: | 51 |
Merged at revision: | 22 |
Proposed branch: | lp:~hloeung/jenkins-agent-charm/reactive-rewrite |
Merge into: | lp:jenkins-agent-charm |
Diff against target: |
1152 lines (+673/-311) 25 files modified
.bzrignore (+11/-0) Makefile (+30/-0) README.md (+5/-0) files/jenkins-slave-sudoers (+5/-0) hooks/configure-slave (+0/-27) hooks/install.d/add_sudoers (+0/-18) hooks/install.d/canonical_ci_utils.py (+0/-91) hooks/nrpe-external-master-relation-changed (+0/-7) hooks/slave-relation-changed (+0/-19) hooks/slave-relation-departed (+0/-3) hooks/slave-relation-joined (+0/-20) hooks/start (+0/-3) hooks/stop (+0/-3) layer.yaml (+5/-0) metadata.yaml (+5/-1) reactive/jenkins_slave.py (+228/-118) requirements.txt (+1/-0) revision (+0/-1) templates/jenkins-slave-default (+8/-0) tests/functional/requirements.txt (+6/-0) tests/functional/test_jenkins_slave.py (+50/-0) tests/unit/files/jenkins-slave-default (+59/-0) tests/unit/requirements.txt (+5/-0) tests/unit/test_jenkins_slave.py (+218/-0) tox.ini (+37/-0) |
To merge this branch: | bzr merge lp:~hloeung/jenkins-agent-charm/reactive-rewrite |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tom Haddon | Approve | ||
Haw Loeung | Needs Resubmitting | ||
Canonical IS Reviewers | Pending | ||
Review via email: mp+363649@code.launchpad.net |
Commit message
Charm rewrite using Python and the Reactive framework
Description of the change
To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Revision history for this message
Tom Haddon (mthaddon) wrote : | # |
Some comments and questions inline.
review:
Needs Fixing
Revision history for this message
Tom Haddon (mthaddon) wrote : | # |
Missed one other thing as well.
Revision history for this message
Tom Haddon (mthaddon) wrote : | # |
Some comments inline with suggestions for testing.
Revision history for this message
Tom Haddon (mthaddon) wrote : | # |
Er, we we obviously *do* want the max-complexity check
Revision history for this message
Tom Haddon (mthaddon) wrote : | # |
A few comments inline
Revision history for this message
Haw Loeung (hloeung) : | # |
review:
Needs Resubmitting
- 50. By Haw Loeung
-
Added basic functional test
- 51. By Haw Loeung
-
Fixed to use the module itself instead of sys.modules
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Change successfully merged at revision 22
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 2019-03-01 05:39:53 +0000 |
4 | @@ -0,0 +1,11 @@ |
5 | +*.pyc |
6 | +*.swp |
7 | +*~ |
8 | +.coverage |
9 | +.pytest_cache/ |
10 | +.tox/ |
11 | +.unit-state.db |
12 | +__pycache__/ |
13 | +builds/ |
14 | +deps/ |
15 | +revision |
16 | |
17 | === added file 'Makefile' |
18 | --- Makefile 1970-01-01 00:00:00 +0000 |
19 | +++ Makefile 2019-03-01 05:39:53 +0000 |
20 | @@ -0,0 +1,30 @@ |
21 | +help: |
22 | + @echo "This project supports the following targets" |
23 | + @echo "" |
24 | + @echo " make help - show this text" |
25 | + @echo " make lint - run flake8" |
26 | + @echo " make test - run the functional test and unittests" |
27 | + @echo " make unittest - run the the unittest" |
28 | + @echo " make functionaltest - run the functional tests" |
29 | + @echo " make clean - remove unneeded files" |
30 | + @echo "" |
31 | + |
32 | +lint: |
33 | + @echo "Running flake8" |
34 | + @tox -e lint |
35 | + |
36 | +test: unittest functionaltest lint |
37 | + |
38 | +unittest: |
39 | + @tox -e unit |
40 | + |
41 | +functionaltest: |
42 | + @tox -e functional |
43 | + |
44 | +clean: |
45 | + @echo "Cleaning files" |
46 | + @if [ -d ./.tox ] ; then rm -r ./.tox ; fi |
47 | + @if [ -d ./.pytest_cache ] ; then rm -r ./.pytest_cache ; fi |
48 | + |
49 | +# The targets below don't depend on a file |
50 | +.PHONY: lint test unittest functionaltest clean help |
51 | |
52 | === modified file 'README.md' |
53 | --- README.md 2014-05-15 16:06:29 +0000 |
54 | +++ README.md 2019-03-01 05:39:53 +0000 |
55 | @@ -21,3 +21,8 @@ |
56 | juju deploy --to <special-mabine-number> jenkins-slave ppc-slave |
57 | |
58 | See the Jenkins charm for more details. |
59 | + |
60 | + |
61 | +# Notes |
62 | + |
63 | +We can't use interface:jenkins-slave yet as it's not fully implemented. |
64 | |
65 | === added directory 'actions' |
66 | === added file 'files/jenkins-slave-sudoers' |
67 | --- files/jenkins-slave-sudoers 1970-01-01 00:00:00 +0000 |
68 | +++ files/jenkins-slave-sudoers 2019-03-01 05:39:53 +0000 |
69 | @@ -0,0 +1,5 @@ |
70 | +# Created automatically during charm installation |
71 | +# Any manual changes to it will be lost |
72 | + |
73 | +# User rules for jenkins |
74 | +jenkins ALL=(ALL) NOPASSWD: ALL |
75 | |
76 | === removed symlink 'hooks/config-changed' |
77 | === target was u'install' |
78 | === removed file 'hooks/configure-slave' |
79 | --- hooks/configure-slave 2016-06-03 02:54:52 +0000 |
80 | +++ hooks/configure-slave 1970-01-01 00:00:00 +0000 |
81 | @@ -1,27 +0,0 @@ |
82 | -#!/bin/bash |
83 | - |
84 | -set -e |
85 | - |
86 | -# Grab the jenkins master url as a passed in parameter |
87 | -url="$1" |
88 | - |
89 | -# Set the slave hostname to match the juju unit |
90 | -slavehost="$(echo ${JUJU_UNIT_NAME} | sed s,/,-,)" |
91 | - |
92 | -# Set the slave and url fields |
93 | -juju-log "Configuring jenkins-slave with ${url}..." |
94 | -sed -i -e "s!^JENKINS_HOSTNAME.*!JENKINS_HOSTNAME=${slavehost}!" \ |
95 | - -e "s!^#*JENKINS_URL.*!JENKINS_URL=${url}!" \ |
96 | - /etc/default/jenkins-slave |
97 | - |
98 | -# Startup the jenkins-slave service |
99 | -# This is called in the install, config-changed and upgrade-charm paths |
100 | -# It needs to be tolerant of a running or stopped jenkins-slave |
101 | -status="$(service jenkins-slave status || true)" |
102 | -if echo "${status}" | egrep -q "stop|inactive"; then |
103 | - juju-log "Starting jenkins-slave..." |
104 | - service jenkins-slave start |
105 | -else |
106 | - juju-log "Restarting jenkins-slave..." |
107 | - service jenkins-slave restart |
108 | -fi |
109 | |
110 | === removed symlink 'hooks/install.d/03_nrpe_relation_changed' |
111 | === target was u'canonical_ci_utils.py' |
112 | === removed file 'hooks/install.d/add_sudoers' |
113 | --- hooks/install.d/add_sudoers 2015-08-13 18:04:16 +0000 |
114 | +++ hooks/install.d/add_sudoers 1970-01-01 00:00:00 +0000 |
115 | @@ -1,18 +0,0 @@ |
116 | -#!/bin/bash |
117 | - |
118 | -set -eu |
119 | - |
120 | -temp_sudoers="$(mktemp /tmp/jenkins.XXXXXX)" |
121 | - |
122 | -cat > "$temp_sudoers" << EOF |
123 | -# Created automatically during charm installation |
124 | -# Any manual changes to it will be lost |
125 | - |
126 | -# User rules for jenkins |
127 | -jenkins ALL=(ALL) NOPASSWD: ALL |
128 | -EOF |
129 | - |
130 | -visudo -c -f "$temp_sudoers" |
131 | -install -m 440 "$temp_sudoers" /etc/sudoers.d/jenkins |
132 | -rm "$temp_sudoers" |
133 | -visudo -c |
134 | |
135 | === removed file 'hooks/install.d/canonical_ci_utils.py' |
136 | --- hooks/install.d/canonical_ci_utils.py 2015-12-03 10:40:55 +0000 |
137 | +++ hooks/install.d/canonical_ci_utils.py 1970-01-01 00:00:00 +0000 |
138 | @@ -1,91 +0,0 @@ |
139 | -#!/usr/bin/python |
140 | - |
141 | -import os |
142 | -import sys |
143 | - |
144 | -from charmhelpers.canonical_ci import nrpe |
145 | - |
146 | - |
147 | -from charmhelpers.core.hookenv import ( |
148 | - config, |
149 | - local_unit, |
150 | - log, |
151 | - relation_ids, |
152 | - unit_get, |
153 | - ERROR, |
154 | - INFO, |
155 | -) |
156 | - |
157 | -from charmhelpers.core.host import ( |
158 | - service_reload, |
159 | -) |
160 | - |
161 | -# Constants set in jenkins/hooks/install. |
162 | -JENKINS_HOME = '/var/lib/jenkins' |
163 | -JENKINS_USER = 'jenkins' |
164 | -JENKINS_GROUP = 'nogroup' |
165 | -JENKINS_PORT = 8080 |
166 | - |
167 | -# Local constants |
168 | -NRPE_CHECK_PS = "/etc/nagios/nrpe.d/check_jenkins_slave_ps.cfg" |
169 | - |
170 | - |
171 | -def update_nrpe_config(): |
172 | - if not relation_ids('nrpe-external-master'): |
173 | - log('No relation to an nrpe-external-master, not configuring ' |
174 | - 'nagios.') |
175 | - return |
176 | - with open(NRPE_CHECK_PS, "w") as conf: |
177 | - log("Writing config: %s." % NRPE_CHECK_PS, INFO) |
178 | - conf.write(nrpe.CONF_HEADER) |
179 | - conf.write( |
180 | - "command[check_jenkins_slave_ps]=" |
181 | - "/usr/lib/nagios/plugins/check_procs -c 1:1 -a slave.jar") |
182 | - |
183 | - # config |
184 | - unit_name = local_unit().replace('/', '-') |
185 | - n_hostname = "%s-%s" % (config("nagios_context"), unit_name) |
186 | - n_servicegroup = config("nagios_servicegroups") if config("nagios_servicegroups") else config("nagios_context") |
187 | - service_file = ( |
188 | - '/var/lib/nagios/export/service__%s_check_jenkins_slave.cfg' % |
189 | - n_hostname) |
190 | - |
191 | - # There is a race between this code and the nrpe_external_master install |
192 | - # hook. Both need to write files to /var/lib/nagios/export, but only one |
193 | - # needs to create it. So tolerate failure if the directory exists. |
194 | - try: |
195 | - os.makedirs(os.path.dirname(service_file)) |
196 | - except os.error: |
197 | - pass |
198 | - |
199 | - with open(service_file, "w") as conf: |
200 | - log("Writing config: %s." % conf, INFO) |
201 | - conf.write(nrpe.CONF_HEADER) |
202 | - conf.write(nrpe.NRPE_SERVICE_ENTRY % { |
203 | - 'nagios_hostname': n_hostname, |
204 | - 'check_name': 'check_jenkins_slave_ps', |
205 | - 'nagios_servicegroup': n_servicegroup, |
206 | - }) |
207 | - |
208 | - # reboot |
209 | - if os.path.isfile('/etc/init.d/nagios-nrpe-server'): |
210 | - service_reload('nagios-nrpe-server') |
211 | - |
212 | - |
213 | -hooks = { |
214 | - '03_nrpe_relation_changed': update_nrpe_config |
215 | -} |
216 | - |
217 | - |
218 | -def main(hook): |
219 | - try: |
220 | - hooks[hook]() |
221 | - except KeyError: |
222 | - e = 'Invalid install.d hook: %s.' % hook |
223 | - log(e, ERROR) |
224 | - raise Exception(e) |
225 | - |
226 | - |
227 | -if __name__ == '__main__': |
228 | - if os.path.islink(sys.argv[0]): |
229 | - main(os.path.basename(sys.argv[0])) |
230 | |
231 | === removed file 'hooks/nrpe-external-master-relation-changed' |
232 | --- hooks/nrpe-external-master-relation-changed 2015-08-19 20:00:15 +0000 |
233 | +++ hooks/nrpe-external-master-relation-changed 1970-01-01 00:00:00 +0000 |
234 | @@ -1,7 +0,0 @@ |
235 | -#!/bin/sh |
236 | -set -e |
237 | - |
238 | -home=`dirname $0` |
239 | - |
240 | -juju-log "Running install hook once more to pick up new NRPE relation changes" |
241 | -exec $home/install |
242 | |
243 | === removed symlink 'hooks/slave-relation-broken' |
244 | === target was u'slave-relation-departed' |
245 | === removed file 'hooks/slave-relation-changed' |
246 | --- hooks/slave-relation-changed 2015-08-05 13:20:44 +0000 |
247 | +++ hooks/slave-relation-changed 1970-01-01 00:00:00 +0000 |
248 | @@ -1,19 +0,0 @@ |
249 | -#!/bin/bash |
250 | - |
251 | -set -e |
252 | - |
253 | -# Setup connection to master instance once set |
254 | -url="$(relation-get url)" |
255 | - |
256 | -if [ "x$url" = "x" ]; then |
257 | - juju-log "Master hasn't exported its url yet, exiting..." |
258 | - exit 0 |
259 | -fi |
260 | - |
261 | -master_url="$(config-get master_url)" |
262 | -if [ -n "${master_url}" ]; then |
263 | - juju-log "Config option 'master_url' is set. Can't use slave relation." |
264 | - exit 0 |
265 | -fi |
266 | - |
267 | -hooks/configure-slave "${url}" |
268 | |
269 | === removed file 'hooks/slave-relation-departed' |
270 | --- hooks/slave-relation-departed 2012-07-27 11:23:24 +0000 |
271 | +++ hooks/slave-relation-departed 1970-01-01 00:00:00 +0000 |
272 | @@ -1,3 +0,0 @@ |
273 | -#!/bin/bash |
274 | - |
275 | -stop jenkins-slave || true |
276 | |
277 | === removed file 'hooks/slave-relation-joined' |
278 | --- hooks/slave-relation-joined 2015-08-04 16:46:21 +0000 |
279 | +++ hooks/slave-relation-joined 1970-01-01 00:00:00 +0000 |
280 | @@ -1,20 +0,0 @@ |
281 | -#!/bin/bash |
282 | - |
283 | -set -e |
284 | - |
285 | -# Set the slave hostname to match the juju unit |
286 | -# in the jenkins master instance |
287 | -slavehost=`echo ${JUJU_UNIT_NAME} | sed s,/,-,` |
288 | -noexecutors=`cat /proc/cpuinfo | grep processor | wc -l` |
289 | -config_labels=`config-get labels` |
290 | -labels=`uname -p` |
291 | - |
292 | -if [ -n "$config_labels" ]; then |
293 | - labels=$config_labels |
294 | -fi |
295 | - |
296 | -# Set all relations |
297 | -relation-set executors=$noexecutors |
298 | -relation-set labels="$labels" |
299 | -relation-set slavehost=$slavehost |
300 | -relation-set slaveaddress=`unit-get private-address` |
301 | |
302 | === removed file 'hooks/start' |
303 | --- hooks/start 2011-08-02 08:53:54 +0000 |
304 | +++ hooks/start 1970-01-01 00:00:00 +0000 |
305 | @@ -1,3 +0,0 @@ |
306 | -#!/bin/bash |
307 | - |
308 | -start jenkins-slave || true |
309 | |
310 | === removed file 'hooks/stop' |
311 | --- hooks/stop 2011-08-02 08:53:54 +0000 |
312 | +++ hooks/stop 1970-01-01 00:00:00 +0000 |
313 | @@ -1,3 +0,0 @@ |
314 | -#!/bin/bash |
315 | - |
316 | -stop jenkins-slave |
317 | |
318 | === removed symlink 'hooks/upgrade-charm' |
319 | === target was u'install' |
320 | === added file 'layer.yaml' |
321 | --- layer.yaml 1970-01-01 00:00:00 +0000 |
322 | +++ layer.yaml 2019-03-01 05:39:53 +0000 |
323 | @@ -0,0 +1,5 @@ |
324 | +includes: |
325 | + - layer:basic |
326 | + - layer:apt |
327 | + - layer:nagios |
328 | +repo: lp:jenkins-slave-charm |
329 | |
330 | === added directory 'lib' |
331 | === modified file 'metadata.yaml' |
332 | --- metadata.yaml 2019-02-18 00:41:09 +0000 |
333 | +++ metadata.yaml 2019-03-01 05:39:53 +0000 |
334 | @@ -9,8 +9,12 @@ |
335 | This charm provides support for jenkins slaves |
336 | . |
337 | https://launchpad.net/jenkins-slave-charm |
338 | -categories: |
339 | +tags: |
340 | - applications |
341 | +series: |
342 | + - bionic |
343 | + - xenial |
344 | + - trusty |
345 | provides: |
346 | slave: |
347 | interface: jenkins-slave |
348 | |
349 | === added directory 'reactive' |
350 | === renamed file 'hooks/install' => 'reactive/jenkins_slave.py' |
351 | --- hooks/install 2016-06-14 01:04:43 +0000 |
352 | +++ reactive/jenkins_slave.py 2019-03-01 05:39:53 +0000 |
353 | @@ -1,121 +1,231 @@ |
354 | -#!/bin/bash |
355 | - |
356 | -set -eu |
357 | - |
358 | - |
359 | -install_exec_d () { |
360 | - if [[ -d exec.d ]]; then |
361 | - shopt -s nullglob |
362 | - for f in exec.d/*/charm-pre-install; do |
363 | - [[ -x "$f" ]] || continue |
364 | - ${SHELL} -c "$f"|| { |
365 | - ## bail out if anyone fails |
366 | - juju-log -l ERROR "$f: returned exit_status=$? " |
367 | - } |
368 | - done |
369 | - shopt -u nullglob |
370 | - fi |
371 | -} |
372 | - |
373 | -# Get rid of the legacy jenkins-slave package, including config files. |
374 | -clean_up_old_package () { |
375 | - juju-log "Removing the old jenkin-slave package... (obsoleted by this charm)" |
376 | - dpkg --purge jenkins-slave |
377 | - juju-log "Removing the old jenkin-slave package... done." |
378 | -} |
379 | - |
380 | -# Install the slave if it is not installed already. |
381 | -install_slave () { |
382 | - juju-log "Installing jenkins-slave..." |
383 | - juju-log "Installing jenkins-slave (dependencies)..." |
384 | - apt-get -y install -qq wget adduser default-jre-headless |
385 | +import os |
386 | + |
387 | +from charmhelpers.core import hookenv, host, templating, unitdata |
388 | +from charmhelpers.contrib.charmsupport import nrpe |
389 | +from charmhelpers.fetch import apt_purge |
390 | +from charms import apt, reactive |
391 | + |
392 | + |
393 | +@reactive.hook('upgrade-charm') |
394 | +def upgrade_charm(): |
395 | + hookenv.status_set('maintenance', 'forcing reconfiguration on upgrade-charm') |
396 | + reactive.clear_flag('jenkins-slave.active') |
397 | + reactive.clear_flag('jenkins-slave.installed') |
398 | + |
399 | + |
400 | +@reactive.when_not('jenkins-slave.installed') |
401 | +def install(): |
402 | + hookenv.status_set('maintenance', 'installing jenkins-slave') |
403 | + reactive.clear_flag('jenkins-slave.active') |
404 | + |
405 | + config = hookenv.config() |
406 | + |
407 | + hookenv.log('Adding jenkins-slave dependencies to be installed') |
408 | + packages = ['wget', 'default-jre-headless'] |
409 | + |
410 | + # Install extra packages needed by the slave. |
411 | + tools = config.get('tools') |
412 | + if tools: |
413 | + hookenv.log('Adding jenkins-slave additional tools to be installed: {}'.format(tools)) |
414 | + for package in tools.split(): |
415 | + packages.append(package) |
416 | + apt.queue_install(packages) |
417 | + if not apt.install_queued(): |
418 | + return # apt layer already set blocked state. |
419 | + |
420 | + # Get rid of the legacy jenkins-slave package, including config files. |
421 | + hookenv.log('Removing the old jenkins-slave package... (obsoleted by this charm)') |
422 | + apt_purge(['jenkins-slave']) |
423 | |
424 | # Create jenkins user if it doesn't exist. |
425 | - if ! id jenkins > /dev/null 2>&1 ; then |
426 | - juju-log "Installing jenkins-slave (user account)..." |
427 | - adduser --system --home /var/lib/jenkins --group \ |
428 | - --disabled-password --quiet --shell /bin/bash \ |
429 | - jenkins |
430 | - else |
431 | - juju-log "Installing jenkins-slave (user account already exists)..." |
432 | - fi |
433 | - juju-log "Installing jenkins-slave (directories)..." |
434 | + if host.user_exists('jenkins'): |
435 | + hookenv.log('Installing jenkins-slave (user account already exists)...') |
436 | + else: |
437 | + hookenv.log('Installing jenkins-slave (user account)...') |
438 | + host.adduser(username='jenkins', system_user=True, home_dir='/var/lib/jenkins') |
439 | + |
440 | # And ensure required directories exist and are set up. |
441 | - mkdir -p /var/lib/jenkins |
442 | - chown -R jenkins:jenkins /var/lib/jenkins || true |
443 | - mkdir -p /var/log/jenkins |
444 | - chown -R jenkins:jenkins /var/log/jenkins || true |
445 | - juju-log "Installing jenkins-slave (common files)..." |
446 | - install -m 0555 files/download-slave.sh /usr/local/sbin/download-slave.sh |
447 | - # XXX obviously we lose conffile handling here... |
448 | - install -m 0444 files/jenkins-slave-default /etc/default/jenkins-slave |
449 | - install -m 0444 files/jenkins-slave-logrotate-config /etc/logrotate.d/jenkins-slave |
450 | - |
451 | - distro=$(source /etc/lsb-release ; echo $DISTRIB_CODENAME) |
452 | - case $distro in |
453 | - xenial) |
454 | - # LTS or bust! |
455 | - juju-log "Installing jenkins-slave (system unit)..." |
456 | - install -m 0444 files/jenkins-slave-systemd-config /lib/systemd/system/jenkins-slave.service |
457 | - systemctl enable jenkins-slave |
458 | - ;; |
459 | - *) |
460 | - # Probably an LTS, and it's not, then too bad. |
461 | - juju-log "Installing jenkins-slave (upstart job)..." |
462 | - install -m 0444 files/jenkins-slave-upstart-config /etc/init/jenkins-slave.conf |
463 | - ;; |
464 | - esac |
465 | - juju-log "Installing jenkins-slave... done." |
466 | -} |
467 | - |
468 | - |
469 | -# Install extra packages needed by the slave. |
470 | -install_tools () { |
471 | - juju-log "Installing tools..." |
472 | - apt-get -y install -qq $(config-get tools) |
473 | -} |
474 | - |
475 | - |
476 | -# Configure slave |
477 | -set_up_slave () { |
478 | - # If a master_url value is specified, use that to configure the slave. |
479 | - master_url="$(config-get master_url)" |
480 | - if [ -n "${master_url}" ]; then |
481 | - juju-log "Using 'master_url' to configure the slave." |
482 | - hooks/configure-slave "${master_url}" |
483 | - else |
484 | - juju-log "No 'master_url' set; not configuring slave at this time." |
485 | - fi |
486 | -} |
487 | - |
488 | -# Execute any hook overlay which may be provided |
489 | -# by forks of this charm. |
490 | -install_extra_hooks () { |
491 | - # XXX for canonical_ci_utils.py |
492 | - apt-get -y install -qq python-yaml |
493 | - |
494 | - juju-log "Installing hooks..." |
495 | - if [[ -d hooks/install.d ]] |
496 | - then |
497 | - for i in $(ls -1 hooks/install.d/*) |
498 | - do |
499 | - if [[ -x "$i" ]] |
500 | - then |
501 | - ./$i |
502 | - fi |
503 | - done |
504 | - else |
505 | - juju-log "No extra hooks found." |
506 | - fi |
507 | -} |
508 | - |
509 | - |
510 | -apt-get update -qq |
511 | -install_exec_d |
512 | -clean_up_old_package |
513 | -install_slave |
514 | -install_tools |
515 | -set_up_slave |
516 | -install_extra_hooks |
517 | - |
518 | -exit 0 |
519 | + hookenv.log('Installing jenkins-slave (directories)...') |
520 | + host.mkdir('/var/lib/jenkins', owner='jenkins', group='jenkins') |
521 | + host.mkdir('/var/log/jenkins', owner='jenkins', group='jenkins') |
522 | + |
523 | + hookenv.log('Installing jenkins-slave (common files)...') |
524 | + write_default_conf() |
525 | + file_to_units('files/download-slave.sh', '/usr/local/sbin/download-slave.sh') |
526 | + file_to_units('files/jenkins-slave-logrotate-config', '/etc/logrotate.d/jenkins-slave') |
527 | + |
528 | + if host.lsb_release()['DISTRIB_CODENAME'] == 'trusty': |
529 | + hookenv.log('Installing jenkins-slave (upstart job)...') |
530 | + file_to_units('files/jenkins-slave-upstart-config', '/etc/init/jenkins-slave.conf') |
531 | + else: |
532 | + hookenv.log('Installing jenkins-slave (system unit)...') |
533 | + file_to_units('files/jenkins-slave-systemd-config', '/lib/systemd/system/jenkins-slave.service') |
534 | + host.service('enable', 'jenkins-slave') |
535 | + |
536 | + hookenv.log('Installing jenkins-slave... done.') |
537 | + reactive.clear_flag('jenkins-slave.blocked') |
538 | + reactive.clear_flag('jenkins-slave.configured') |
539 | + reactive.set_flag('jenkins-slave.installed') |
540 | + |
541 | + |
542 | +@reactive.when('config.changed') |
543 | +def config_changed(): |
544 | + reactive.clear_flag('jenkins-slave.blocked') |
545 | + reactive.clear_flag('jenkins-slave.configured') |
546 | + reactive.clear_flag('nagios-nrpe.configured') |
547 | + |
548 | + |
549 | +@reactive.when('jenkins-slave.installed') |
550 | +@reactive.when_not('jenkins-slave.configured') |
551 | +@reactive.when_not('jenkins-slave.blocked') |
552 | +def configure_jenkins_slave(): |
553 | + hookenv.status_set('maintenance', 'configuring jenkins-slave') |
554 | + reactive.clear_flag('jenkins-slave.active') |
555 | + |
556 | + config = hookenv.config() |
557 | + kv = unitdata.kv() |
558 | + |
559 | + if config.get('master_url'): |
560 | + hookenv.log("Using 'master_url' to configure the slave.") |
561 | + write_default_conf(config.get('master_url')) |
562 | + elif kv.get('url'): |
563 | + hookenv.log("Using url from relation as 'master_url'") |
564 | + write_default_conf(kv.get('url')) |
565 | + else: |
566 | + hookenv.log("No 'master_url' set; not configuring slave at this time.") |
567 | + hookenv.status_set('blocked', "requires either slave relation or 'master_url'") |
568 | + reactive.set_flag('jenkins-slave.blocked') |
569 | + return |
570 | + |
571 | + file_to_units('files/jenkins-slave-sudoers', '/etc/sudoers.d/jenkins', perms=0o440) |
572 | + |
573 | + reactive.clear_flag('nagios-nrpe.configured') |
574 | + reactive.set_flag('jenkins-slave.configured') |
575 | + |
576 | + |
577 | +@reactive.when('jenkins-slave.blocked') |
578 | +def blocked_on_jenkins_url(): |
579 | + reactive.clear_flag('jenkins-slave.active') |
580 | + |
581 | + |
582 | +@reactive.when('jenkins-slave.configured') |
583 | +@reactive.when('nrpe-external-master.available') |
584 | +@reactive.when('jenkins-slave.active') |
585 | +@reactive.when_not('nagios-nrpe.configured') |
586 | +def configure_nagios(nagios): |
587 | + hookenv.status_set('maintenance', 'setting up NRPE checks') |
588 | + |
589 | + # Use charmhelpers.contrib.charmsupport's nrpe to determine hostname |
590 | + hostname = nrpe.get_nagios_hostname() |
591 | + nrpe_setup = nrpe.NRPE(hostname=hostname, primary=True) |
592 | + |
593 | + cmd = '/usr/lib/nagios/plugins/check_procs -c 1:1 -a slave.jar' |
594 | + nrpe_setup.add_check('jenkins_slave_ps', 'Jenkins Slave Process', cmd) |
595 | + |
596 | + nrpe_setup.write() |
597 | + reactive.set_flag('nagios-nrpe.configured') |
598 | + |
599 | + |
600 | +@reactive.when('jenkins-slave.configured') |
601 | +@reactive.when_not('jenkins-slave.active') |
602 | +def set_active(): |
603 | + # Startup the jenkins-slave service. This is called in the |
604 | + # install, config-changed and upgrade-charm paths. It needs to be |
605 | + # tolerant of a running or stopped jenkins-slave. |
606 | + if host.service_running('jenkins-slave'): |
607 | + hookenv.log('Restarting jenkins-slave...') |
608 | + host.service_restart('jenkins-slave') |
609 | + else: |
610 | + hookenv.log('Starting jenkins-slave...') |
611 | + host.service_start('jenkins-slave') |
612 | + |
613 | + hookenv.status_set('active', 'ready') |
614 | + reactive.set_flag('jenkins-slave.active') |
615 | + |
616 | + |
617 | +# We can't use interface:jenkins-slave yet as it's not implemented. |
618 | +@reactive.hook('slave-relation-joined', 'slave-relation-changed') |
619 | +def slave_relation_changed(): |
620 | + reactive.set_flag('slave-relation.available') |
621 | + reactive.clear_flag('jenkins-slave.blocked') |
622 | + reactive.clear_flag('jenkins-slave.configured') |
623 | + reactive.clear_flag('slave-relation.configured') |
624 | + |
625 | + |
626 | +@reactive.hook('slave-relation-departed', 'slave-relation-broken') |
627 | +def slave_relation_removed(): |
628 | + kv = unitdata.kv() |
629 | + kv.set('url', None) |
630 | + reactive.clear_flag('slave-relation.available') |
631 | + |
632 | + |
633 | +@reactive.when('slave-relation.available') |
634 | +@reactive.when_not('slave-relation.configured') |
635 | +def slave_relation(): |
636 | + hookenv.status_set('maintenance', 'setting up jenkins via slave relation') |
637 | + config = hookenv.config() |
638 | + kv = unitdata.kv() |
639 | + |
640 | + if config.get('master_url'): |
641 | + hookenv.log("Config option 'master_url' is set. Can't use slave relation.") |
642 | + reactive.set_flag('slave-relation.configured') |
643 | + return |
644 | + |
645 | + url = hookenv.relation_get('url') |
646 | + if url: |
647 | + kv.set('url', url) |
648 | + write_default_conf(url) |
649 | + else: |
650 | + hookenv.log("Master hasn't exported its url yet, exiting...") |
651 | + return |
652 | + |
653 | + reactive.clear_flag('jenkins-slave.active') |
654 | + |
655 | + # Set the slave hostname to match the juju unit |
656 | + # in the jenkins master instance |
657 | + slave_host = hookenv.local_unit().replace('/', '-') |
658 | + slave_address = hookenv.unit_private_ip() |
659 | + noexecutors = os.cpu_count() |
660 | + config_labels = config.get('labels') |
661 | + |
662 | + if config_labels: |
663 | + labels = config_labels |
664 | + else: |
665 | + labels = os.uname()[4] |
666 | + |
667 | + # Set all relations |
668 | + hookenv.relation_set(executors=noexecutors) |
669 | + hookenv.relation_set(labels=labels) |
670 | + hookenv.relation_set(slavehost=slave_host) |
671 | + hookenv.relation_set(slaveaddress=slave_address) |
672 | + reactive.set_flag('slave-relation.configured') |
673 | + |
674 | + |
675 | +def file_to_units(local_path, unit_path, perms=None, owner='root', group='root'): |
676 | + """ copy a file from the charm onto our unit(s) """ |
677 | + file_perms = perms |
678 | + if not perms: |
679 | + # Let's try manually work it out |
680 | + if local_path[-3:] == '.py' or local_path[-3:] == '.sh': |
681 | + file_perms = 0o755 |
682 | + else: |
683 | + file_perms = 0o644 |
684 | + |
685 | + with open(local_path, 'r') as fh: |
686 | + host.write_file( |
687 | + path=unit_path, |
688 | + content=fh.read().encode(), |
689 | + owner=owner, |
690 | + group=group, |
691 | + perms=file_perms, |
692 | + ) |
693 | + |
694 | + |
695 | +def write_default_conf(master_url=None, owner='root', group='root', |
696 | + conf_path='/etc/default/jenkins-slave'): |
697 | + templates_dir = os.path.join(hookenv.charm_dir(), 'templates') |
698 | + slave_host = hookenv.local_unit().replace('/', '-') |
699 | + templating.render('jenkins-slave-default', conf_path, |
700 | + {'master_url': master_url, 'slave_host': slave_host}, |
701 | + owner=owner, group=group, perms=0o444, |
702 | + templates_dir=templates_dir) |
703 | |
704 | === added file 'requirements.txt' |
705 | --- requirements.txt 1970-01-01 00:00:00 +0000 |
706 | +++ requirements.txt 2019-03-01 05:39:53 +0000 |
707 | @@ -0,0 +1,1 @@ |
708 | +# Include python requirements here |
709 | |
710 | === removed file 'revision' |
711 | --- revision 2015-08-04 16:46:21 +0000 |
712 | +++ revision 1970-01-01 00:00:00 +0000 |
713 | @@ -1,1 +0,0 @@ |
714 | -9 |
715 | |
716 | === added directory 'templates' |
717 | === renamed file 'files/jenkins-slave-default' => 'templates/jenkins-slave-default' |
718 | --- files/jenkins-slave-default 2016-06-03 03:37:31 +0000 |
719 | +++ templates/jenkins-slave-default 2019-03-01 05:39:53 +0000 |
720 | @@ -32,12 +32,20 @@ |
721 | # URL of jenkins server to connect to |
722 | # Not specifying this parameter will stop the slave |
723 | # job from running. |
724 | +{% if master_url %} |
725 | +JENKINS_URL="{{ master_url }}" |
726 | +{% else %} |
727 | #JENKINS_URL="" |
728 | +{% endif %} |
729 | |
730 | # Name of slave configuration to use at JENKINS_URL |
731 | # Override if it need to be something other than the |
732 | # hostname of the server the slave is running on. |
733 | +{% if slave_host %} |
734 | +JENKINS_HOSTNAME="{{ slave_host }}" |
735 | +{% else %} |
736 | JENKINS_HOSTNAME="$(hostname)" |
737 | +{% endif %} |
738 | |
739 | # Log file location for use in Debian init script |
740 | JENKINS_SLAVE_LOG=/var/log/jenkins/$NAME.log |
741 | |
742 | === added directory 'tests' |
743 | === added directory 'tests/functional' |
744 | === added file 'tests/functional/requirements.txt' |
745 | --- tests/functional/requirements.txt 1970-01-01 00:00:00 +0000 |
746 | +++ tests/functional/requirements.txt 2019-03-01 05:39:53 +0000 |
747 | @@ -0,0 +1,6 @@ |
748 | +flake8 |
749 | +juju |
750 | +mock |
751 | +pytest |
752 | +pytest-asyncio |
753 | +requests |
754 | |
755 | === added file 'tests/functional/test_jenkins_slave.py' |
756 | --- tests/functional/test_jenkins_slave.py 1970-01-01 00:00:00 +0000 |
757 | +++ tests/functional/test_jenkins_slave.py 2019-03-01 05:39:53 +0000 |
758 | @@ -0,0 +1,50 @@ |
759 | +import os |
760 | +import pytest |
761 | +from juju.model import Model |
762 | + |
763 | +# Treat tests as coroutines |
764 | +pytestmark = pytest.mark.asyncio |
765 | + |
766 | +series = ['bionic'] |
767 | +juju_repository = os.getenv('JUJU_REPOSITORY', '.').rstrip('/') |
768 | + |
769 | + |
770 | +@pytest.fixture |
771 | +async def model(): |
772 | + model = Model() |
773 | + await model.connect_current() |
774 | + yield model |
775 | + await model.disconnect() |
776 | + |
777 | + |
778 | +@pytest.fixture |
779 | +async def apps(model): |
780 | + apps = [] |
781 | + for entry in series: |
782 | + app = model.applications['jenkins-slave-{}'.format(entry)] |
783 | + apps.append(app) |
784 | + return apps |
785 | + |
786 | + |
787 | +@pytest.fixture |
788 | +async def units(apps): |
789 | + units = [] |
790 | + for app in apps: |
791 | + units.extend(app.units) |
792 | + return units |
793 | + |
794 | + |
795 | +@pytest.mark.parametrize('series', series) |
796 | +async def test_jenkins_slave_deploy(model, series): |
797 | + # Starts a deploy for each series |
798 | + await model.deploy('{}/builds/jenkins-slave'.format(juju_repository), |
799 | + series=series, |
800 | + application_name='jenkins-slave-{}'.format(series)) |
801 | + assert True |
802 | + |
803 | + |
804 | +async def test_jenkins_slave_status(apps, model): |
805 | + # Verifies status for all deployed series of the charm |
806 | + for app in apps: |
807 | + await model.block_until(lambda: app.status == 'active') |
808 | + assert True |
809 | |
810 | === added directory 'tests/unit' |
811 | === added directory 'tests/unit/files' |
812 | === added file 'tests/unit/files/jenkins-slave-default' |
813 | --- tests/unit/files/jenkins-slave-default 1970-01-01 00:00:00 +0000 |
814 | +++ tests/unit/files/jenkins-slave-default 2019-03-01 05:39:53 +0000 |
815 | @@ -0,0 +1,59 @@ |
816 | +# |
817 | +# This file is managed by Juju. Attempt no changes here. |
818 | +# |
819 | + |
820 | +# defaults for jenkins-slave component of the jenkins continuous integration |
821 | +# system |
822 | + |
823 | +# pulled in from the init script; makes things easier. |
824 | +NAME=jenkins-slave |
825 | + |
826 | +# location of java |
827 | +JAVA=/usr/bin/java |
828 | + |
829 | +# arguments to pass to java - optional |
830 | +#JAVA_ARGS="-Xmx256m" |
831 | + |
832 | +# for daemon to use |
833 | +PIDFILE=/var/run/jenkins/$NAME.pid |
834 | + |
835 | +# user id to be invoked as (otherwise will run as root; not wise!) |
836 | +JENKINS_USER=jenkins |
837 | + |
838 | +# location of jenkins arch indep files |
839 | +JENKINS_ROOT=/usr/share/jenkins |
840 | + |
841 | +# jenkins home location |
842 | +JENKINS_HOME=/var/lib/jenkins |
843 | + |
844 | +# jenkins /run location |
845 | +JENKINS_RUN=/var/run/jenkins |
846 | + |
847 | +# URL of jenkins server to connect to |
848 | +# Not specifying this parameter will stop the slave |
849 | +# job from running. |
850 | + |
851 | +#JENKINS_URL="" |
852 | + |
853 | + |
854 | +# Name of slave configuration to use at JENKINS_URL |
855 | +# Override if it need to be something other than the |
856 | +# hostname of the server the slave is running on. |
857 | + |
858 | +JENKINS_HOSTNAME="jenkins-slave-3" |
859 | + |
860 | + |
861 | +# Log file location for use in Debian init script |
862 | +JENKINS_SLAVE_LOG=/var/log/jenkins/$NAME.log |
863 | + |
864 | +# OS LIMITS SETUP |
865 | +# comment this out to observe /etc/security/limits.conf |
866 | +# this is on by default because http://github.com/feniix/hudson/commit/d13c08ea8f5a3fa730ba174305e6429b74853927 |
867 | +# reported that Ubuntu's PAM configuration doesn't include pam_limits.so, and as a result the # of file |
868 | +# descriptors are forced to 1024 regardless of /etc/security/limits.confa |
869 | +# NOTE - Ubuntu Users - this is not used by the upstart configuration - please use an upstart overrides file |
870 | +# to change the OS limits setup. |
871 | +MAXOPENFILES=8192 |
872 | + |
873 | +# Arguments to pass to jenkins slave on startup |
874 | +JENKINS_ARGS="-jnlpUrl $JENKINS_URL/computer/$JENKINS_HOSTNAME/slave-agent.jnlp" |
875 | \ No newline at end of file |
876 | |
877 | === added file 'tests/unit/files/somefile' |
878 | === added file 'tests/unit/files/somefile.py' |
879 | === added file 'tests/unit/requirements.txt' |
880 | --- tests/unit/requirements.txt 1970-01-01 00:00:00 +0000 |
881 | +++ tests/unit/requirements.txt 2019-03-01 05:39:53 +0000 |
882 | @@ -0,0 +1,5 @@ |
883 | +charmhelpers |
884 | +charms.reactive |
885 | +mock |
886 | +pytest |
887 | +pytest-cov |
888 | |
889 | === added file 'tests/unit/test_jenkins_slave.py' |
890 | --- tests/unit/test_jenkins_slave.py 1970-01-01 00:00:00 +0000 |
891 | +++ tests/unit/test_jenkins_slave.py 2019-03-01 05:39:53 +0000 |
892 | @@ -0,0 +1,218 @@ |
893 | +import grp |
894 | +import os |
895 | +import pwd |
896 | +import shutil |
897 | +import sys |
898 | +import tempfile |
899 | +import unittest |
900 | +from unittest import mock |
901 | + |
902 | +sys.modules['charms.apt'] = mock.MagicMock() |
903 | +from charms import apt # NOQA: E402 |
904 | + |
905 | +# Add path to where our reactive layer lives and import. |
906 | +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) |
907 | +from reactive.jenkins_slave import ( |
908 | + config_changed, |
909 | + install, |
910 | + configure_jenkins_slave, |
911 | + file_to_units, |
912 | + write_default_conf, |
913 | +) # NOQA: E402 |
914 | + |
915 | + |
916 | +INITIAL_CONF = 'tests/unit/files/jenkins-slave-default' |
917 | + |
918 | + |
919 | +class TestSetDefaultConf(unittest.TestCase): |
920 | + def setUp(self): |
921 | + self.tmpdir = tempfile.mkdtemp(prefix='charm-unittests-') |
922 | + temp_file = tempfile.NamedTemporaryFile(delete=False, dir=self.tmpdir) |
923 | + with open(INITIAL_CONF, 'rb') as f: |
924 | + conf = f.read().decode('utf-8') |
925 | + temp_file.write(conf.encode()) |
926 | + temp_file.close() |
927 | + self.conf_file = temp_file.name |
928 | + self.user = pwd.getpwuid(os.getuid()).pw_name |
929 | + self.group = grp.getgrgid(os.getgid()).gr_name |
930 | + self.charm_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) |
931 | + |
932 | + # charmhelpers is getting difficult to test against, as it writes |
933 | + # to system directories even for things that should be idempotent, |
934 | + # like accessing config options. |
935 | + patcher = mock.patch('charmhelpers.core.hookenv.charm_dir') |
936 | + self.mock_charm_dir = patcher.start() |
937 | + self.addCleanup(patcher.stop) |
938 | + self.mock_charm_dir.return_value = self.charm_dir |
939 | + |
940 | + patcher = mock.patch('charmhelpers.core.hookenv.config') |
941 | + self.mock_config = patcher.start() |
942 | + self.addCleanup(patcher.stop) |
943 | + self.mock_config.return_value = {'tools': []} |
944 | + |
945 | + patcher = mock.patch('charmhelpers.core.hookenv.local_unit') |
946 | + self.mock_local_unit = patcher.start() |
947 | + self.addCleanup(patcher.stop) |
948 | + self.mock_local_unit.return_value = 'mock-jenkins-slave/0' |
949 | + |
950 | + patcher = mock.patch('charmhelpers.core.hookenv.log') |
951 | + self.mock_log = patcher.start() |
952 | + self.addCleanup(patcher.stop) |
953 | + self.mock_log.return_value = '' |
954 | + |
955 | + def tearDown(self): |
956 | + shutil.rmtree(self.tmpdir) |
957 | + |
958 | + @mock.patch('charms.reactive.clear_flag') |
959 | + def test_hook_config_changed(self, clear_flag): |
960 | + config_changed() |
961 | + expected = [mock.call('jenkins-slave.blocked'), |
962 | + mock.call('jenkins-slave.configured'), |
963 | + mock.call('nagios-nrpe.configured')] |
964 | + self.assertEqual(clear_flag.call_args_list, expected) |
965 | + |
966 | + @mock.patch('charmhelpers.core.host.adduser') |
967 | + @mock.patch('charmhelpers.core.host.mkdir') |
968 | + @mock.patch('charmhelpers.core.host.service') |
969 | + @mock.patch('reactive.jenkins_slave.apt_purge') |
970 | + @mock.patch('reactive.jenkins_slave.file_to_units') |
971 | + @mock.patch('reactive.jenkins_slave.write_default_conf') |
972 | + def test_hook_install(self, write_default_conf, file_to_units, apt_purge, service, mkdir, adduser): |
973 | + install() |
974 | + expected = [mock.call(home_dir='/var/lib/jenkins', system_user=True, username='jenkins')] |
975 | + self.assertEqual(adduser.call_args_list, expected) |
976 | + expected = [mock.call('/var/lib/jenkins', group='jenkins', owner='jenkins'), |
977 | + mock.call('/var/log/jenkins', group='jenkins', owner='jenkins')] |
978 | + self.assertEqual(mkdir.call_args_list, expected) |
979 | + self.assertEqual(service.call_args_list, [mock.call('enable', 'jenkins-slave')]) |
980 | + self.assertEqual(apt_purge.call_args_list, [mock.call(['jenkins-slave'])]) |
981 | + expected = [mock.call('files/download-slave.sh', '/usr/local/sbin/download-slave.sh'), |
982 | + mock.call('files/jenkins-slave-logrotate-config', '/etc/logrotate.d/jenkins-slave'), |
983 | + mock.call('files/jenkins-slave-systemd-config', '/lib/systemd/system/jenkins-slave.service')] |
984 | + self.assertEqual(file_to_units.call_args_list, expected) |
985 | + self.assertEqual(write_default_conf.call_args_list, [mock.call()]) |
986 | + expected = [mock.call.queue_install(['wget', 'default-jre-headless']), |
987 | + mock.call.install_queued()] |
988 | + self.assertEqual(apt.method_calls, expected) |
989 | + |
990 | + @mock.patch('charms.reactive.clear_flag') |
991 | + @mock.patch('charms.reactive.set_flag') |
992 | + @mock.patch('charmhelpers.core.hookenv.config') |
993 | + @mock.patch('charmhelpers.core.unitdata.kv') |
994 | + @mock.patch('reactive.jenkins_slave.write_default_conf') |
995 | + @mock.patch('reactive.jenkins_slave.file_to_units') |
996 | + def test_configure_jenkins_slave_no_url(self, file_to_units, write_default_conf, unitdata_kv, config, |
997 | + set_flag, clear_flag): |
998 | + config.return_value = {} |
999 | + unitdata_kv.return_value = {} |
1000 | + configure_jenkins_slave() |
1001 | + self.assertEqual(write_default_conf.call_args_list, []) |
1002 | + self.assertEqual(set_flag.call_args_list, [mock.call('jenkins-slave.blocked')]) |
1003 | + self.assertEqual(clear_flag.call_args_list, [mock.call('jenkins-slave.active')]) |
1004 | + |
1005 | + @mock.patch('charms.reactive.clear_flag') |
1006 | + @mock.patch('charms.reactive.set_flag') |
1007 | + @mock.patch('charmhelpers.core.hookenv.config') |
1008 | + @mock.patch('charmhelpers.core.unitdata.kv') |
1009 | + @mock.patch('reactive.jenkins_slave.write_default_conf') |
1010 | + @mock.patch('reactive.jenkins_slave.file_to_units') |
1011 | + def test_configure_jenkins_slave_master_url(self, file_to_units, write_default_conf, unitdata_kv, config, |
1012 | + set_flag, clear_flag): |
1013 | + config.return_value = {'master_url': 'http://10.1.1.1:8080'} |
1014 | + unitdata_kv.return_value = {} |
1015 | + configure_jenkins_slave() |
1016 | + self.assertEqual(write_default_conf.call_args_list, [mock.call('http://10.1.1.1:8080')]) |
1017 | + self.assertEqual(set_flag.call_args_list, [mock.call('jenkins-slave.configured')]) |
1018 | + expected = [mock.call('jenkins-slave.active'), mock.call('nagios-nrpe.configured')] |
1019 | + self.assertEqual(clear_flag.call_args_list, expected) |
1020 | + |
1021 | + @mock.patch('charms.reactive.clear_flag') |
1022 | + @mock.patch('charms.reactive.set_flag') |
1023 | + @mock.patch('charmhelpers.core.hookenv.config') |
1024 | + @mock.patch('charmhelpers.core.unitdata.kv') |
1025 | + @mock.patch('reactive.jenkins_slave.write_default_conf') |
1026 | + @mock.patch('reactive.jenkins_slave.file_to_units') |
1027 | + def test_configure_jenkins_slave_relation_url(self, file_to_units, write_default_conf, unitdata_kv, config, |
1028 | + set_flag, clear_flag): |
1029 | + config.return_value = {} |
1030 | + unitdata_kv.return_value = {'url': 'http://10.22.22.22:8080'} |
1031 | + configure_jenkins_slave() |
1032 | + print(write_default_conf.call_args_list) |
1033 | + self.assertEqual(write_default_conf.call_args_list, [mock.call('http://10.22.22.22:8080')]) |
1034 | + self.assertEqual(set_flag.call_args_list, [mock.call('jenkins-slave.configured')]) |
1035 | + expected = [mock.call('jenkins-slave.active'), mock.call('nagios-nrpe.configured')] |
1036 | + self.assertEqual(clear_flag.call_args_list, expected) |
1037 | + |
1038 | + def test_write_default_conf_update(self): |
1039 | + write_default_conf('http://10.1.1.1:8080', self.user, self.group, self.conf_file) |
1040 | + self.assertTrue(conf_match(self.conf_file, 'JENKINS_URL', 'http://10.1.1.1:8080')) |
1041 | + |
1042 | + def test_write_default_conf_reset(self): |
1043 | + write_default_conf(None, self.user, self.group, self.conf_file) |
1044 | + self.assertTrue(conf_match(self.conf_file, '#JENKINS_URL', '')) |
1045 | + |
1046 | + def test_file_to_units_executable_sh(self): |
1047 | + source = os.path.join(self.charm_dir, 'files/download-slave.sh') |
1048 | + dest = os.path.join(self.tmpdir, os.path.basename(source)) |
1049 | + file_to_units(source, dest, owner=self.user, group=self.group) |
1050 | + with open(dest, 'rb') as fh: |
1051 | + want = fh.read().decode('utf-8') |
1052 | + self.assertTrue(conf_equals(source, want)) |
1053 | + self.assertEqual(pwd.getpwuid(os.stat(dest).st_uid).pw_name, self.user) |
1054 | + self.assertEqual(grp.getgrgid(os.stat(dest).st_gid).gr_name, self.group) |
1055 | + self.assertTrue(os.access(dest, os.X_OK)) |
1056 | + |
1057 | + def test_file_to_units_executable_py(self): |
1058 | + source = os.path.join(self.charm_dir, 'tests/unit/files/somefile.py') |
1059 | + dest = os.path.join(self.tmpdir, os.path.basename(source)) |
1060 | + file_to_units(source, dest, owner=self.user, group=self.group) |
1061 | + with open(dest, 'rb') as fh: |
1062 | + want = fh.read().decode('utf-8') |
1063 | + self.assertTrue(conf_equals(source, want)) |
1064 | + self.assertEqual(pwd.getpwuid(os.stat(dest).st_uid).pw_name, self.user) |
1065 | + self.assertEqual(grp.getgrgid(os.stat(dest).st_gid).gr_name, self.group) |
1066 | + self.assertTrue(os.access(dest, os.X_OK)) |
1067 | + |
1068 | + def test_file_to_units_non_executable(self): |
1069 | + source = os.path.join(self.charm_dir, 'files/jenkins-slave-logrotate-config') |
1070 | + dest = os.path.join(self.tmpdir, os.path.basename(source)) |
1071 | + file_to_units(source, dest, owner=self.user, group=self.group) |
1072 | + with open(dest, 'rb') as fh: |
1073 | + want = fh.read().decode('utf-8') |
1074 | + self.assertTrue(conf_equals(dest, want)) |
1075 | + self.assertEqual(pwd.getpwuid(os.stat(dest).st_uid).pw_name, self.user) |
1076 | + self.assertEqual(grp.getgrgid(os.stat(dest).st_gid).gr_name, self.group) |
1077 | + self.assertFalse(os.access(dest, os.X_OK)) |
1078 | + |
1079 | + def test_file_to_units_non_executable_x_on_disk(self): |
1080 | + source = os.path.join(self.charm_dir, 'tests/unit/files/somefile') |
1081 | + dest = os.path.join(self.tmpdir, os.path.basename(source)) |
1082 | + file_to_units(source, dest, owner=self.user, group=self.group) |
1083 | + with open(dest, 'rb') as fh: |
1084 | + want = fh.read().decode('utf-8') |
1085 | + self.assertTrue(conf_equals(source, want)) |
1086 | + self.assertEqual(pwd.getpwuid(os.stat(dest).st_uid).pw_name, self.user) |
1087 | + self.assertEqual(grp.getgrgid(os.stat(dest).st_gid).gr_name, self.group) |
1088 | + self.assertFalse(os.access(dest, os.X_OK)) |
1089 | + |
1090 | + |
1091 | +def conf_equals(conf_file, want): |
1092 | + with open(conf_file, 'rb') as conf: |
1093 | + got = conf.read().decode('utf-8') |
1094 | + if got == want: |
1095 | + return True |
1096 | + print('{}\n != \n{}'.format(got, want)) |
1097 | + return False |
1098 | + |
1099 | + |
1100 | +def conf_match(conf_file, key, value): |
1101 | + with open(conf_file, 'rb') as conf: |
1102 | + for line in conf.readlines(): |
1103 | + line = line.decode('utf-8').rstrip('\n') |
1104 | + if line == '{}="{}"'.format(key, value): |
1105 | + return True |
1106 | + return False |
1107 | + |
1108 | + |
1109 | +if __name__ == '__main__': |
1110 | + unittest.main() |
1111 | |
1112 | === added file 'tox.ini' |
1113 | --- tox.ini 1970-01-01 00:00:00 +0000 |
1114 | +++ tox.ini 2019-03-01 05:39:53 +0000 |
1115 | @@ -0,0 +1,37 @@ |
1116 | +[tox] |
1117 | +skipsdist=True |
1118 | +envlist = unit, functional |
1119 | +skip_missing_interpreters = True |
1120 | + |
1121 | +[testenv] |
1122 | +basepython = python3 |
1123 | +setenv = |
1124 | + PYTHONPATH = . |
1125 | + |
1126 | +[testenv:unit] |
1127 | +commands = pytest -v --ignore {toxinidir}/tests/functional --cov=lib --cov=reactive --cov=actions --cov-report=term |
1128 | +deps = -r{toxinidir}/tests/unit/requirements.txt |
1129 | + -r{toxinidir}/requirements.txt |
1130 | +setenv = PYTHONPATH={toxinidir}/lib |
1131 | + |
1132 | +[testenv:functional] |
1133 | +passenv = |
1134 | + HOME |
1135 | + JUJU_REPOSITORY |
1136 | + PATH |
1137 | +commands = pytest -v --ignore {toxinidir}/tests/unit |
1138 | +deps = -r{toxinidir}/tests/functional/requirements.txt |
1139 | + -r{toxinidir}/requirements.txt |
1140 | + |
1141 | +[testenv:lint] |
1142 | +commands = flake8 |
1143 | +deps = flake8 |
1144 | + |
1145 | +[flake8] |
1146 | +exclude = |
1147 | + .git, |
1148 | + __pycache__, |
1149 | + .tox, |
1150 | + hooks/install.d/, |
1151 | +max-line-length = 120 |
1152 | +max-complexity = 10 |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.