diff options
author | Scott Moser <smoser@ubuntu.com> | 2012-11-10 22:32:31 -0500 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2012-11-10 22:32:31 -0500 |
commit | 6a3bd563282a51695bf1384d057d0495fd59929f (patch) | |
tree | 0df5b82bf2b49b8899614688886fa6f5e3b4cdad | |
parent | d7a42777c83668111d9bb496f581605b33a0b4f2 (diff) | |
parent | 9cb3130b0b87eabe458df7dc113f00431ff3648e (diff) | |
download | vyos-cloud-init-6a3bd563282a51695bf1384d057d0495fd59929f.tar.gz vyos-cloud-init-6a3bd563282a51695bf1384d057d0495fd59929f.zip |
add yum_add_repo configuration module
Add in a configuration module that can write out the yum.repo format for
those that want to hook into different repos for installing.
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | cloudinit/config/cc_yum_add_repo.py | 106 | ||||
-rw-r--r-- | doc/examples/cloud-config-yum-repo.txt | 20 | ||||
-rw-r--r-- | tests/unittests/test_handler/test_handler_yum_add_repo.py | 68 |
4 files changed, 195 insertions, 0 deletions
@@ -22,6 +22,7 @@ - add yaml/cloud config examples checking tool [revno 706] - Fix the merging of group configuration when that group configuration is a dict => members. [revno 707] + - add yum_add_repo configuration module for adding additional yum repos 0.7.0: - add a 'exception_cb' argument to 'wait_for_url'. If provided, this method will be called back with the exception received and the message. diff --git a/cloudinit/config/cc_yum_add_repo.py b/cloudinit/config/cc_yum_add_repo.py new file mode 100644 index 00000000..5c273825 --- /dev/null +++ b/cloudinit/config/cc_yum_add_repo.py @@ -0,0 +1,106 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow <harlowja@yahoo-inc.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from cloudinit import util + +import configobj + + +def _canonicalize_id(repo_id): + repo_id = repo_id.lower().replace("-", "_") + repo_id = repo_id.replace(" ", "_") + return repo_id + + +def _format_repo_value(val): + if isinstance(val, (bool)): + # Seems like yum prefers 1/0 + return str(int(val)) + if isinstance(val, (list, tuple)): + # Can handle 'lists' in certain cases + # See: http://bit.ly/Qqrf1t + return "\n ".join([_format_repo_value(v) for v in val]) + if not isinstance(val, (basestring, str)): + return str(val) + return val + + +## TODO(harlowja): move to distro? +# See man yum.conf +def _format_repository_config(repo_id, repo_config): + to_be = configobj.ConfigObj() + to_be[repo_id] = {} + # Do basic translation of the items -> values + for (k, v) in repo_config.items(): + # For now assume that people using this know + # the format of yum and don't verify keys/values further + to_be[repo_id][k] = _format_repo_value(v) + lines = to_be.write() + lines.insert(0, "# Created by cloud-init on %s" % (util.time_rfc2822())) + return "\n".join(lines) + + +def handle(name, cfg, _cloud, log, _args): + repos = cfg.get('yum_repos') + if not repos: + log.debug(("Skipping module named %s," + " no 'yum_repos' configuration found"), name) + return + repo_base_path = util.get_cfg_option_str(cfg, 'yum_repo_dir', + '/etc/yum.repos.d/') + repo_locations = {} + repo_configs = {} + for (repo_id, repo_config) in repos.items(): + canon_repo_id = _canonicalize_id(repo_id) + repo_fn_pth = os.path.join(repo_base_path, "%s.repo" % (canon_repo_id)) + if os.path.exists(repo_fn_pth): + log.info("Skipping repo %s, file %s already exists!", + repo_id, repo_fn_pth) + continue + elif canon_repo_id in repo_locations: + log.info("Skipping repo %s, file %s already pending!", + repo_id, repo_fn_pth) + continue + if not repo_config: + repo_config = {} + # Do some basic sanity checks/cleaning + n_repo_config = {} + for (k, v) in repo_config.items(): + k = k.lower().strip().replace("-", "_") + if k: + n_repo_config[k] = v + repo_config = n_repo_config + missing_required = 0 + for req_field in ['baseurl']: + if not req_field in repo_config: + log.warn(("Repository %s does not contain a %s" + " configuration 'required' entry"), + repo_id, req_field) + missing_required += 1 + if not missing_required: + repo_configs[canon_repo_id] = repo_config + repo_locations[canon_repo_id] = repo_fn_pth + else: + log.warn("Repository %s is missing %s required fields, skipping!", + repo_id, missing_required) + for (c_repo_id, path) in repo_locations.items(): + repo_blob = _format_repository_config(c_repo_id, + repo_configs.get(c_repo_id)) + util.write_file(path, repo_blob) diff --git a/doc/examples/cloud-config-yum-repo.txt b/doc/examples/cloud-config-yum-repo.txt new file mode 100644 index 00000000..ab2c031e --- /dev/null +++ b/doc/examples/cloud-config-yum-repo.txt @@ -0,0 +1,20 @@ +#cloud-config +# vim: syntax=yaml +# +# Add yum repository configuration to the system +# +# The following example adds the file /etc/yum.repos.d/epel_testing.repo +# which can then subsequently be used by yum for later operations. +yum_repos: + # The name of the repository + epel-testing: + # Any repository configuration options + # See: man yum.conf + # + # This one is required! + baseurl: http://download.fedoraproject.org/pub/epel/testing/5/$basearch + enabled: false + failovermethod: priority + gpgcheck: true + gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL + name: Extra Packages for Enterprise Linux 5 - Testing diff --git a/tests/unittests/test_handler/test_handler_yum_add_repo.py b/tests/unittests/test_handler/test_handler_yum_add_repo.py new file mode 100644 index 00000000..c7fcddc4 --- /dev/null +++ b/tests/unittests/test_handler/test_handler_yum_add_repo.py @@ -0,0 +1,68 @@ +from cloudinit import helpers +from cloudinit import util + +from cloudinit.config import cc_yum_add_repo + +from tests.unittests import helpers + +import logging + +from StringIO import StringIO + +import configobj + +LOG = logging.getLogger(__name__) + + +class TestConfig(helpers.FilesystemMockingTestCase): + def setUp(self): + super(TestConfig, self).setUp() + self.tmp = self.makeDir(prefix="unittest_") + + def test_bad_config(self): + cfg = { + 'yum_repos': { + 'epel-testing': { + 'name': 'Extra Packages for Enterprise Linux 5 - Testing', + # Missing this should cause the repo not to be written + #'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch', + 'enabled': False, + 'gpgcheck': True, + 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL', + 'failovermethod': 'priority', + }, + }, + } + self.patchUtils(self.tmp) + cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, []) + with self.assertRaises(IOError): + util.load_file("/etc/yum.repos.d/epel_testing.repo") + + def test_write_config(self): + cfg = { + 'yum_repos': { + 'epel-testing': { + 'name': 'Extra Packages for Enterprise Linux 5 - Testing', + 'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch', + 'enabled': False, + 'gpgcheck': True, + 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL', + 'failovermethod': 'priority', + }, + }, + } + self.patchUtils(self.tmp) + cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, []) + contents = util.load_file("/etc/yum.repos.d/epel_testing.repo") + contents = configobj.ConfigObj(StringIO(contents)) + expected = { + 'epel_testing': { + 'name': 'Extra Packages for Enterprise Linux 5 - Testing', + 'failovermethod': 'priority', + 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL', + 'enabled': '0', + 'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch', + 'gpgcheck': '1', + } + } + self.assertEquals(expected, dict(contents)) |