← Back to team overview

yellow team mailing list archive

[Merge] lp:~frankban/charms/oneiric/buildbot-slave/initial into lp:~yellow/charms/oneiric/buildbot-slave/trunk

 

Francesco Banconi has proposed merging lp:~frankban/charms/oneiric/buildbot-slave/initial into lp:~yellow/charms/oneiric/buildbot-slave/trunk.

Requested reviews:
  Gary Poster (gary)

For more details, see:
https://code.launchpad.net/~frankban/charms/oneiric/buildbot-slave/initial/+merge/90739

Fisr working implementation of the buildbot slave charm.
-- 
https://code.launchpad.net/~frankban/charms/oneiric/buildbot-slave/initial/+merge/90739
Your team Launchpad Yellow Squad is subscribed to branch lp:~yellow/charms/oneiric/buildbot-slave/trunk.
=== added file 'HANDOFF.txt'
--- HANDOFF.txt	1970-01-01 00:00:00 +0000
+++ HANDOFF.txt	2012-01-30 17:26:26 +0000
@@ -0,0 +1,73 @@
+--------------------------------------------------
+Tue Jan 17 20:55:21 2012
+
+Poor Man's 'juju debug-log':
+
+(On the client)
+root@ip-10-116-73-15:/# grep unit.hook.api /var/lib/juju/units/buildbot-master-7/charm.log
+2012-01-17 20:51:17,315: unit.hook.api@INFO: --> install
+2012-01-17 20:51:20,588: unit.hook.api@INFO: Creating master in /tmp/buildbot
+2012-01-17 20:51:23,539: unit.hook.api@INFO: <-- install
+2012-01-17 20:51:24,883: unit.hook.api@INFO: --> config-changed
+2012-01-17 20:51:25,561: unit.hook.api@INFO: Updating buildbot configuration.
+2012-01-17 20:51:26,811: unit.hook.api@INFO: Config decoded and written.
+2012-01-17 20:51:27,406: unit.hook.api@INFO: <-- config-changed
+2012-01-17 20:51:28,793: unit.hook.api@INFO: --> start
+2012-01-17 20:51:30,613: unit.hook.api@DEBUG: opened 8010/tcp
+2012-01-17 20:51:31,258: unit.hook.api@INFO: <-- start
+
+Note that if you have a config.yaml file, the config-changed hook will
+fire before the start hook.  So commands that assume start has been
+called will fail.  Work-around is to test that the service is running
+before trying a 'restart' or 'reconfig'.
+
+--------------------------------------------------
+Mon Jan 16 21:56:10 2012
+
+In order to get around the problems with the config file being passed
+as a BAS (big-ass string) I attempted to uuencode it, with some decent
+results.
+
+Currently a deploy is resulting is going into an 'install_error'.  It
+looks like multiple buildbots are running (twistd complains about not
+having access to the port).
+
+Using debug-hooks[1] has been useful, though sometimes it fails
+miserable, a la:
+
+% /var/lib/juju/units/buildbot-master-9/charm/hooks/install
+++ config-get installdir
+usage: config-get [-h] [-o OUTPUT] [-s SOCKET] [--client-id CLIENT_ID]
+                  [--format FORMAT] [--log-file FILE]
+                  [--log-level CRITICAL|DEBUG|INFO|ERROR|WARNING]
+                  [option_name]
+No JUJU_AGENT_SOCKET/-s option found
++ BUILDBOT_DIR=
+
+[1] Locally,
+% juju resolved --retry buildbot-master/9
+then
+% juju debug-hooks buildbot-master/9
+(for various values of '9')
+
+
+To update the master.cfg you can do the following:
+% juju set buildbot-master config="$(uuencode -m buildbot-master/configuration/master.cfg.lp master.cfg)"
+
+(The only difference with this file from the example master.cfg is
+that the slave password is "launchpad".  If you run the above
+successfully you can observer /tmp/buildbot/master.cfg has been updated.
+
+Unfortunately 'juju expose' does not open any ports.  'juju status'
+shows it as 'exposed: true' but with no open ports.
+
+
+Problems
+--------
+
+I made the branch lp:~yellow/launchpad/buildbot-master which probably
+messed you up since there was a mismatch with the name in
+metadata.yaml.  You fixed it in the file.  Then I fetched the branch
+and named it locally 'buildbot' again.  So I then had a mismatch and
+juju refused to find the charm.  Took me an absurdly long time to
+figure that out, since I could see the charm plainly.  Argh.

=== added file 'config.yaml'
--- config.yaml	1970-01-01 00:00:00 +0000
+++ config.yaml	2012-01-30 17:26:26 +0000
@@ -0,0 +1,45 @@
+options:
+  installdir:
+    description: |
+      The directory where the Buildbot master will be installed.
+    type: string
+    default: /tmp/buildbot
+  config-file:
+    description: |
+        A uuencoded master.cfg file.  Use of this configuration is
+        mutually exclusive with the use of config-transport,
+        config-url.  Use it like:
+          juju set buildbot-master config-file `uuencode master.cfg`
+    type: string
+  config-transport:
+    description: |
+      The command transport for fetching the configuration directory
+      from the `config-url`.  Must be one of [bzr, rsync].  If adding a
+      new supported protocol, ensure the program is installed in the
+      `start` hook and that it is properly handled in the
+      `config-changed` hook.
+    type: string
+  config-url:
+    description: |
+       The location the buildbot master configuration is to be
+       fetched.  It must be compatible with the `config-transport`.
+    type: string
+  config-user:
+    description: |
+      The user for access to a restricted URL.
+    type: string
+  config-private-key:
+    description: |
+      The private key for `config-user`.
+    type: string
+  slave-name:
+    description: |
+      The name of this slave.
+    type: string
+    default: example-slave
+  slave-passwd:
+    description: |
+      The password of this slave.
+    type: string
+    default: pass
+

=== added directory 'configuration'
=== added file 'configuration/master.cfg.b64'
--- configuration/master.cfg.b64	1970-01-01 00:00:00 +0000
+++ configuration/master.cfg.b64	2012-01-30 17:26:26 +0000
@@ -0,0 +1,93 @@
+begin-base64 664 master.cfg
+IyAtKi0gcHl0aG9uIC0qLQojIGV4OiBzZXQgc3ludGF4PXB5dGhvbjoKCiMg
+VGhpcyBpcyBhIHNhbXBsZSBidWlsZG1hc3RlciBjb25maWcgZmlsZS4gSXQg
+bXVzdCBiZSBpbnN0YWxsZWQgYXMKIyAnbWFzdGVyLmNmZycgaW4geW91ciBi
+dWlsZG1hc3RlcidzIGJhc2UgZGlyZWN0b3J5LgoKIyBUaGlzIGlzIHRoZSBk
+aWN0aW9uYXJ5IHRoYXQgdGhlIGJ1aWxkbWFzdGVyIHBheXMgYXR0ZW50aW9u
+IHRvLiBXZSBhbHNvIHVzZQojIGEgc2hvcnRlciBhbGlhcyB0byBzYXZlIHR5
+cGluZy4KYyA9IEJ1aWxkbWFzdGVyQ29uZmlnID0ge30KCiMjIyMjIyMgQlVJ
+TERTTEFWRVMKCiMgVGhlICdzbGF2ZXMnIGxpc3QgZGVmaW5lcyB0aGUgc2V0
+IG9mIHJlY29nbml6ZWQgYnVpbGRzbGF2ZXMuIEVhY2ggZWxlbWVudCBpcwoj
+IGEgQnVpbGRTbGF2ZSBvYmplY3QsIHNwZWNpZnlpbmcgYSB1c2VybmFtZSBh
+bmQgcGFzc3dvcmQuICBUaGUgc2FtZSB1c2VybmFtZSBhbmQKIyBwYXNzd29y
+ZCBtdXN0IGJlIGNvbmZpZ3VyZWQgb24gdGhlIHNsYXZlLgpmcm9tIGJ1aWxk
+Ym90LmJ1aWxkc2xhdmUgaW1wb3J0IEJ1aWxkU2xhdmUKY1snc2xhdmVzJ10g
+PSBbQnVpbGRTbGF2ZSgiZXhhbXBsZS1zbGF2ZSIsICJwYXNzIildCgojICdz
+bGF2ZVBvcnRudW0nIGRlZmluZXMgdGhlIFRDUCBwb3J0IHRvIGxpc3RlbiBv
+biBmb3IgY29ubmVjdGlvbnMgZnJvbSBzbGF2ZXMuCiMgVGhpcyBtdXN0IG1h
+dGNoIHRoZSB2YWx1ZSBjb25maWd1cmVkIGludG8gdGhlIGJ1aWxkc2xhdmVz
+ICh3aXRoIHRoZWlyCiMgLS1tYXN0ZXIgb3B0aW9uKQpjWydzbGF2ZVBvcnRu
+dW0nXSA9IDk5ODkKCiMjIyMjIyMgQ0hBTkdFU09VUkNFUwoKIyB0aGUgJ2No
+YW5nZV9zb3VyY2UnIHNldHRpbmcgdGVsbHMgdGhlIGJ1aWxkbWFzdGVyIGhv
+dyBpdCBzaG91bGQgZmluZCBvdXQKIyBhYm91dCBzb3VyY2UgY29kZSBjaGFu
+Z2VzLiAgSGVyZSB3ZSBwb2ludCB0byB0aGUgYnVpbGRib3QgY2xvbmUgb2Yg
+cHlmbGFrZXMuCgpmcm9tIGJ1aWxkYm90LmNoYW5nZXMuZ2l0cG9sbGVyIGlt
+cG9ydCBHaXRQb2xsZXIKY1snY2hhbmdlX3NvdXJjZSddID0gR2l0UG9sbGVy
+KAogICAgICAgICdnaXQ6Ly9naXRodWIuY29tL2J1aWxkYm90L3B5Zmxha2Vz
+LmdpdCcsCiAgICAgICAgYnJhbmNoPSdtYXN0ZXInLCBwb2xsaW50ZXJ2YWw9
+MTIwMCkKCiMjIyMjIyMgU0NIRURVTEVSUwoKIyBDb25maWd1cmUgdGhlIFNj
+aGVkdWxlcnMsIHdoaWNoIGRlY2lkZSBob3cgdG8gcmVhY3QgdG8gaW5jb21p
+bmcgY2hhbmdlcy4gIEluIHRoaXMKIyBjYXNlLCBqdXN0IGtpY2sgb2ZmIGEg
+J3J1bnRlc3RzJyBidWlsZAoKZnJvbSBidWlsZGJvdC5zY2hlZHVsZXIgaW1w
+b3J0IFNjaGVkdWxlcgpjWydzY2hlZHVsZXJzJ10gPSBbXQpjWydzY2hlZHVs
+ZXJzJ10uYXBwZW5kKFNjaGVkdWxlcihuYW1lPSJhbGwiLCBicmFuY2g9Tm9u
+ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJlZVN0YWJs
+ZVRpbWVyPU5vbmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+IGJ1aWxkZXJOYW1lcz1bInJ1bnRlc3RzIl0pKQoKIyMjIyMjIyBCVUlMREVS
+UwoKIyBUaGUgJ2J1aWxkZXJzJyBsaXN0IGRlZmluZXMgdGhlIEJ1aWxkZXJz
+LCB3aGljaCB0ZWxsIEJ1aWxkYm90IGhvdyB0byBwZXJmb3JtIGEgYnVpbGQ6
+CiMgd2hhdCBzdGVwcywgYW5kIHdoaWNoIHNsYXZlcyBjYW4gZXhlY3V0ZSB0
+aGVtLiAgTm90ZSB0aGF0IGFueSBwYXJ0aWN1bGFyIGJ1aWxkIHdpbGwKIyBv
+bmx5IHRha2UgcGxhY2Ugb24gb25lIHNsYXZlLgoKZnJvbSBidWlsZGJvdC5w
+cm9jZXNzLmZhY3RvcnkgaW1wb3J0IEJ1aWxkRmFjdG9yeQpmcm9tIGJ1aWxk
+Ym90LnN0ZXBzLnNvdXJjZSBpbXBvcnQgR2l0CmZyb20gYnVpbGRib3Quc3Rl
+cHMuc2hlbGwgaW1wb3J0IFNoZWxsQ29tbWFuZAoKZmFjdG9yeSA9IEJ1aWxk
+RmFjdG9yeSgpCiMgY2hlY2sgb3V0IHRoZSBzb3VyY2UKZmFjdG9yeS5hZGRT
+dGVwKEdpdChyZXBvdXJsPSdnaXQ6Ly9naXRodWIuY29tL2J1aWxkYm90L3B5
+Zmxha2VzLmdpdCcsIG1vZGU9J2NvcHknKSkKIyBydW4gdGhlIHRlc3RzIChu
+b3RlIHRoYXQgdGhpcyB3aWxsIHJlcXVpcmUgdGhhdCAndHJpYWwnIGlzIGlu
+c3RhbGxlZCkKZmFjdG9yeS5hZGRTdGVwKFNoZWxsQ29tbWFuZChjb21tYW5k
+PVsidHJpYWwiLCAicHlmbGFrZXMiXSkpCgpmcm9tIGJ1aWxkYm90LmNvbmZp
+ZyBpbXBvcnQgQnVpbGRlckNvbmZpZwoKY1snYnVpbGRlcnMnXSA9IFtdCmNb
+J2J1aWxkZXJzJ10uYXBwZW5kKAogICAgQnVpbGRlckNvbmZpZyhuYW1lPSJy
+dW50ZXN0cyIsCiAgICAgIHNsYXZlbmFtZXM9WyJleGFtcGxlLXNsYXZlIl0s
+CiAgICAgIGZhY3Rvcnk9ZmFjdG9yeSkpCgojIyMjIyMjIFNUQVRVUyBUQVJH
+RVRTCgojICdzdGF0dXMnIGlzIGEgbGlzdCBvZiBTdGF0dXMgVGFyZ2V0cy4g
+VGhlIHJlc3VsdHMgb2YgZWFjaCBidWlsZCB3aWxsIGJlCiMgcHVzaGVkIHRv
+IHRoZXNlIHRhcmdldHMuIGJ1aWxkYm90L3N0YXR1cy8qLnB5IGhhcyBhIHZh
+cmlldHkgdG8gY2hvb3NlIGZyb20sCiMgaW5jbHVkaW5nIHdlYiBwYWdlcywg
+ZW1haWwgc2VuZGVycywgYW5kIElSQyBib3RzLgoKY1snc3RhdHVzJ10gPSBb
+XQoKZnJvbSBidWlsZGJvdC5zdGF0dXMgaW1wb3J0IGh0bWwKZnJvbSBidWls
+ZGJvdC5zdGF0dXMud2ViIGltcG9ydCBhdXRoLCBhdXRoegphdXRoel9jZmc9
+YXV0aHouQXV0aHooCiAgICAjIGNoYW5nZSBhbnkgb2YgdGhlc2UgdG8gVHJ1
+ZSB0byBlbmFibGU7IHNlZSB0aGUgbWFudWFsIGZvciBtb3JlCiAgICAjIG9w
+dGlvbnMKICAgIGdyYWNlZnVsU2h1dGRvd24gPSBGYWxzZSwKICAgIGZvcmNl
+QnVpbGQgPSBUcnVlLCAjIHVzZSB0aGlzIHRvIHRlc3QgeW91ciBzbGF2ZSBv
+bmNlIGl0IGlzIHNldCB1cAogICAgZm9yY2VBbGxCdWlsZHMgPSBGYWxzZSwK
+ICAgIHBpbmdCdWlsZGVyID0gRmFsc2UsCiAgICBzdG9wQnVpbGQgPSBGYWxz
+ZSwKICAgIHN0b3BBbGxCdWlsZHMgPSBGYWxzZSwKICAgIGNhbmNlbFBlbmRp
+bmdCdWlsZCA9IEZhbHNlLAopCmNbJ3N0YXR1cyddLmFwcGVuZChodG1sLldl
+YlN0YXR1cyhodHRwX3BvcnQ9ODAxMCwgYXV0aHo9YXV0aHpfY2ZnKSkKCiMj
+IyMjIyMgUFJPSkVDVCBJREVOVElUWQoKIyB0aGUgJ3Byb2plY3ROYW1lJyBz
+dHJpbmcgd2lsbCBiZSB1c2VkIHRvIGRlc2NyaWJlIHRoZSBwcm9qZWN0IHRo
+YXQgdGhpcwojIGJ1aWxkYm90IGlzIHdvcmtpbmcgb24uIEZvciBleGFtcGxl
+LCBpdCBpcyB1c2VkIGFzIHRoZSB0aXRsZSBvZiB0aGUKIyB3YXRlcmZhbGwg
+SFRNTCBwYWdlLiBUaGUgJ3Byb2plY3RVUkwnIHN0cmluZyB3aWxsIGJlIHVz
+ZWQgdG8gcHJvdmlkZSBhIGxpbmsKIyBmcm9tIGJ1aWxkYm90IEhUTUwgcGFn
+ZXMgdG8geW91ciBwcm9qZWN0J3MgaG9tZSBwYWdlLgoKY1sncHJvamVjdE5h
+bWUnXSA9ICJQeWZsYWtlcyIKY1sncHJvamVjdFVSTCddID0gImh0dHA6Ly9k
+aXZtb2Qub3JnL3RyYWMvd2lraS9EaXZtb2RQeWZsYWtlcyIKCiMgdGhlICdi
+dWlsZGJvdFVSTCcgc3RyaW5nIHNob3VsZCBwb2ludCB0byB0aGUgbG9jYXRp
+b24gd2hlcmUgdGhlIGJ1aWxkYm90J3MKIyBpbnRlcm5hbCB3ZWIgc2VydmVy
+ICh1c3VhbGx5IHRoZSBodG1sLldlYlN0YXR1cyBwYWdlKSBpcyB2aXNpYmxl
+LiBUaGlzCiMgdHlwaWNhbGx5IHVzZXMgdGhlIHBvcnQgbnVtYmVyIHNldCBp
+biB0aGUgV2F0ZXJmYWxsICdzdGF0dXMnIGVudHJ5LCBidXQKIyB3aXRoIGFu
+IGV4dGVybmFsbHktdmlzaWJsZSBob3N0IG5hbWUgd2hpY2ggdGhlIGJ1aWxk
+Ym90IGNhbm5vdCBmaWd1cmUgb3V0CiMgd2l0aG91dCBzb21lIGhlbHAuCgpj
+WydidWlsZGJvdFVSTCddID0gImh0dHA6Ly9sb2NhbGhvc3Q6ODAxMC8iCgoj
+IyMjIyMjIERCIFVSTAoKIyBUaGlzIHNwZWNpZmllcyB3aGF0IGRhdGFiYXNl
+IGJ1aWxkYm90IHVzZXMgdG8gc3RvcmUgY2hhbmdlIGFuZCBzY2hlZHVsZXIK
+IyBzdGF0ZS4gIFlvdSBjYW4gbGVhdmUgdGhpcyBhdCBpdHMgZGVmYXVsdCBm
+b3IgYWxsIGJ1dCB0aGUgbGFyZ2VzdAojIGluc3RhbGxhdGlvbnMuCmNbJ2Ri
+X3VybCddID0gInNxbGl0ZTovLy9zdGF0ZS5zcWxpdGUiCgo=
+====

=== added file 'configuration/master.cfg.lp'
--- configuration/master.cfg.lp	1970-01-01 00:00:00 +0000
+++ configuration/master.cfg.lp	2012-01-30 17:26:26 +0000
@@ -0,0 +1,115 @@
+# -*- python -*-
+# ex: set syntax=python:
+
+# This is a sample buildmaster config file. It must be installed as
+# 'master.cfg' in your buildmaster's base directory.
+
+# This is the dictionary that the buildmaster pays attention to. We also use
+# a shorter alias to save typing.
+c = BuildmasterConfig = {}
+
+####### BUILDSLAVES
+
+# The 'slaves' list defines the set of recognized buildslaves. Each element is
+# a BuildSlave object, specifying a username and password.  The same username and
+# password must be configured on the slave.
+from buildbot.buildslave import BuildSlave
+c['slaves'] = [BuildSlave("example-slave", "launchpad")]
+
+# 'slavePortnum' defines the TCP port to listen on for connections from slaves.
+# This must match the value configured into the buildslaves (with their
+# --master option)
+c['slavePortnum'] = 9989
+
+####### CHANGESOURCES
+
+# the 'change_source' setting tells the buildmaster how it should find out
+# about source code changes.  Here we point to the buildbot clone of pyflakes.
+
+from buildbot.changes.gitpoller import GitPoller
+c['change_source'] = GitPoller(
+        'git://github.com/buildbot/pyflakes.git',
+        branch='master', pollinterval=1200)
+
+####### SCHEDULERS
+
+# Configure the Schedulers, which decide how to react to incoming changes.  In this
+# case, just kick off a 'runtests' build
+
+from buildbot.scheduler import Scheduler
+c['schedulers'] = []
+c['schedulers'].append(Scheduler(name="all", branch=None,
+                                 treeStableTimer=None,
+                                 builderNames=["runtests"]))
+
+####### BUILDERS
+
+# The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
+# what steps, and which slaves can execute them.  Note that any particular build will
+# only take place on one slave.
+
+from buildbot.process.factory import BuildFactory
+from buildbot.steps.source import Git
+from buildbot.steps.shell import ShellCommand
+
+factory = BuildFactory()
+# check out the source
+factory.addStep(Git(repourl='git://github.com/buildbot/pyflakes.git', mode='copy'))
+# run the tests (note that this will require that 'trial' is installed)
+factory.addStep(ShellCommand(command=["trial", "pyflakes"]))
+
+from buildbot.config import BuilderConfig
+
+c['builders'] = []
+c['builders'].append(
+    BuilderConfig(name="runtests",
+      slavenames=["example-slave"],
+      factory=factory))
+
+####### STATUS TARGETS
+
+# 'status' is a list of Status Targets. The results of each build will be
+# pushed to these targets. buildbot/status/*.py has a variety to choose from,
+# including web pages, email senders, and IRC bots.
+
+c['status'] = []
+
+from buildbot.status import html
+from buildbot.status.web import auth, authz
+authz_cfg=authz.Authz(
+    # change any of these to True to enable; see the manual for more
+    # options
+    gracefulShutdown = False,
+    forceBuild = True, # use this to test your slave once it is set up
+    forceAllBuilds = False,
+    pingBuilder = False,
+    stopBuild = False,
+    stopAllBuilds = False,
+    cancelPendingBuild = False,
+)
+c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg))
+
+####### PROJECT IDENTITY
+
+# the 'projectName' string will be used to describe the project that this
+# buildbot is working on. For example, it is used as the title of the
+# waterfall HTML page. The 'projectURL' string will be used to provide a link
+# from buildbot HTML pages to your project's home page.
+
+c['projectName'] = "Pyflakes"
+c['projectURL'] = "http://divmod.org/trac/wiki/DivmodPyflakes";
+
+# the 'buildbotURL' string should point to the location where the buildbot's
+# internal web server (usually the html.WebStatus page) is visible. This
+# typically uses the port number set in the Waterfall 'status' entry, but
+# with an externally-visible host name which the buildbot cannot figure out
+# without some help.
+
+c['buildbotURL'] = "http://localhost:8010/";
+
+####### DB URL
+
+# This specifies what database buildbot uses to store change and scheduler
+# state.  You can leave this at its default for all but the largest
+# installations.
+c['db_url'] = "sqlite:///state.sqlite"

