Merge lp:~smoser/cloud-init/trunk.1568940 into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Scott Moser
Status: Merged
Merged at revision: 1207
Proposed branch: lp:~smoser/cloud-init/trunk.1568940
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 174 lines (+84/-13)
4 files modified
cloudinit/config/cc_chef.py (+17/-9)
doc/examples/cloud-config-chef.txt (+3/-1)
templates/chef_client.rb.tmpl (+1/-1)
tests/unittests/test_handler/test_handler_chef.py (+63/-2)
To merge this branch: bzr merge lp:~smoser/cloud-init/trunk.1568940
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+291635@code.launchpad.net

Commit message

chef: straighten out validation_cert and validation_key

Now, validation_key is always a path to a file, as it is in
chef's client.rb syntax.

validation_cert is always the *content* of that file that should
be written. However, if validation_cert is the string "system",
then we do not write that value, but rather assume the file exists.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cloudinit/config/cc_chef.py'
2--- cloudinit/config/cc_chef.py 2016-04-04 19:17:28 +0000
3+++ cloudinit/config/cc_chef.py 2016-04-12 14:47:21 +0000
4@@ -38,8 +38,10 @@
5 chef:
6 directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef,
7 /var/cache/chef, /var/backups/chef, /var/run/chef)
8- validation_key or validation_cert: (optional string to be written to
9- /etc/chef/validation.pem)
10+ validation_cert: (optional string to be written to file validation_key)
11+ special value 'system' means set use existing file
12+ validation_key: (optional the path for validation_cert. default
13+ /etc/chef/validation.pem)
14 firstboot_path: (path to write run_list and initial_attributes keys that
15 should also be present in this configuration, defaults
16 to /etc/chef/firstboot.json)
17@@ -64,6 +66,7 @@
18 server_url:
19 show_time:
20 ssl_verify_mode:
21+ validation_cert:
22 validation_key:
23 validation_name:
24 """
25@@ -105,6 +108,7 @@
26 # These are not symbols...
27 'log_location': '/var/log/chef/client.log',
28 'validation_key': CHEF_VALIDATION_PEM_PATH,
29+ 'validation_cert': None,
30 'client_key': "/etc/chef/client.pem",
31 'json_attribs': CHEF_FB_PATH,
32 'file_cache_path': "/var/cache/chef",
33@@ -201,13 +205,17 @@
34 for d in itertools.chain(chef_dirs, REQUIRED_CHEF_DIRS):
35 util.ensure_dir(d)
36
37- # Set the validation key based on the presence of either 'validation_key'
38- # or 'validation_cert'. In the case where both exist, 'validation_key'
39- # takes precedence
40- for key in ('validation_key', 'validation_cert'):
41- if key in chef_cfg and chef_cfg[key]:
42- util.write_file(CHEF_VALIDATION_PEM_PATH, chef_cfg[key])
43- break
44+ vkey_path = chef_cfg.get('validation_key', CHEF_VALIDATION_PEM_PATH)
45+ vcert = chef_cfg.get('validation_cert')
46+ # special value 'system' means do not overwrite the file
47+ # but still render the template to contain 'validation_key'
48+ if vcert:
49+ if vcert != "system":
50+ util.write_file(vkey_path, vcert)
51+ elif not os.path.isfile(vkey_path):
52+ log.warn("chef validation_cert provided as 'system', but "
53+ "validation_key path '%s' does not exist.",
54+ vkey_path)
55
56 # Create the chef config from template
57 template_fn = cloud.get_template_filename('chef_client.rb')
58
59=== modified file 'doc/examples/cloud-config-chef.txt'
60--- doc/examples/cloud-config-chef.txt 2012-12-12 15:39:43 +0000
61+++ doc/examples/cloud-config-chef.txt 2016-04-12 14:47:21 +0000
62@@ -67,7 +67,9 @@
63
64 # Default validation name is chef-validator
65 validation_name: "yourorg-validator"
66- validation_key: |
67+ # if validation_cert's value is "system" then it is expected
68+ # that the file already exists on the system.
69+ validation_cert: |
70 -----BEGIN RSA PRIVATE KEY-----
71 YOUR-ORGS-VALIDATION-KEY-HERE
72 -----END RSA PRIVATE KEY-----
73
74=== modified file 'templates/chef_client.rb.tmpl'
75--- templates/chef_client.rb.tmpl 2014-10-11 23:59:50 +0000
76+++ templates/chef_client.rb.tmpl 2016-04-12 14:47:21 +0000
77@@ -26,7 +26,7 @@
78 {% if validation_name %}
79 validation_client_name "{{validation_name}}"
80 {% endif %}
81-{% if validation_key %}
82+{% if validation_cert %}
83 validation_key "{{validation_key}}"
84 {% endif %}
85 {% if client_key %}
86
87=== modified file 'tests/unittests/test_handler/test_handler_chef.py'
88--- tests/unittests/test_handler/test_handler_chef.py 2015-02-10 20:32:32 +0000
89+++ tests/unittests/test_handler/test_handler_chef.py 2016-04-12 14:47:21 +0000
90@@ -75,17 +75,28 @@
91 'chef': {
92 'server_url': 'localhost',
93 'validation_name': 'bob',
94+ 'validation_key': "/etc/chef/vkey.pem",
95+ 'validation_cert': "this is my cert",
96 },
97 }
98 cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
99 for d in cc_chef.CHEF_DIRS:
100 self.assertTrue(os.path.isdir(d))
101 c = util.load_file(cc_chef.CHEF_RB_PATH)
102+
103+ # the content of these keys is not expected to be rendered to tmpl
104+ unrendered_keys = ('validation_cert',)
105 for k, v in cfg['chef'].items():
106+ if k in unrendered_keys:
107+ continue
108 self.assertIn(v, c)
109 for k, v in cc_chef.CHEF_RB_TPL_DEFAULTS.items():
110- if isinstance(v, six.string_types):
111- self.assertIn(v, c)
112+ if k in unrendered_keys:
113+ continue
114+ # the value from the cfg overrides that in the default
115+ val = cfg['chef'].get(k, v)
116+ if isinstance(val, six.string_types):
117+ self.assertIn(val, c)
118 c = util.load_file(cc_chef.CHEF_FB_PATH)
119 self.assertEqual({}, json.loads(c))
120
121@@ -131,3 +142,53 @@
122 c = util.load_file(cc_chef.CHEF_RB_PATH)
123 self.assertNotIn('json_attribs', c)
124 self.assertNotIn('Formatter.show_time', c)
125+
126+ @t_help.skipIf(not os.path.isfile(CLIENT_TEMPL),
127+ CLIENT_TEMPL + " is not available")
128+ def test_validation_cert_and_validation_key(self):
129+ # test validation_cert content is written to validation_key path
130+ tpl_file = util.load_file('templates/chef_client.rb.tmpl')
131+ self.patchUtils(self.tmp)
132+ self.patchOS(self.tmp)
133+
134+ util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
135+ v_path = '/etc/chef/vkey.pem'
136+ v_cert = 'this is my cert'
137+ cfg = {
138+ 'chef': {
139+ 'server_url': 'localhost',
140+ 'validation_name': 'bob',
141+ 'validation_key': v_path,
142+ 'validation_cert': v_cert
143+ },
144+ }
145+ cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
146+ content = util.load_file(cc_chef.CHEF_RB_PATH)
147+ self.assertIn(v_path, content)
148+ util.load_file(v_path)
149+ self.assertEqual(v_cert, util.load_file(v_path))
150+
151+ def test_validation_cert_with_system(self):
152+ # test validation_cert content is not written over system file
153+ tpl_file = util.load_file('templates/chef_client.rb.tmpl')
154+ self.patchUtils(self.tmp)
155+ self.patchOS(self.tmp)
156+
157+ v_path = '/etc/chef/vkey.pem'
158+ v_cert = "system"
159+ expected_cert = "this is the system file certificate"
160+ cfg = {
161+ 'chef': {
162+ 'server_url': 'localhost',
163+ 'validation_name': 'bob',
164+ 'validation_key': v_path,
165+ 'validation_cert': v_cert
166+ },
167+ }
168+ util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
169+ util.write_file(v_path, expected_cert)
170+ cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
171+ content = util.load_file(cc_chef.CHEF_RB_PATH)
172+ self.assertIn(v_path, content)
173+ util.load_file(v_path)
174+ self.assertEqual(expected_cert, util.load_file(v_path))