Merge lp:~canonical-ca-hackers/ubuntu-webcatalog/branch-deployment into lp:ubuntu-webcatalog

Proposed by Łukasz Czyżykowski
Status: Merged
Approved by: Anthony Lenton
Approved revision: 70
Merged at revision: 68
Proposed branch: lp:~canonical-ca-hackers/ubuntu-webcatalog/branch-deployment
Merge into: lp:ubuntu-webcatalog
Diff against target: 295 lines (+89/-187)
3 files modified
fabtasks/__init__.py (+1/-1)
fabtasks/deploy.py (+88/-0)
fabtasks/upgrade_from_package.py (+0/-186)
To merge this branch: bzr merge lp:~canonical-ca-hackers/ubuntu-webcatalog/branch-deployment
Reviewer Review Type Date Requested Status
Anthony Lenton (community) Approve
Review via email: mp+96637@code.launchpad.net

Commit message

Branch based deployment fabric task.

Description of the change

Added branch-based fab deploy task.

To post a comment you must log in.
Revision history for this message
Anthony Lenton (elachuni) wrote :

Thanks Łukasz!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'fabtasks/__init__.py'
2--- fabtasks/__init__.py 2011-09-12 13:37:24 +0000
3+++ fabtasks/__init__.py 2012-03-08 18:18:19 +0000
4@@ -15,6 +15,6 @@
5 # You should have received a copy of the GNU Affero General Public License
6 # along with this program. If not, see <http://www.gnu.org/licenses/>.
7
8-from .upgrade_from_package import *
9 from .bootstrap import *
10 from .django import *
11+from .deploy import *
12
13=== added file 'fabtasks/deploy.py'
14--- fabtasks/deploy.py 1970-01-01 00:00:00 +0000
15+++ fabtasks/deploy.py 2012-03-08 18:18:19 +0000
16@@ -0,0 +1,88 @@
17+# -*- coding: utf-8 -*-
18+"""Fabric commands for deploying from the branches to testing server."""
19+
20+from __future__ import absolute_import
21+from __future__ import with_statement
22+
23+__metaclass__ = type
24+__all__ = [
25+ 'deploy',
26+ ]
27+
28+import os
29+import shutil
30+import tempfile
31+
32+from fabric.api import env, run, local, put, cd, sudo
33+from fabric.contrib import files
34+
35+
36+def _format(s):
37+ """Format string using substitutions from fabric's env."""
38+ return s.format(**env)
39+
40+
41+def _run(cmd):
42+ run(_format(cmd))
43+
44+
45+def _local(cmd):
46+ local(_format(cmd))
47+
48+
49+def _sudo(cmd):
50+ sudo(_format(cmd))
51+
52+
53+def migrate_database(deploy_dir):
54+ path = os.path.join(
55+ deploy_dir, "ubuntu-webcatalog/sourcecode/framework")
56+ with cd(path):
57+ run("python manage.py syncdb --migrate --noinput")
58+
59+
60+def apache_graceful():
61+ sudo('service apache2 graceful', shell=False)
62+
63+
64+def deploy(config_branch, deploy_dir="/srv/uwc.staging.ubuntu.com/staging",
65+ production=False):
66+ env.cm = "/usr/lib/config-manager/cm.py"
67+
68+ if not files.exists(env.cm):
69+ sudo("apt-get install --yes config-manager")
70+
71+ env.config_branch = config_branch
72+ env.deploy_dir = deploy_dir
73+ env.build_dir = tempfile.mkdtemp()
74+ env.sourcedeps = _format("{build_dir}/cm/sourcedeps.conf")
75+ env.revno = local("bzr revno", capture=True).strip()
76+
77+ _local("bzr branch {config_branch} {build_dir}/cm")
78+
79+ _local("sed -i 's/bazaar.isd/bazaar.launchpad.net/g' {sourcedeps}")
80+
81+ if not production:
82+ _local("sed -i '1 s/production/trunk/' {sourcedeps}")
83+ _local("sed -i '1 s/;revno=[0-9]\+$/;revno={revno}/' {sourcedeps}")
84+ _local("sed -i '2 s/;revno=[0-9]\+$//' {sourcedeps}")
85+
86+ put(env.sourcedeps, deploy_dir)
87+
88+ with cd(deploy_dir):
89+ _sudo("chown -R jenkins: ubuntu-webcatalog || true")
90+
91+ if files.exists("ubuntu-webcatalog"):
92+ _run("{cm} update sourcedeps.conf")
93+ else:
94+ _run("{cm} build sourcedeps.conf")
95+
96+ _run("rm sourcedeps.conf")
97+
98+ shutil.rmtree(env.build_dir, ignore_errors=True)
99+
100+ migrate_database(deploy_dir)
101+
102+ _sudo("chown -R www-data: {deploy_dir}/ubuntu-webcatalog")
103+
104+ apache_graceful()
105
106=== removed file 'fabtasks/upgrade_from_package.py'
107--- fabtasks/upgrade_from_package.py 2011-09-12 13:37:24 +0000
108+++ fabtasks/upgrade_from_package.py 1970-01-01 00:00:00 +0000
109@@ -1,186 +0,0 @@
110-# -*- coding: utf-8 -*-
111-# This file is part of Apps Directory
112-# Copyright (C) 2011 Canonical Ltd.
113-#
114-# This program is free software: you can redistribute it and/or modify
115-# it under the terms of the GNU Affero General Public License as
116-# published by the Free Software Foundation, either version 3 of the
117-# License, or (at your option) any later version.
118-#
119-# This program is distributed in the hope that it will be useful,
120-# but WITHOUT ANY WARRANTY; without even the implied warranty of
121-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
122-# GNU Affero General Public License for more details.
123-#
124-# You should have received a copy of the GNU Affero General Public License
125-# along with this program. If not, see <http://www.gnu.org/licenses/>.
126-
127-"""Fabric commands for building a package for a direct server upgrade.
128-
129-The local machine must have bzr-builder and pbuilder, and a lucid chroot
130-setup as the default pbuilder distribution:
131-
132- $ sudo pbuilder create --distribution lucid
133-
134-"""
135-
136-from __future__ import absolute_import
137-from __future__ import with_statement
138-
139-__metaclass__ = type
140-__all__ = [
141- 'build_and_install_deb',
142- 'build_binary_package',
143- 'build_source_package',
144- 'clean_local_branch',
145- 'install_binary_package',
146- 'migrate_database',
147- 'preflight_check',
148- 'restart_services',
149- 'update_configs',
150- ]
151-
152-import os
153-import shutil
154-import tempfile
155-from datetime import datetime
156-from glob import glob
157-from textwrap import dedent
158-
159-from fabric.api import (
160- env,
161- local,
162- put,
163- run,
164- sudo,
165- )
166-from fabric.contrib.files import exists
167-
168-
169-def clean_local_branch():
170- local("find . -name '*.pyc' -delete")
171-
172-
173-def build_source_package(build_dir, distroseries='lucid'):
174- clean_local_branch()
175- # We use a recipe to ensure that we always generate later versions
176- # with a timestamp. The recipe refers to the local branch '.' rather
177- # than pulling from the network.
178- recipe = dedent("""\
179- # bzr-builder format 0.2 deb-version {debupstream}-0~{revno}+{time}
180- .""")
181- recipe_path = os.path.join(build_dir, 'uwc.recipe')
182- with open(recipe_path, 'w+') as recipe_file:
183- recipe_file.write(recipe)
184-
185- local('bzr dailydeb --distribution={0} {1} {2}'.format(
186- distroseries, recipe_path, build_dir))
187- dsc_file = glob(os.path.join(build_dir, '*.dsc'))[0]
188-
189- print("Created source package at {0}.".format(dsc_file))
190- return dsc_file
191-
192-
193-def build_binary_package(build_dir, source_dsc):
194- print("Building binary package for {0}".format(source_dsc))
195- local('sudo pbuilder build --buildresult {0} {1}'.format(
196- build_dir, source_dsc))
197- deb_file = glob(os.path.join(build_dir, "*.deb"))[0]
198- print("Created binary at {0}.".format(deb_file))
199- return deb_file
200-
201-
202-def migrate_database(config_dir=None):
203- if config_dir is None:
204- # By default, the uwc config directory is assumed to be
205- # /home/username/django_project.
206- config_dir = 'django_project'
207- run(config_dir + '/manage.py syncdb --migrate')
208-
209-
210-def preflight_check(config_dir='django_project'):
211- run('COLUMNS=40 %s/manage.py preflight' % config_dir)
212-
213-
214-def restart_services():
215- sudo('service apache2 graceful', shell=False)
216-
217-
218-def install_binary_package(deb_file):
219- put(deb_file, '.')
220- deb_filename = os.path.basename(deb_file)
221- sudo('dpkg -i {0}'.format(deb_filename), shell=False)
222-
223-
224-LOCAL_CONFIG = """
225-[__main__]
226-includes = config/staging.cfg
227- config/dailies.cfg
228-"""
229-
230-
231-def update_configs(config_branch, config_dir='django_project'):
232- """Backup current config files and pull in the latest from a bzr branch.
233-
234- If it exists, local.cfg is left unmodified.
235- """
236- timestamp = datetime.utcnow().isoformat()
237- backup_dir = "%s.backup.%s" % (config_dir, timestamp)
238- if exists(config_dir):
239- run("mv %s %s" % (config_dir, backup_dir))
240- put_bzr_branch(config_branch, config_dir)
241- if exists(backup_dir + '/local.cfg'):
242- run("cp %s/local.cfg %s" % (backup_dir, config_dir))
243- else:
244- # Create a local.cfg on the server from our template.
245- local_fd, local_path = tempfile.mkstemp()
246- local_file = os.fdopen(local_fd, 'w')
247- local_file.write(LOCAL_CONFIG)
248- local_file.close()
249- put(local_path, "%s/local.cfg" % config_dir)
250- os.remove(local_path)
251-
252-
253-def put_bzr_branch(url, name):
254- """
255- Copy bazaar branch from launchpad to remote host
256-
257- This have to be done with local machine as proxy, because remote machine
258- cannot have access to private projects on launchpad. We don't want to put
259- there our private ssh keys.
260-
261- :param url: bazaar url to the branch, it can start with lp:
262- :type url: str
263-
264- :param name: name of the directory in which branch will be located remotely
265- :type name: str
266-
267- """
268- local("rm -rf /tmp/%s" % name)
269-
270- local("bzr branch %s /tmp/%s" % (url, name))
271- local("cd /tmp && tar cjf %s.tar.bz2 %s" % (name, name))
272- put("/tmp/%s.tar.bz2" % name, '~/')
273-
274- local("rm -rf /tmp/%s.tar.bz2 /tmp/%s" % (name, name))
275-
276- run("tar xjf %s.tar.bz2" % name)
277-
278-
279-def build_and_install_deb(config_branch, build_dir=None, distroseries='lucid'):
280- delete_dir_after_build = False
281- if build_dir is None:
282- build_dir = tempfile.mkdtemp()
283- delete_dir_after_build = True
284-
285- dsc_file = build_source_package(build_dir, distroseries=distroseries)
286- binary_file = build_binary_package(build_dir, dsc_file)
287- install_binary_package(binary_file)
288- migrate_database()
289- update_configs(config_branch)
290- preflight_check()
291- restart_services()
292- print("Package installed and services restarted.")
293-
294- if delete_dir_after_build:
295- shutil.rmtree(build_dir, ignore_errors=True)

Subscribers

People subscribed via source and target branches