=== added file 'configuration/master.cfg.template'
--- configuration/master.cfg.template	1970-01-01 00:00:00 +0000
+++ configuration/master.cfg.template	2012-01-30 17:26:26 +0000
@@ -0,0 +1,116 @@
+# -*- python -*-
+# ex: set syntax=python:
+
+# This is a sample buildmaster config file. It must be installed as
+# 'master.cfg' in your buildmaster's base directory.
+
+# This is the dictionary that the buildmaster pays attention to. We also use
+# a shorter alias to save typing.
+c = BuildmasterConfig = {}
+
+####### BUILDSLAVES
+
+# The 'slaves' list defines the set of recognized buildslaves. Each element is
+# a BuildSlave object, specifying a username and password.  The same username and
+# password must be configured on the slave.
+from buildbot.buildslave import BuildSlave
+c['slaves'] = [BuildSlave("example-slave", "pass")]
+
+# 'slavePortnum' defines the TCP port to listen on for connections from slaves.
+# This must match the value configured into the buildslaves (with their
+# --master option)
+c['slavePortnum'] = 9989
+
+####### CHANGESOURCES
+
+# the 'change_source' setting tells the buildmaster how it should find out
+# about source code changes.  Here we point to the buildbot clone of pyflakes.
+
+from buildbot.changes.gitpoller import GitPoller
+c['change_source'] = GitPoller(
+        'git://github.com/buildbot/pyflakes.git',
+        branch='master', pollinterval=1200)
+
+####### SCHEDULERS
+
+# Configure the Schedulers, which decide how to react to incoming changes.  In this
+# case, just kick off a 'runtests' build
+
+from buildbot.scheduler import Scheduler
+c['schedulers'] = []
+c['schedulers'].append(Scheduler(name="all", branch=None,
+                                 treeStableTimer=None,
+                                 builderNames=["runtests"]))
+
+####### BUILDERS
+
+# The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
+# what steps, and which slaves can execute them.  Note that any particular build will
+# only take place on one slave.
+
+from buildbot.process.factory import BuildFactory
+from buildbot.steps.source import Git
+from buildbot.steps.shell import ShellCommand
+
+factory = BuildFactory()
+# check out the source
+factory.addStep(Git(repourl='git://github.com/buildbot/pyflakes.git', mode='copy'))
+# run the tests (note that this will require that 'trial' is installed)
+factory.addStep(ShellCommand(command=["trial", "pyflakes"]))
+
+from buildbot.config import BuilderConfig
+
+c['builders'] = []
+c['builders'].append(
+    BuilderConfig(name="runtests",
+      slavenames=["example-slave"],
+      factory=factory))
+
+####### STATUS TARGETS
+
+# 'status' is a list of Status Targets. The results of each build will be
+# pushed to these targets. buildbot/status/*.py has a variety to choose from,
+# including web pages, email senders, and IRC bots.
+
+c['status'] = []
+
+from buildbot.status import html
+from buildbot.status.web import auth, authz
+authz_cfg=authz.Authz(
+    # change any of these to True to enable; see the manual for more
+    # options
+    gracefulShutdown = False,
+    forceBuild = True, # use this to test your slave once it is set up
+    forceAllBuilds = False,
+    pingBuilder = False,
+    stopBuild = False,
+    stopAllBuilds = False,
+    cancelPendingBuild = False,
+)
+c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg))
+
+####### PROJECT IDENTITY
+
+# the 'projectName' string will be used to describe the project that this
+# buildbot is working on. For example, it is used as the title of the
+# waterfall HTML page. The 'projectURL' string will be used to provide a link
+# from buildbot HTML pages to your project's home page.
+
+c['projectName'] = "Pyflakes"
+c['projectURL'] = "http://divmod.org/trac/wiki/DivmodPyflakes";
+
+# the 'buildbotURL' string should point to the location where the buildbot's
+# internal web server (usually the html.WebStatus page) is visible. This
+# typically uses the port number set in the Waterfall 'status' entry, but
+# with an externally-visible host name which the buildbot cannot figure out
+# without some help.
+
+c['buildbotURL'] = "http://localhost:8010/";
+
+####### DB URL
+
+# This specifies what database buildbot uses to store change and scheduler
+# state.  You can leave this at its default for all but the largest
+# installations.
+c['db_url'] = "sqlite:///state.sqlite"
+

