~yellow/charms/oneiric/buildbot-master/trunk

« back to all changes in this revision

Viewing changes to hooks/config-changed

  • Committer: Brad Crittenden
  • Date: 2012-02-03 14:21:51 UTC
  • mfrom: (8.1.11 wip)
  • Revision ID: bac@canonical.com-20120203142151-1xdzrpqismvjefpm
[r=gary_poster] Fix config-changed to save state and only modify items that have changed.  More helpers and tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
2
 
3
 
from helpers import command, Config, run
 
3
from helpers import (
 
4
    command,
 
5
    DictDiffer,
 
6
    get_config,
 
7
    install_extra_repository,
 
8
    load_pickle,
 
9
    save_pickle,
 
10
    run,
 
11
    )
4
12
from subprocess import CalledProcessError
5
13
import base64
6
14
import os
7
15
import os.path
8
 
 
 
16
import sys
9
17
 
10
18
# config_file is changed via juju like:
11
19
# juju set buildbot-master config-file=`uuencode master.cfg`
12
20
 
 
21
CONFIG_PICKLE = "config.pkl"
 
22
REQUIRED_KEYS = [
 
23
    'buildbot-pkg',
 
24
    'installdir',
 
25
    ]
 
26
SUPPORTED_TRANSPORTS = ['bzr']
 
27
 
 
28
restart_required = False
 
29
 
13
30
log = command('juju-log')
14
31
bzr = command('bzr')
 
32
apt_get_install = command('apt-get', 'install', '-y', '--force-yes')
15
33
 
16
34
# Log the fact that we're about to begin the install step.
17
35
log('--> config-changed')
18
36
 
19
 
config = Config()
20
 
buildbot_dir =  config['installdir']
21
 
config_file = config['config-file']
22
 
config_transport = config['config-transport']
23
 
config_url = config['config-url']
 
37
config = get_config()
 
38
log(str(config))
 
39
 
 
40
# If all of the required keys are not present in the configuration then exit
 
41
# with an error.
 
42
if not all(config.get(k) for k in REQUIRED_KEYS):
 
43
    log('All required items not configured: {}'.format(REQUIRED_KEYS))
 
44
    log(str(config))
 
45
    sys.exit(1)
 
46
 
 
47
prev_config = load_pickle(CONFIG_PICKLE)
 
48
diff = DictDiffer(config, prev_config)
 
49
 
 
50
if not diff.modified:
 
51
    log("No configuration changes, exiting.")
 
52
    sys.exit(0)
24
53
 
25
54
log('Updating buildbot configuration.')
 
55
log('Configuration changes seen:')
 
56
log(str(diff))
 
57
 
 
58
buildbot_pkg = config.get('buildbot-pkg')
 
59
buildbot_dir =  config.get('installdir')
 
60
config_file = config.get('config-file')
 
61
config_transport = config.get('config-transport')
 
62
config_url = config.get('config-url')
 
63
extra_repo = config.get('extra-repository')
 
64
extra_pkgs = config.get('extra-packages')
 
65
 
 
66
# Add a new repository if it was just added.
 
67
if extra_repo and 'extra-repository' in diff.added_or_changed:
 
68
    install_extra_repository(extra_repo)
 
69
    restart_required = True
 
70
 
 
71
if extra_pkgs and 'extra_packages' not in diff.unchanged:
 
72
    apt_get_install(extra_pkgs)
 
73
    restart_required = True
 
74
 
 
75
if 'buildbot-pkg' not in diff.unchanged:
 
76
    apt_get_install(buildbot_pkg)
 
77
    restart_required = True
 
78
 
 
79
# Ensure the install directory exists.
 
80
if not os.path.exists(buildbot_dir):
 
81
    os.makedirs(buildbot_dir)
 
82
 
 
83
# If asked to fetch the config file then it must be a transport we support.
 
84
if config_url and config_transport not in SUPPORTED_TRANSPORTS:
 
85
    log("{} is an unsupported transport".format(config_transport))
 
