summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@yahoo-inc.com>2012-06-25 16:59:39 -0700
committerJoshua Harlow <harlowja@yahoo-inc.com>2012-06-25 16:59:39 -0700
commitc36c782d3c3913611b86edeb7d371c54ced4b8bd (patch)
tree1ecbfc9de0ea710155e4b51f3558ee740a3d3773 /packages
parent3b05473d57f5aaadf4cd0b57b7138d9ff2141808 (diff)
downloadvyos-cloud-init-c36c782d3c3913611b86edeb7d371c54ced4b8bd.tar.gz
vyos-cloud-init-c36c782d3c3913611b86edeb7d371c54ced4b8bd.zip
Get rpm building working with a template.
Diffstat (limited to 'packages')
-rwxr-xr-xpackages/brpm270
-rw-r--r--packages/brpm.tmpl161
2 files changed, 289 insertions, 142 deletions
diff --git a/packages/brpm b/packages/brpm
index f2c3dac4..5feade24 100755
--- a/packages/brpm
+++ b/packages/brpm
@@ -6,9 +6,19 @@ import subprocess
import sys
import tempfile
import re
+import textwrap
+import shutil
+import zipfile
+
+import glob
import tempita
+from datetime import datetime
+from datetime import date
+
+from distutils import version as ver
+
# This is more just for running from the bin folder so that
# cloud-init binary can find the cloudinit module
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
@@ -16,28 +26,268 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")):
sys.path.insert(0, possible_topdir)
+from cloudinit import util
+from cloudinit import version
+
+import contextlib
+
+# Mapping of expected packages to there full name...
+PKG_MP = {
+ 'boto': 'python-boto',
+ 'tempita': 'python-tempita',
+ 'prettytable': 'python-prettytable',
+ 'oauth': 'python-oauth',
+ 'configobj': 'python-configobj',
+ 'yaml': 'PyYAML',
+ 'argparse': 'python-argparse'
+}
+
+
+@contextlib.contextmanager
+def chdir(where_to):
+ cur_cwd = os.path.abspath(os.getcwd())
+ where_to = os.path.abspath(where_to)
+ os.chdir(where_to)
+ yield where_to
+ os.chdir(cur_cwd)
+
+
PWD = os.getcwd()
def info(msg):
- sys.stderr.write("INFO: %s\n" % (msg))
+ print("INFO: %s" % (msg))
def warn(msg):
- sys.stderr.write("WARNING: %s\n" % (msg))
+ print("WARNING: %s" % (msg))
-def main():
- if not os.path.isfile(os.path.join(PWD, 'brpm.tmpl')):
- warn("Can not find required template file 'brpm.tmpl'")
- return 1
- if not os.path.isfile(os.path.join(os.pardir, 'setup.py')):
- warn("Can not find required root 'setup.py' file")
- return 1
+def cut_up(entry, maxline=80):
+ if len(entry) < maxline:
+ return entry
+ else:
+ c = entry[0:maxline]
+ return "%s..." % (c)
+
+
+def extract_entry(collecting):
+ a_entry = {}
+ for t in ['tags', 'revno', 'author', 'timestamp', 'committer']:
+ look_for = "%s:" % (t)
+ for v in collecting:
+ if v.startswith(look_for):
+ a_entry[t] = v[len(look_for):].strip()
+ break
+ i = -1
+ for a, v in enumerate(collecting):
+ if v.startswith("message:"):
+ i = a
+ break
+ if i != -1:
+ msg_lines = collecting[i + 1:]
+ n_lines = []
+ for m in msg_lines:
+ m = m.strip()
+ if not m:
+ continue
+ m = m.replace("\n", " ")
+ n_lines.append("" + m.lstrip())
+ message = " ".join(n_lines).lstrip()
+ a_entry['message'] = message
+ return a_entry
+
+
+def build_changelog(history=-1):
+ cmd = ['bzr', 'log', '--timezone=utc']
+ (stdout, _stderr) = util.subp(cmd)
+ # Clean the format up
+ entries = stdout.splitlines()
+ all_entries = []
+ collecting = []
+ for e in entries:
+ if e.startswith("---"):
+ if collecting:
+ a_entry = extract_entry(collecting)
+ if a_entry:
+ all_entries.append(a_entry)
+ collecting = []
+ else:
+ collecting.append(e)
+ a_entry = extract_entry(collecting)
+ if a_entry:
+ all_entries.append(a_entry)
+
+ if history > 0:
+ take_entries = list(all_entries[0:history])
+ else:
+ take_entries = list(all_entries)
+
+ # Merge those with same date
+ date_entries = {}
+ for e in take_entries:
+ author = e.get('author')
+ if not author:
+ author = e.get('committer')
+ if not author:
+ continue
+ timestamp = e.get('timestamp')
+ if not timestamp:
+ continue
+ msg = e.get('message')
+ if not msg:
+ continue
+ revno = e.get('revno')
+ if not revno:
+ continue
+ # http://bugs.python.org/issue6641
+ timestamp = timestamp.replace("+0000", '').strip()
+ ds = datetime.strptime(timestamp, '%a %Y-%m-%d %H:%M:%S')
+ c_ds = ds.date()
+ if c_ds not in date_entries:
+ ap_entry = {}
+ ap_entry['messages'] = []
+ ap_entry['authors'] = []
+ ap_entry['revnos'] = []
+ date_entries[c_ds] = ap_entry
+ ap_entry = date_entries[c_ds]
+ ap_entry['messages'].append(msg)
+ ap_entry['authors'].append(author)
+ ap_entry['revnos'].append(revno)
+
+ dates = sorted(date_entries.keys())
+ chglog = []
+ for ds in reversed(dates):
+ e = date_entries[ds]
+ authors = ", ".join(set(e['authors']))
+ revnos = ", ".join(list(sorted(e['revnos'])))
+ top_line = "%s %s - %s" % (ds.strftime("%a %b %d %Y"),
+ authors, revnos)
+ chglog.append("* %s" % (top_line))
+ for msg in e['messages']:
+ chglog.append("- %s" % (cut_up(msg)))
+ return "\n".join(chglog)
+
+
+def generate_spec_contents(tmpl_fn):
+ # Version junk
cmd = [os.path.join(os.pardir, 'tools', 'read-version')]
- version = subprocess.check_Call(cmd)
+ (stdout, _stderr) = util.subp(cmd)
+ i_version = stdout.strip()
+
+ # Ensure ok match!
+ if ver.StrictVersion(i_version) != version.version():
+ raise RuntimeError("Version found does not match the code version")
+
+ # Tmpl params
+ subs = {}
+ subs['version'] = i_version
+ (stdout, _stderr) = util.subp(['bzr', 'revno'])
+ subs['revno'] = "%s" % (stdout.strip())
+ subs['release'] = "%s" % (subs['revno'])
+ subs['archive_name'] = '%{name}-%{version}-' + subs['revno'] + '.tar.gz'
+ subs['bd_requires'] = ['python-devel', 'python-setuptools']
+
+ requires = []
+ cmd = [os.path.join(os.pardir, 'tools', 'read-dependencies')]
+ (stdout, _stderr) = util.subp(cmd)
+ pkgs = stdout.splitlines()
+
+ # Map to known packages
+ for e in pkgs:
+ e = e.lower().strip()
+ tgt_pkg = None
+ for n in PKG_MP.keys():
+ if e.find(n) != -1:
+ tgt_pkg = PKG_MP.get(n)
+ if not tgt_pkg:
+ raise RuntimeError(("Do not know how to translate %s to "
+ " a known package") % (e))
+ else:
+ requires.append(tgt_pkg)
+
+ base_name = 'cloud-init-%s-%s' % (i_version, subs['revno'])
+ subs['requires'] = requires
+ subs['changelog'] = build_changelog()
+
+ # See: http://www.zarb.org/~jasonc/macros.php
+ # Pickup any special files
+ docs = [
+ 'TODO',
+ 'LICENSE',
+ 'ChangeLog',
+ 'Requires',
+ '%{_defaultdocdir}/cloud-init/*',
+ ]
+ subs['docs'] = docs
+ configs = [
+ 'cloud/cloud.cfg',
+ 'cloud/cloud.cfg.d/*.cfg',
+ 'cloud/cloud.cfg.d/README',
+ 'cloud/templates/*',
+ ]
+ subs['configs'] = configs
+ other_files = [
+ '%{_bindir}/*',
+ '/usr/lib/cloud-init/*',
+ ]
+ subs['files'] = other_files
+ with open(tmpl_fn, 'r') as fh:
+ tmpl = tempita.Template(fh.read())
+ contents = tmpl.substitute(**subs)
+ return (base_name, '%s.tar.gz' % (base_name), contents)
+
+
+def main():
+ root_dir = os.path.expanduser("~/rpmbuild")
+ info("Cleaning %s" % (root_dir))
+ util.delete_dir_contents(root_dir)
+ arc_dir = os.path.join(root_dir, 'SOURCES')
+ util.ensure_dirs([root_dir, arc_dir])
+ tmpl_fn = os.path.join(os.getcwd(), 'brpm.tmpl')
+ info("Generated spec file from template %s" % (tmpl_fn))
+ (base_name, arc_name, contents) = generate_spec_contents(tmpl_fn)
+ spec_fn = os.path.join(root_dir, 'cloud-init.spec')
+ util.write_file(spec_fn, contents)
+ info("Wrote spec file to %s" % (spec_fn))
+ with util.tempdir() as td:
+ src_dir = os.path.join(td, base_name)
+ os.makedirs(src_dir)
+ for fn in os.listdir(os.pardir):
+ if fn.startswith("."):
+ continue
+ full_fn = os.path.abspath(os.path.join(os.pardir, fn))
+ if os.path.isfile(full_fn):
+ shutil.copy(full_fn, os.path.join(src_dir, fn))
+ else:
+ shutil.copytree(full_fn, os.path.join(src_dir, fn),
+ ignore=shutil.ignore_patterns('*.pyc',
+ '.bzr',
+ 'tmp*',
+ '*bzr*'))
+ arc_fn = os.path.join(arc_dir, arc_name)
+ cmd = ['tar', '-zcvf', arc_fn, '-C', td]
+ cmd.extend(os.listdir(td))
+ util.subp(cmd)
+ info("Archived code at %s" % (arc_fn))
+ cmd = ['rpmbuild', '-ba', spec_fn]
+ info("Running rpmbuild %s" % (cmd))
+ util.subp(cmd)
+ info("Rpmbuild completed!")
+ globs = []
+ globs.extend(glob.glob("%s/*.rpm" %
+ (os.path.join(root_dir, 'RPMS', 'noarch'))))
+ globs.extend(glob.glob("%s/*.rpm" %
+ (os.path.join(root_dir, 'RPMS'))))
+ globs.extend(glob.glob("%s/*.rpm" %
+ (os.path.join(root_dir, 'SRPMS'))))
+ for fn in globs:
+ n = os.path.basename(fn)
+ tgt_fn = os.path.join(os.getcwd(), n)
+ util.copy(fn, tgt_fn)
+ info("Copied %s to %s" % (n, tgt_fn))
return 0
diff --git a/packages/brpm.tmpl b/packages/brpm.tmpl
index 141578a5..f0c874ee 100644
--- a/packages/brpm.tmpl
+++ b/packages/brpm.tmpl
@@ -9,28 +9,21 @@ Group: System Environment/Base
License: GPLv3
URL: http://launchpad.net/cloud-init
-Source0: %{name}-%{version}-bzr532.tar.gz
+Source0: {{archive_name}}
BuildArch: noarch
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-
-BuildRequires: python-devel
-BuildRequires: python-setuptools-devel
-Requires: e2fsprogs
-Requires: iproute
-Requires: libselinux-python
-Requires: net-tools
-Requires: procps
-Requires: python-boto
-Requires: python-cheetah
-Requires: python-configobj
-Requires: PyYAML
-Requires: rsyslog
-Requires: shadow-utils
-Requires: /usr/bin/run-parts
-Requires(post): chkconfig
-Requires(preun): chkconfig
-Requires(postun): initscripts
+
+BuildRoot: %{_tmppath}
+
+
+{{for r in bd_requires}}
+BuildRequires: {{r}}
+{{endfor}}
+
+# Install requirements
+{{for r in requires}}
+Requires: {{r}}
+{{endfor}}
%description
Cloud-init is a set of init scripts for cloud instances. Cloud instances
@@ -39,14 +32,7 @@ ssh keys and to let the user run various scripts.
%prep
-%setup -q -n %{name}-%{version}-bzr532
-%patch0 -p0
-%patch1 -p0
-%patch2 -p1
-%patch3 -p1
-
-cp -p %{SOURCE2} README.fedora
-
+%setup -q -n %{name}-%{version}-{{revno}}
%build
%{__python} setup.py build
@@ -56,118 +42,29 @@ cp -p %{SOURCE2} README.fedora
rm -rf $RPM_BUILD_ROOT
%{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
-for x in $RPM_BUILD_ROOT/%{_bindir}/*.py; do mv "$x" "${x%.py}"; done
-chmod +x $RPM_BUILD_ROOT/%{python_sitelib}/cloudinit/SshUtil.py
-mkdir -p $RPM_BUILD_ROOT/%{_sharedstatedir}/cloud
-
-# We supply our own config file since our software differs from Ubuntu's.
-cp -p %{SOURCE1} $RPM_BUILD_ROOT/%{_sysconfdir}/cloud/cloud.cfg
-
-# Note that /etc/rsyslog.d didn't exist by default until F15.
-# el6 request: https://bugzilla.redhat.com/show_bug.cgi?id=740420
-mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rsyslog.d
-cp -p tools/21-cloudinit.conf $RPM_BUILD_ROOT/%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
-
-# Install the init scripts
-install -p -D -m 755 %{SOURCE3} %{buildroot}%{_initrddir}/cloud-config
-install -p -D -m 755 %{SOURCE4} %{buildroot}%{_initrddir}/cloud-final
-install -p -D -m 755 %{SOURCE5} %{buildroot}%{_initrddir}/cloud-init
-install -p -D -m 755 %{SOURCE6} %{buildroot}%{_initrddir}/cloud-init-local
-
-
%clean
rm -rf $RPM_BUILD_ROOT
+%files
-%post
-if [ $1 -eq 1 ] ; then
- # Initial installation
- # Enabled by default per "runs once then goes away" exception
- for svc in config final init init-local; do
- chkconfig --add cloud-$svc
- chkconfig cloud-$svc on
- done
-fi
-
-%preun
-if [ $1 -eq 0 ] ; then
- # Package removal, not upgrade
- for svc in config final init init-local; do
- chkconfig --del cloud-$svc
- chkconfig cloud-$svc on
- done
- # One-shot services -> no need to stop
-fi
+# Docs
+{{for r in docs}}
+%doc {{r}}
+{{endfor}}
-%postun
-# One-shot services -> no need to restart
+# Configs
+{{for r in configs}}
+%config(noreplace) %{_sysconfdir}/{{r}}
+{{endfor}}
+# Other files
+{{for r in files}}
+{{r}}
+{{endfor}}
-%files
-%doc ChangeLog LICENSE TODO README.fedora
-%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg
-%dir %{_sysconfdir}/cloud/cloud.cfg.d
-%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/*.cfg
-%doc %{_sysconfdir}/cloud/cloud.cfg.d/README
-%dir %{_sysconfdir}/cloud/templates
-%config(noreplace) %{_sysconfdir}/cloud/templates/*
-%{_initrddir}/cloud-*
+# Python sitelib
%{python_sitelib}/*
-%{_libexecdir}/%{name}
-%{_bindir}/cloud-init*
-%doc %{_datadir}/doc/%{name}
-%dir %{_sharedstatedir}/cloud
-
-%config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
-
%changelog
-* Mon Jun 18 2012 Pádraig Brady <P@draigBrady.com> - 0.6.3-0.6.bzr532
-- Further adjustments to support EPEL 6
-
-* Fri Jun 15 2012 Tomas Karasek <tomas.karasek@cern.ch> - 0.6.3-0.5.bzr532
-- Fix cloud-init-cfg invocation in init script
-
-* Tue May 22 2012 Pádraig Brady <P@draigBrady.com> - 0.6.3-0.4.bzr532
-- Support EPEL 6
-
-* Sat Mar 31 2012 Andy Grimm <agrimm@gmail.com> - 0.6.3-0.2.bzr532
-- Fixed incorrect interpretation of relative path for
- AuthorizedKeysFile (BZ #735521)
-
-* Mon Mar 5 2012 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.3-0.1.bzr532
-- Rebased against upstream rev 532
-- Fixed runparts() incompatibility with Fedora
-
-* Thu Jan 12 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6.2-0.8.bzr457
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
-
-* Wed Oct 5 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.7.bzr457
-- Disabled SSH key-deleting on startup
-
-* Wed Sep 28 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.6.bzr457
-- Consolidated selinux file context patches
-- Fixed cloud-init.service dependencies
-- Updated sshkeytypes patch
-- Dealt with differences from Ubuntu's sshd
-
-* Sat Sep 24 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.5.bzr457
-- Rebased against upstream rev 457
-- Added missing dependencies
-
-* Fri Sep 23 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.4.bzr450
-- Added more macros to the spec file
-
-* Fri Sep 23 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.3.bzr450
-- Fixed logfile permission checking
-- Fixed SSH key generation
-- Fixed a bad method call in FQDN-guessing [LP:857891]
-- Updated localefile patch
-- Disabled the grub_dpkg module
-- Fixed failures due to empty script dirs [LP:857926]
-
-* Fri Sep 23 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.2.bzr450
-- Updated tzsysconfig patch
-* Wed Sep 21 2011 Garrett Holmstrom <gholms@fedoraproject.org> - 0.6.2-0.1.bzr450
-- Initial packaging
+{{changelog}}