=== added directory 'hooks'
=== added file 'hooks/buildbot-relation-changed'
--- hooks/buildbot-relation-changed	1970-01-01 00:00:00 +0000
+++ hooks/buildbot-relation-changed	2012-01-30 17:26:26 +0000
@@ -0,0 +1,19 @@
+#!/bin/bash
+# This must be renamed to the name of the relation. The goal here is to
+# affect any change needed by relationships being formed, modified, or broken
+# This script should be idempotent.
+juju-log $JUJU_REMOTE_UNIT modified its settings
+
+BUILDBOT_DIR=`config-get installdir`
+NAME=`config-get slave-name`
+PASSWD=`config-get slave-passwd`
+HOST=`relation-get private-address`
+
+juju-log "--> create slave"
+juju-log "buildslave create-slave $BUILDBOT_DIR $HOST $NAME $PASSWD"
+buildslave create-slave $BUILDBOT_DIR $HOST $NAME $PASSWD
+juju-log "<-- create slave"
+
+juju-log "--> start"
+buildslave start $BUILDBOT_DIR
+juju-log "<-- start"

=== added file 'hooks/config-changed'
--- hooks/config-changed	1970-01-01 00:00:00 +0000
+++ hooks/config-changed	2012-01-30 17:26:26 +0000
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Hook for handling config changes.
+set -eux # -x for verbose logging to juju debug-log
+
+# config_file is changed via juju like:
+# juju set buildbot-slave config-file=`uuencode slave.cfg`
+
+BUILDBOT_DIR=`config-get installdir`
+juju-log "--> config-changed"
+
+juju-log "Updating buildbot configuration."
+CONFIG_FILE=`config-get config-file`
+CONFIG_TRANSPORT=`config-get config-transport`
+CONFIG_URL=`config-get config-url`
+
+#
+if [[ -n $CONFIG_FILE ]]; then
+    echo "$CONFIG_FILE" | uudecode -o $BUILDBOT_DIR/master.cfg
+    juju-log "Config decoded and written."
+elif [ "$CONFIG_TRANSPORT" == "bzr" ] && [[ -n $CONFIG_URL ]]; then
+    # If the branch is private then more setup needs to be done.  The gpg-agent needs to send the key over and the
+    # bzr launchpad-login needs to be set.
+    LP_ID=`config-get config-user`
+    if [[ -n $LP_ID ]]; then
+	bzr launchpad-login $LP_ID
+    fi
+    PKEY=`config-get config-private-key`
+    if [[ -n $PKEY ]]; then
+        # Set up the .ssh directory.
+        mkdir ~/.ssh
+        chmod 700 ~/.ssh
+        echo "$PKEY" | uudecode -o ~/.ssh/lp_key
+    fi
+    bzr branch --use-existing-dir $CONFIG_URL $BUILDBOT_DIR
+    chown -R ubuntu:ubuntu $BUILDBOT_DIR
+fi
+
+# Restart buildbot if it is running.
+PIDFILE=$BUILDBOT_DIR/twistd.pid
+if [ -f $PIDFILE ]; then
+  BUILDBOT_PID=`cat $PIDFILE`
+  if kill -0 $BUILDBOT_PID; then
+    # Buildbot is running, reconfigure it.
+    juju-log "Reconfiguring buildbot"
+    buildbot reconfig $BUILDBOT_DIR
+    juju-log "Buildbot reconfigured"
+  fi
+fi
+
+juju-log "<-- config-changed"

