yellow team mailing list archive
-
yellow team
-
Mailing list archive
-
Message #00536
[Merge] lp:~frankban/charms/oneiric/buildbot-master/upgrade-charm into lp:~yellow/charms/oneiric/buildbot-master/trunk
Francesco Banconi has proposed merging lp:~frankban/charms/oneiric/buildbot-master/upgrade-charm into lp:~yellow/charms/oneiric/buildbot-master/trunk.
Requested reviews:
Launchpad Yellow Squad (yellow)
For more details, see:
https://code.launchpad.net/~frankban/charms/oneiric/buildbot-master/upgrade-charm/+merge/95535
== Changes ==
- Added upgrade-charm symlink
- Updated helpers (with some refactoring to functions running "juju status")
- Updated install hook: now it runs config-changed during charm upgrade
- Some changes in functional tests
The file helper.py is in sync with the one present in
lp:~frankban/charms/oneiric/buildbot-slave/upgrade-charm
Currently the upgrade-charm test does not work due to a bug of juju:
see https://bugs.launchpad.net/juju/+bug/941873
--
https://code.launchpad.net/~frankban/charms/oneiric/buildbot-master/upgrade-charm/+merge/95535
Your team Launchpad Yellow Squad is requested to review the proposed merge of lp:~frankban/charms/oneiric/buildbot-master/upgrade-charm into lp:~yellow/charms/oneiric/buildbot-master/trunk.
=== modified file 'hooks/buildbot-relation-broken'
--- hooks/buildbot-relation-broken 2012-02-13 15:59:35 +0000
+++ hooks/buildbot-relation-broken 2012-03-02 11:26:19 +0000
@@ -3,12 +3,12 @@
# Copyright 2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from shelltoolbox import su
from helpers import (
log,
log_entry,
log_exit,
run,
- su,
)
from local import (
buildbot_reconfig,
=== modified file 'hooks/config-changed'
--- hooks/config-changed 2012-02-29 22:43:30 +0000
+++ hooks/config-changed 2012-03-02 11:26:19 +0000
@@ -78,7 +78,7 @@
install_extra_repositories(extra_repo)
except subprocess.CalledProcessError as e:
log('Error adding repository: ' + extra_repo)
- log(e)
+ log(str(e))
raise
restart_required = True
if extra_pkgs and 'extra-packages' in added_or_changed:
=== modified file 'hooks/helpers.py'
--- hooks/helpers.py 2012-02-29 22:43:30 +0000
+++ hooks/helpers.py 2012-03-02 11:26:19 +0000
@@ -6,15 +6,21 @@
__metaclass__ = type
__all__ = [
'get_config',
+ 'juju_status',
'log',
'log_entry',
'log_exit',
+ 'make_charm_config_file',
'relation_get',
'relation_set',
'unit_info',
+ 'wait_for_machine',
+ 'wait_for_page_contents',
+ 'wait_for_relation',
+ 'wait_for_unit',
]
-from collections import namedtuple
+from contextlib import contextmanager
import json
import operator
from shelltoolbox import (
@@ -22,14 +28,13 @@
run,
script_name,
)
+import os
import tempfile
import time
import urllib2
import yaml
-Env = namedtuple('Env', 'uid gid home')
-
log = command('juju-log')
@@ -67,10 +72,18 @@
return charm_config_file
+def juju_status(key):
+ return yaml.safe_load(run('juju', 'status'))[key]
+
+
+def get_charm_revision(service_name):
+ service = juju_status('services')[service_name]
+ return int(service['charm'].split('-')[-1])
+
+
def unit_info(service_name, item_name, data=None):
- if data is None:
- data = yaml.safe_load(run('juju', 'status'))
- service = data['services'].get(service_name)
+ services = juju_status('services') if data is None else data['services']
+ service = services.get(service_name)
if service is None:
# XXX 2012-02-08 gmb:
# This allows us to cope with the race condition that we
@@ -83,8 +96,27 @@
return item
-def get_machine_data():
- return yaml.safe_load(run('juju', 'status'))['machines']
+@contextmanager
+def maintain_charm_revision(path=None):
+ if path is None:
+ path = os.path.join(os.path.dirname(__file__), '..', 'revision')
+ revision = open(path).read()
+ try:
+ yield revision
+ finally:
+ with open(path, 'w') as f:
+ f.write(revision)
+
+
+def upgrade_charm(service_name, timeout=120):
+ next_revision = get_charm_revision(service_name) + 1
+ start_time = time.time()
+ run('juju', 'upgrade-charm', service_name)
+ while get_charm_revision(service_name) != next_revision:
+ if time.time() - start_time >= timeout:
+ raise RuntimeError('timeout waiting for charm to be upgraded')
+ time.sleep(0.1)
+ return next_revision
def wait_for_machine(num_machines=1, timeout=300):
@@ -98,7 +130,7 @@
# to tell what environment we're working in (LXC vs EC2) is to check
# the dns-name of the first machine. If it's localhost we're in LXC
# and we can just return here.
- if get_machine_data()[0]['dns-name'] == 'localhost':
+ if juju_status('machines')[0]['dns-name'] == 'localhost':
return
start_time = time.time()
while True:
@@ -106,7 +138,7 @@
# not a machine that we need to wait for. This will only work
# for EC2 environments, which is why we return early above if
# we're in LXC.
- machine_data = get_machine_data()
+ machine_data = juju_status('machines')
non_zookeeper_machines = [
machine_data[key] for key in machine_data.keys()[1:]]
if len(non_zookeeper_machines) >= num_machines:
=== modified file 'hooks/install'
--- hooks/install 2012-03-01 14:06:36 +0000
+++ hooks/install 2012-03-02 11:26:19 +0000
@@ -110,10 +110,12 @@
old_config = config_json.get()
buildbot_dir = old_config.get('installdir', config['installdir'])
cleanup(buildbot_dir)
+ if os.path.basename(__file__) == 'upgrade-charm':
+ log('Running config-changed from upgrade-charm hook.')
+ run('hooks/config-changed')
if __name__ == '__main__':
-
log_entry()
try:
main()
=== added symlink 'hooks/upgrade-charm'
=== target is u'install'
=== modified file 'revision'
--- revision 2012-02-29 09:57:12 +0000
+++ revision 2012-03-02 11:26:19 +0000
@@ -1,2 +1,1 @@
1
-
=== modified file 'tests/buildbot-master.test'
--- tests/buildbot-master.test 2012-02-13 10:59:34 +0000
+++ tests/buildbot-master.test 2012-03-02 11:26:19 +0000
@@ -5,11 +5,14 @@
from helpers import (
command,
make_charm_config_file,
+ maintain_charm_revision,
unit_info,
+ upgrade_charm,
wait_for_page_contents,
wait_for_unit,
)
import os.path
+import time
import unittest
juju = command('juju')
@@ -27,27 +30,35 @@
additional_args.append('--config=' + charm_config_file.name)
juju('deploy', 'buildbot-master', *additional_args)
wait_for_unit('buildbot-master')
+
+ def expose_and_check_page(self):
juju('expose', 'buildbot-master')
addr = unit_info('buildbot-master', 'public-address')
url = 'http://{}:8010'.format(addr)
wait_for_page_contents(url, 'Welcome to the Buildbot')
+ def get_config_file_contents(self):
+ bb_config_path = os.path.join(os.path.dirname(__file__), 'test.cfg')
+ return open(bb_config_path).read()
+
+ def get_config(self):
+ return {
+ 'buildbot-master': {
+ 'extra-packages': 'git',
+ 'installdir': '/tmp/buildbot',
+ 'config-file': self.get_config_file_contents(),
+ }}
+
def test_port_opened(self):
# Deploying a buildbot master should result in it opening a port and
# serving its status via HTTP.
- bb_config_path = os.path.join(os.path.dirname(__file__), 'test.cfg')
- charm_config = {
- 'buildbot-master': {
- 'extra-packages': 'git',
- 'installdir': '/tmp/buildbot',
- 'config-file': open(bb_config_path).read(),
- }}
- self.deploy(charm_config)
+ self.deploy(self.get_config())
+ self.expose_and_check_page()
def test_lpbuildbot(self):
# Deploying a Launchpad-specific buildbot master does a good job of
# exercising the configuration parameters. For example, the
- # configuration in this test adds a repositroy (lucid main universe),
+ # configuration in this test adds a repository (lucid main universe),
# installs a non-default buildbot package, and fetches the buildbot
# configuration from bzr.
charm_config = {
@@ -62,6 +73,17 @@
'installdir': '/var/lib/buildbot/masters/lpbuildbot',
}}
self.deploy(charm_config)
+ self.expose_and_check_page()
+
+ def test_upgrade_charm(self):
+ # Ensure the charm can be upgraded without errors.
+ self.deploy(self.get_config())
+ with maintain_charm_revision():
+ upgrade_charm('buildbot-master')
+ # Wait for the charm to upgrade using sleep, since there is no
+ # other confirmation at the moment but the state to remain 'started'.
+ time.sleep(10)
+ self.expose_and_check_page()
if __name__ == '__main__':
Follow ups