86
    sys.exit(1)
 
87
 
26
88
# Write the buildbot config to disk (fetching it if necessary).
27
 
if config_file:
 
89
if config_file and 'config-file' not in diff.unchanged:
 
90
    if not os.path.exists(buildbot_dir):
 
91
        os.makedirs(buildbot_dir)
28
92
    with open(os.path.join(buildbot_dir, 'master.cfg', 'w')) as f:
29
93
        f.write(base64.decode(config_file))
30
 
    log('Config decoded and written.')
31
 
elif config_transport == 'bzr' and config_url:
 
94
    log('config_file decoded and written.')
 
95
    restart_required = True
 
96
elif (config_transport == 'bzr' and config_url and
 
97
      'config-transport' not in diff.unchanged and
 
98
      'config-url' not in diff.unchanged):
32
99
    # If the branch is private then more setup needs to be done.  The
33
100
    # gpg-agent needs to send the key over and the bzr launchpad-login
34
 
    # needs to be set. 
35
 
    lp_id = config['config-user']
 
101
    # needs to be set.
 
102
    lp_id = config.get('config-user')
36
103
    if lp_id:
37
104
        bzr('launchpad-login', lp_id)
38
105
 
39
 
    private_key = config['config-private-key']
 
106
    private_key = config.get('config-private-key')
40
107
    if private_key:
41
108
        # Set up the .ssh directory.
42
109
        ssh_dir = os.expanduser('~/.ssh')
44
111
        os.chmod(ssh_dir, 0700)
45
112
        with open(os.path.join(ssh_dir, 'lp_key', w)) as f:
46
113
            f.write(base64.decode(private_key))
47
 
 
48
114
    bzr('branch', '--use-existing-dir', config_url, buildbot_dir)
49
115
    run('chown', '-R', 'ubuntu:ubuntu', buildbot_dir)
 
116
    log('configuration fetched from {}'.format(config_url))
 
117
    restart_required = True
50
118
else:
51
 
    # XXX Is it an error to get to this point?
 
119
    # Configuration file specifiers are unchanged or unrecognized.
52
120
    pass
53
121
 
54
122
# Restart buildbot if it is running.
55
 
pidfile = os.path.join(buildbot_dir, 'twistd.pid')
56
 
if os.path.exists(pidfile):
57
 
    buildbot_pid = open(pidfile).read().strip()
58
 
    try:
59
 
        # Is buildbot running?
60
 
        run('kill', '-0', buildbot_pid)
61
 
    except CalledProcessError:
62
 
        # Buildbot isn't running, so no need to reconfigure it.
63
 
        pass
 
123
if restart_required:
 
124
    pidfile = os.path.join(buildbot_dir, 'twistd.pid')
 
125
    if os.path.exists(pidfile):
 
126
        buildbot_pid = open(pidfile).read().strip()
 
127
        try:
 
128
            # Is buildbot running?
 
129
            run('kill', '-0', buildbot_pid)
 
130
        except CalledProcessError:
 
131
            # Buildbot isn't running, so no need to reconfigure it.
 
132
            pass
 
133
        else:
 
134
            # Buildbot is running, reconfigure it.
 
135
            log('Reconfiguring buildbot')
 
136
            run('buildbot', 'reconfig', buildbot_dir)
 
137
            log('Buildbot reconfigured')
64
138
    else:
65
 
        # Buildbot is running, reconfigure it.
66
 
        log('Reconfiguring buildbot')
67
 
        run('buildbot', 'reconfig', buildbot_dir)
68
 
        log('Buildbot reconfigured')
 
139
        # Buildbot isn't running so start afresh but only if properly
 
140
        # configured.
 
141
        if os.path.exists(os.path.join(buildbot_dir, 'master.cfg')):
 
142
            run('buildbot', 'start', buildbot_dir)
 
143
else:
 
144
    log("Configuration changed but didn't require restarting.")
 
145
 
 
146
save_pickle(config, CONFIG_PICKLE)
69
147
 
70
148
log('<-- config-changed')