=== added file 'hooks/install'
--- hooks/install	1970-01-01 00:00:00 +0000
+++ hooks/install	2012-01-30 17:26:26 +0000
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Here do anything needed to install the service
+# i.e. apt-get install -y foo  or  bzr branch http://myserver/mycode /srv/webroot
+set -eux # -x for verbose logging to juju debug-log
+
+juju-log "--> install"
+BUILDBOT_DIR=`config-get installdir`
+apt-get install -y buildbot sharutils
+# Needed only for the demo site.
+apt-get install -y git
+
+juju-log "Creating slave in $BUILDBOT_DIR"
+# Since we may be installing into a pre-existing service, ensure the
+# buildbot directory is removed.
+if [ -e $BUILDBOT_DIR ]; then
+  buildbot stop $BUILDBOT_DIR
+  rm -rf $BUILDBOT_DIR
+fi
+mkdir -p $BUILDBOT_DIR
+juju-log "<-- install"

=== added file 'hooks/relation-name-relation-broken'
--- hooks/relation-name-relation-broken	1970-01-01 00:00:00 +0000
+++ hooks/relation-name-relation-broken	2012-01-30 17:26:26 +0000
@@ -0,0 +1,2 @@
+#!/bin/sh
+# This hook runs when the full relation is removed (not just a single member)

