Merge ~dylan.perry/cloud-init:fix-yum-config-array-quoting into cloud-init:master

Proposed by Dylan Perry
Status: Merged
Merged at revision: d16632ad8dfd1844d265d93ab00b54d419626019
Proposed branch: ~dylan.perry/cloud-init:fix-yum-config-array-quoting
Merge into: cloud-init:master
Diff against target: 134 lines (+64/-15)
2 files modified
cloudinit/config/cc_yum_add_repo.py (+14/-9)
tests/unittests/test_handler/test_handler_yum_add_repo.py (+50/-6)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
cloud-init Commiters Pending
Review via email: mp+322268@code.launchpad.net

Commit message

Fix yum repo config where keys contain array values

ConfigObj produces configuration files that are incompatible with yum if
multiple values are listed for a configuration key. Switch to the builtin
configparser, and ConfigParser (Python 2) which correctly handles this
case.

Remove broken bitly link

Add additional test case for array values in yum_repos definition

Description of the change

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/config/cc_yum_add_repo.py b/cloudinit/config/cc_yum_add_repo.py
2index ef8535e..3f1e706 100644
3--- a/cloudinit/config/cc_yum_add_repo.py
4+++ b/cloudinit/config/cc_yum_add_repo.py
5@@ -32,7 +32,10 @@ entry, the config entry will be skipped.
6
7 import os
8
9-import configobj
10+try:
11+ from configparser import ConfigParser
12+except ImportError:
13+ from ConfigParser import ConfigParser
14 import six
15
16 from cloudinit import util
17@@ -52,8 +55,7 @@ def _format_repo_value(val):
18 return str(int(val))
19 if isinstance(val, (list, tuple)):
20 # Can handle 'lists' in certain cases
21- # See: http://bit.ly/Qqrf1t
22- return "\n ".join([_format_repo_value(v) for v in val])
23+ return "\n".join([_format_repo_value(v) for v in val])
24 if not isinstance(val, six.string_types):
25 return str(val)
26 return val
27@@ -62,16 +64,19 @@ def _format_repo_value(val):
28 # TODO(harlowja): move to distro?
29 # See man yum.conf
30 def _format_repository_config(repo_id, repo_config):
31- to_be = configobj.ConfigObj()
32- to_be[repo_id] = {}
33+ to_be = ConfigParser()
34+ to_be.add_section(repo_id)
35 # Do basic translation of the items -> values
36 for (k, v) in repo_config.items():
37 # For now assume that people using this know
38 # the format of yum and don't verify keys/values further
39- to_be[repo_id][k] = _format_repo_value(v)
40- lines = to_be.write()
41- lines.insert(0, "# Created by cloud-init on %s" % (util.time_rfc2822()))
42- return "\n".join(lines)
43+ to_be.set(repo_id, k, _format_repo_value(v))
44+ to_be_stream = six.StringIO()
45+ to_be.write(to_be_stream)
46+ to_be_stream.seek(0)
47+ lines = to_be_stream.readlines()
48+ lines.insert(0, "# Created by cloud-init on %s\n" % (util.time_rfc2822()))
49+ return "".join(lines)
50
51
52 def handle(name, cfg, _cloud, log, _args):
53diff --git a/tests/unittests/test_handler/test_handler_yum_add_repo.py b/tests/unittests/test_handler/test_handler_yum_add_repo.py
54index 3feba86..4815bdb 100644
55--- a/tests/unittests/test_handler/test_handler_yum_add_repo.py
56+++ b/tests/unittests/test_handler/test_handler_yum_add_repo.py
57@@ -5,10 +5,13 @@ from cloudinit import util
58
59 from .. import helpers
60
61-import configobj
62+try:
63+ from configparser import ConfigParser
64+except ImportError:
65+ from ConfigParser import ConfigParser
66 import logging
67 import shutil
68-from six import BytesIO
69+from six import StringIO
70 import tempfile
71
72 LOG = logging.getLogger(__name__)
73@@ -54,9 +57,9 @@ class TestConfig(helpers.FilesystemMockingTestCase):
74 }
75 self.patchUtils(self.tmp)
76 cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
77- contents = util.load_file("/etc/yum.repos.d/epel_testing.repo",
78- decode=False)
79- contents = configobj.ConfigObj(BytesIO(contents))
80+ contents = util.load_file("/etc/yum.repos.d/epel_testing.repo")
81+ parser = ConfigParser()
82+ parser.readfp(StringIO(contents))
83 expected = {
84 'epel_testing': {
85 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
86@@ -67,6 +70,47 @@ class TestConfig(helpers.FilesystemMockingTestCase):
87 'gpgcheck': '1',
88 }
89 }
90- self.assertEqual(expected, dict(contents))
91+ for section in expected:
92+ self.assertTrue(parser.has_section(section),
93+ "Contains section {}".format(section))
94+ for k, v in expected[section].items():
95+ self.assertEqual(parser.get(section, k), v)
96+
97+ def test_write_config_array(self):
98+ cfg = {
99+ 'yum_repos': {
100+ 'puppetlabs-products': {
101+ 'name': 'Puppet Labs Products El 6 - $basearch',
102+ 'baseurl':
103+ 'http://yum.puppetlabs.com/el/6/products/$basearch',
104+ 'gpgkey': [
105+ 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs',
106+ 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppet',
107+ ],
108+ 'enabled': True,
109+ 'gpgcheck': True,
110+ }
111+ }
112+ }
113+ self.patchUtils(self.tmp)
114+ cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
115+ contents = util.load_file("/etc/yum.repos.d/puppetlabs_products.repo")
116+ parser = ConfigParser()
117+ parser.readfp(StringIO(contents))
118+ expected = {
119+ 'puppetlabs_products': {
120+ 'name': 'Puppet Labs Products El 6 - $basearch',
121+ 'baseurl': 'http://yum.puppetlabs.com/el/6/products/$basearch',
122+ 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs\n'
123+ 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppet',
124+ 'enabled': '1',
125+ 'gpgcheck': '1',
126+ }
127+ }
128+ for section in expected:
129+ self.assertTrue(parser.has_section(section),
130+ "Contains section {}".format(section))
131+ for k, v in expected[section].items():
132+ self.assertEqual(parser.get(section, k), v)
133
134 # vi: ts=4 expandtab

Subscribers

People subscribed via source and target branches