=== added file 'hooks/relation-name-relation-changed'
--- hooks/relation-name-relation-changed	1970-01-01 00:00:00 +0000
+++ hooks/relation-name-relation-changed	2012-01-30 17:26:26 +0000
@@ -0,0 +1,9 @@
+#!/bin/bash
+# This must be renamed to the name of the relation. The goal here is to
+# affect any change needed by relationships being formed, modified, or broken
+# This script should be idempotent.
+juju-log $JUJU_REMOTE_UNIT modified its settings
+juju-log Relation settings:
+relation-get
+juju-log Relation members:
+relation-list

=== added file 'hooks/relation-name-relation-departed'
--- hooks/relation-name-relation-departed	1970-01-01 00:00:00 +0000
+++ hooks/relation-name-relation-departed	2012-01-30 17:26:26 +0000
@@ -0,0 +1,5 @@
+#!/bin/sh
+# This must be renamed to the name of the relation. The goal here is to
+# affect any change needed by the remote unit leaving the relationship.
+# This script should be idempotent.
+juju-log $JUJU_REMOTE_UNIT departed

=== added file 'hooks/relation-name-relation-joined'
--- hooks/relation-name-relation-joined	1970-01-01 00:00:00 +0000
+++ hooks/relation-name-relation-joined	2012-01-30 17:26:26 +0000
@@ -0,0 +1,5 @@
+#!/bin/sh
+# This must be renamed to the name of the relation. The goal here is to
+# affect any change needed by relationships being formed
+# This script should be idempotent.
+juju-log $JUJU_REMOTE_UNIT joined

=== added file 'hooks/start'
--- hooks/start	1970-01-01 00:00:00 +0000
+++ hooks/start	2012-01-30 17:26:26 +0000
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Here put anything that is needed to start the service.
+# Note that currently this is run directly after install
+# i.e. 'service apache2 start'
+set -eux # -x for verbose logging to juju debug-log
+
+BUILDBOT_DIR=`config-get installdir`
+

=== added file 'hooks/stop'
--- hooks/stop	1970-01-01 00:00:00 +0000
+++ hooks/stop	2012-01-30 17:26:26 +0000
@@ -0,0 +1,16 @@
+#!/bin/bash
+# This will be run when the service is being torn down, allowing you to disable
+# it in various ways..
+# For example, if your web app uses a text file to signal to the load balancer
+# that it is live... you could remove it and sleep for a bit to allow the load
+# balancer to stop sending traffic.
+# rm /srv/webroot/server-live.txt && sleep 30
+
+BUILDBOT_DIR=`config-get installdir`
+
+juju-log "<-- stop"
+juju-log "Stopping buildbot in $BUILDBOT_DIR"
+close-port 8010/tcp
+buildbot stop $BUILDBOT_DIR
+juju-log "Finished stopping buildbot"
+juju-log "--> stop"

=== added file 'metadata.yaml'
--- metadata.yaml	1970-01-01 00:00:00 +0000
+++ metadata.yaml	2012-01-30 17:26:26 +0000
@@ -0,0 +1,21 @@
+name: buildbot-slave
+summary: system to automate the compile/test cycle
+description: |
+  The BuildBot is a system to automate the compile/test cycle required by
+  most software projects to validate code changes. By automatically
+  rebuilding and testing the tree each time something has changed, build
+  problems are pinpointed quickly, before other developers are
+  inconvenienced by the failure. The guilty developer can be identified
+  and harassed without human intervention.  By running the builds on a
+  variety of platforms, developers who do not have the facilities to
+  test their changes everywhere before checkin will at least know
+  shortly afterwards whether they have broken the build or not. Warning
+  counts, lint checks, image size, compile time, and other build
+  parameters can be tracked over time, are more visible, and are
+  therefore easier to improve.
+requires:
+  buildbot:
+    interface: master
+provides:
+  buildbot:
+    interface: slave

=== added file 'notes.txt'
--- notes.txt	1970-01-01 00:00:00 +0000
+++ notes.txt	2012-01-30 17:26:26 +0000
@@ -0,0 +1,41 @@
+------------
+Known Issues
+------------
+
+lp:760818 - debug log is initialized too late in the unit agent startup, to catch install/start hooks
+    symptom: 'juju debug-log' does not provide any useful
+    information.  Log can be found on the client at /var/log/juju/units/X/charm.log
+
+lp:902143 - juju set <service_name> --filename does not work
+
+lp:887077 - upgrading to precise breaks java which breaks zookeeper.
+
+----------
+Unreported
+----------
+
+'juju upgrade-charm' does not work unless the service is actually
+running, which makes it hard to fix a charm that has a start_error.
+
+The charm directory and name must match or juju reports the charm can
+not be found.  If that is the case, the name should be removed from
+the metadata.yaml.
+
+--repository should default to ./
+
+destroy-environment should have a '-y' option to prevent the service
+not shutting down waiting for confirmation.
+
+
+------------
+Unrepeatable
+------------
+
+open-port silently ignores some settings unless in quotes.  This
+    should work:
+    open-port 8010/tcp
+
+    but silently fails unless written as:
+    open-port "8010/tcp"
+
+    Other charms use the first spelling so it is confusing.

=== added file 'revision'
--- revision	1970-01-01 00:00:00 +0000
+++ revision	2012-01-30 17:26:26 +0000
@@ -0,0 +1,1 @@
+16


Follow ups