Merge lp:~mmoulton/cloud-init/chef into lp:~cloud-init-dev/cloud-init/trunk
- chef
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 446 |
Proposed branch: | lp:~mmoulton/cloud-init/chef |
Merge into: | lp:~cloud-init-dev/cloud-init/trunk |
Diff against target: |
221 lines (+92/-68) 3 files modified
cloudinit/CloudConfig/cc_chef.py (+59/-44) doc/examples/cloud-config-chef.txt (+22/-16) templates/chef_client.rb.tmpl (+11/-8) |
To merge this branch: | bzr merge lp:~mmoulton/cloud-init/chef |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Scott Moser | Pending | ||
Review via email: mp+74900@code.launchpad.net |
Commit message
Description of the change
This branch is based on lp:~avishai-ish-shalom/cloud-init/chef with several bug fixes to support both 'gems' and 'packages' install types.
This branch has been fully tested with the Beta 1 release of Oneiric.
In addition to bug fixes, this branch introduces support for setting the Chef 'node_name' and 'environment' properties.
Scott Moser (smoser) wrote : | # |
- 447. By Mike Moulton
-
Set sane defaults for 'node_name' and 'environment'
Support both 'validation_cert' and 'validation_key' for backwards compatibility
Cleaned up line length
Mike Moulton (mmoulton) wrote : | # |
> A couple things I'd like to see fixed
> - you added 'environment' and 'node_name' configuration variables, but did not
> add defaults. That means a cloud-config that would previously have worked
> will now fail in the rendering of that template. (I think). Please supply
> default values for those.
I have updated the branch to include sane defaults for both node_name and environment.
> - please try to keep lines to less than 80 chars. Some of the lines added are
> well over that.
I've cleaned this up.
> - you've changed 'validation_cert' to 'validation_key', and the example even
> suggest different formatting going into the same file
> (/etc/chef/
In Chef, the client uses a key pair to validate it's request with the server. The key supplied in the 'validation_key' attribute is the private key for this pair. The naming originally implied and showed this value should have been a certificate, leading to confusion.
I have updated the branch to support the original 'validation_cert' and the new 'validation_key' param where 'validation_key' has precidence.
Scott Moser (smoser) wrote : | # |
The changes seem fine. avishai can you test this ?
The one I see that avishai's branch ([1], specifically [2]) has that this one does not have is 'initial_
[1] lp:~avishai-ish-shalom/cloud-init/chef
[2] http://
- 448. By Mike Moulton
-
Bringing in proper json support for firstboot.json from lp:~avishai-ish-shalom/cloud-init/chef
Bringing in 'initial_properties' support from lp:~avishai-ish-shalom/cloud-init/chef
Mike Moulton (mmoulton) wrote : | # |
This branch now models Avishai's branch [1] for both initial_attributes and using json to write the file.
I also fixed a bug where the initial_properties would not be written if the run_list was not specified. This is important as you can push run lists to a node after the fact via the Chef server.
[1] http://
Preview Diff
1 | === modified file 'cloudinit/CloudConfig/cc_chef.py' |
2 | --- cloudinit/CloudConfig/cc_chef.py 2011-09-08 23:10:17 +0000 |
3 | +++ cloudinit/CloudConfig/cc_chef.py 2011-09-13 00:43:10 +0000 |
4 | @@ -1,6 +1,7 @@ |
5 | # vi: ts=4 expandtab |
6 | # |
7 | # Author: Avishai Ish-Shalom <avishai@fewbytes.com> |
8 | +# Author: Mike Moulton <mike@meltmedia.com> |
9 | # |
10 | # This program is free software: you can redistribute it and/or modify |
11 | # it under the terms of the GNU General Public License version 3, as |
12 | @@ -17,6 +18,7 @@ |
13 | import pwd |
14 | import socket |
15 | import subprocess |
16 | +import json |
17 | import StringIO |
18 | import ConfigParser |
19 | import cloudinit.CloudConfig as cc |
20 | @@ -31,60 +33,73 @@ |
21 | if not cfg.has_key('chef'): return |
22 | chef_cfg = cfg['chef'] |
23 | |
24 | - # Install chef packages from selected source |
25 | - install_type = util.get_cfg_option_str(chef_cfg, "install_type", "packages") |
26 | - if not os.path.isfile('/usr/bin/chef-client'): |
27 | - if install_type == "gems": |
28 | - if chef_cfg.has_key('version'): |
29 | - chef_version = chef_cfg['version'] |
30 | - else: |
31 | - chef_version = None |
32 | - install_chef_from_gems( |
33 | - util.get_cfg_option_str(chef_cfg, 'ruby_version', '1.8'), |
34 | - chef_version) |
35 | - else: |
36 | - cc.install_packages(('chef',)) |
37 | + # ensure the chef directories we use exist |
38 | + mkdirs(['/etc/chef', '/var/log/chef', '/var/lib/chef', |
39 | + '/var/cache/chef', '/var/backups/chef', '/var/run/chef']) |
40 | |
41 | - # set the validation cert |
42 | - if chef_cfg.has_key('validation_cert'): |
43 | - with open('/etc/chef/validation.pem', 'w') as validation_cert_fh: |
44 | - validation_cert_fh.write(chef_cfg['validation_cert']) |
45 | + # set the validation key based on the presence of either 'validation_key' |
46 | + # or 'validation_cert'. In the case where both exist, 'validation_key' |
47 | + # takes precedence |
48 | + if chef_cfg.has_key('validation_key') or chef_cfg.has_key('validation_cert'): |
49 | + validation_key = util.get_cfg_option_str(chef_cfg, 'validation_key', |
50 | + chef_cfg['validation_cert']) |
51 | + with open('/etc/chef/validation.pem', 'w') as validation_key_fh: |
52 | + validation_key_fh.write(validation_key) |
53 | |
54 | validation_name = chef_cfg.get('validation_name','chef-validator') |
55 | # create the chef config from template |
56 | util.render_to_file('chef_client.rb', '/etc/chef/client.rb', |
57 | {'server_url': chef_cfg['server_url'], |
58 | + 'node_name': util.get_cfg_option_str(chef_cfg, 'node_name', |
59 | + cloud.datasource.get_instance_id()), |
60 | + 'environment': util.get_cfg_option_str(chef_cfg, 'environment', |
61 | + '_default'), |
62 | 'validation_name': chef_cfg['validation_name']}) |
63 | |
64 | - chef_args = ['-d'] |
65 | # set the firstboot json |
66 | - if chef_cfg.has_key('run_list'): |
67 | - with open('/etc/chef/firstboot.json', 'w') as firstboot_json_fh: |
68 | - firstboot_json_fh.write("{\n\"run_list\":\n[\n") |
69 | - firstboot_json_fh.write( |
70 | - ",\n".join(["\"%s\"" % runlist_item for runlist_item in chef_cfg['run_list']]) |
71 | - ) |
72 | - firstboot_json_fh.write("]\n\}") |
73 | - chef_args.append('-j /etc/chef/firstboot.json') |
74 | + with open('/etc/chef/firstboot.json', 'w') as firstboot_json_fh: |
75 | + initial_json = {} |
76 | + if chef_cfg.has_key('run_list'): |
77 | + initial_json['run_list'] = chef_cfg['run_list'] |
78 | + if chef_cfg.has_key('initial_attributes'): |
79 | + initial_attributes = chef_cfg['initial_attributes'] |
80 | + for k in initial_attributes.keys(): initial_json[k] = initial_attributes[k] |
81 | + firstboot_json_fh.write(json.dumps(initial_json)) |
82 | |
83 | - # and finally, run chef |
84 | - log.debug("running chef-client %s" % chef_args) |
85 | - subprocess.check_call(['/usr/bin/chef-client'] + chef_args) |
86 | + # If chef is not installed, we install chef based on 'install_type' |
87 | + if not os.path.isfile('/usr/bin/chef-client'): |
88 | + install_type = util.get_cfg_option_str(chef_cfg, 'install_type', 'packages') |
89 | + if install_type == "gems": |
90 | + # this will install and run the chef-client from gems |
91 | + chef_version = util.get_cfg_option_str(chef_cfg, 'version', None) |
92 | + ruby_version = util.get_cfg_option_str(chef_cfg, 'ruby_version', '1.8') |
93 | + install_chef_from_gems(ruby_version, chef_version) |
94 | + # and finally, run chef-client |
95 | + log.debug('running chef-client') |
96 | + subprocess.check_call(['/usr/bin/chef-client', '-d', '-i', '1800', '-s', '20']) |
97 | + else: |
98 | + # this will install and run the chef-client from packages |
99 | + cc.install_packages(('chef',)) |
100 | |
101 | def install_chef_from_gems(ruby_version, chef_version = None): |
102 | cc.install_packages(ruby_packages[ruby_version]) |
103 | - gem_bin = get_gem_bin() |
104 | - if not os.path.exists('/usr/bin/gem'): os.symlink(gem_bin, '/usr/bin/gem') |
105 | - chef_version_arg = "" |
106 | - if chef_version: chef_version_arg = "-v %s" % chef_version |
107 | - subprocess.check_call([gem_bin,'install','chef',chef_version_arg, '--no-ri','--no-rdoc','--no-test','-q']) |
108 | - os.mkdirs('/etc/chef', '/var/log/chef', '/var/lib/chef', '/var/cache/chef', '/var/backups/chef', '/var/run/chef') |
109 | - os.symlink('/var/lib/gem/%s/bin/chef-client' % ruby_version, '/usr/bin/chef-client') |
110 | - # Ohai ruby plugin breaks if there is no ruby or gem binaries at /usr/bin, so |
111 | - try: os.symlink('/usr/bin/gem%s' % ruby_version, '/usr/bin/gem') |
112 | - except: pass |
113 | - try: os.symlink('/usr/bin/ruby%s' % ruby_version, '/usr/bin/ruby') |
114 | - except: pass |
115 | - |
116 | -def get_gem_bin(): |
117 | - return '/usr/bin/gem%s' % util.get_cfg_option_str(chef_cfg, 'ruby_version', '1.8') |
118 | + if not os.path.exists('/usr/bin/gem'): |
119 | + os.symlink('/usr/bin/gem%s' % ruby_version, '/usr/bin/gem') |
120 | + if not os.path.exists('/usr/bin/ruby'): |
121 | + os.symlink('/usr/bin/ruby%s' % ruby_version, '/usr/bin/ruby') |
122 | + if chef_version: |
123 | + subprocess.check_call(['/usr/bin/gem','install','chef', |
124 | + '-v %s' % chef_version, '--no-ri', |
125 | + '--no-rdoc','--bindir','/usr/bin','-q']) |
126 | + else: |
127 | + subprocess.check_call(['/usr/bin/gem','install','chef', |
128 | + '--no-ri','--no-rdoc','--bindir', |
129 | + '/usr/bin','-q']) |
130 | + |
131 | +def ensure_dir(d): |
132 | + if not os.path.exists(d): |
133 | + os.makedirs(d) |
134 | + |
135 | +def mkdirs(dirs): |
136 | + for d in dirs: |
137 | + ensure_dir(d) |
138 | |
139 | === modified file 'doc/examples/cloud-config-chef.txt' |
140 | --- doc/examples/cloud-config-chef.txt 2011-04-21 14:57:54 +0000 |
141 | +++ doc/examples/cloud-config-chef.txt 2011-09-13 00:43:10 +0000 |
142 | @@ -9,30 +9,36 @@ |
143 | apt_mirror: http://apt.opscode.com/ |
144 | |
145 | chef: |
146 | - # If you want to install from rubygems: |
147 | + |
148 | + # Valid values are 'gems' and 'packages' |
149 | install_type: "gems" |
150 | |
151 | # Chef settings |
152 | server_url: "https://chef.yourorg.com:4000" |
153 | |
154 | + # Node Name |
155 | + # Defaults to the instance-id if not present |
156 | + node_name: "your-node-name" |
157 | + |
158 | + # Environment |
159 | + # Defaults to '_default' if not present |
160 | + environment: "production" |
161 | + |
162 | # Default validation name is chef-validator |
163 | validation_name: "yourorg-validator" |
164 | - validation_cert: | |
165 | - -----BEGIN CERTIFICATE----- |
166 | - MIICCTCCAXKgAwIBAgIBATANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJjYTAe |
167 | - Fw0xMDAyMTUxNzI5MjFaFw0xNTAyMTQxNzI5MjFaMA0xCzAJBgNVBAMMAmNhMIGf |
168 | - MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCu7Q40sm47/E1Pf+r8AYb/V/FWGPgc |
169 | - b014OmNoX7dgCxTDvps/h8Vw555PdAFsW5+QhsGr31IJNI3kSYprFQcYf7A8tNWu |
170 | - 1MASW2CfaEiOEi9F1R3R4Qlz4ix+iNoHiUDTjazw/tZwEdxaQXQVLwgTGRwVa+aA |
171 | - qbutJKi93MILLwIDAQABo3kwdzA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1Ynkv |
172 | - T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDwYDVR0TAQH/BAUwAwEB/zAd |
173 | - BgNVHQ4EFgQUu4+jHB+GYE5Vxo+ol1OAhevspjAwCwYDVR0PBAQDAgEGMA0GCSqG |
174 | - SIb3DQEBBQUAA4GBAH/rxlUIjwNb3n7TXJcDJ6MMHUlwjr03BDJXKb34Ulndkpaf |
175 | - +GAlzPXWa7bO908M9I8RnPfvtKnteLbvgTK+h+zX1XCty+S2EQWk29i2AdoqOTxb |
176 | - hppiGMp0tT5Havu4aceCXiy2crVcudj3NFciy8X66SoECemW9UYDCb9T5D0d |
177 | - -----END CERTIFICATE----- |
178 | - |
179 | + validation_key: | |
180 | + -----BEGIN RSA PRIVATE KEY----- |
181 | + YOUR-ORGS-VALIDATION-KEY-HERE |
182 | + -----END RSA PRIVATE KEY----- |
183 | + |
184 | # A run list for a first boot json |
185 | run_list: |
186 | - "recipe[apache2]" |
187 | - "role[db]" |
188 | + |
189 | + # Specify a list of initial attributes used by the cookbooks |
190 | + initial_attributes: |
191 | + apache: |
192 | + prefork: |
193 | + maxclients: 100 |
194 | + keepalive: "off" |
195 | |
196 | === modified file 'templates/chef_client.rb.tmpl' |
197 | --- templates/chef_client.rb.tmpl 2011-04-21 14:57:54 +0000 |
198 | +++ templates/chef_client.rb.tmpl 2011-09-13 00:43:10 +0000 |
199 | @@ -1,12 +1,15 @@ |
200 | -log_level :info |
201 | -log_location "/var/log/chef/client.log" |
202 | -ssl_verify_mode :verify_none |
203 | +log_level :info |
204 | +log_location "/var/log/chef/client.log" |
205 | +ssl_verify_mode :verify_none |
206 | validation_client_name "$validation_name" |
207 | validation_key "/etc/chef/validation.pem" |
208 | -client_key "/etc/chef/client.pem" |
209 | -chef_server_url "$server_url" |
210 | -file_cache_path "/var/cache/chef" |
211 | -file_backup_path "/var/backups/chef" |
212 | -pid_file "/var/run/chef/client.pid" |
213 | +client_key "/etc/chef/client.pem" |
214 | +chef_server_url "$server_url" |
215 | +environment "$environment" |
216 | +node_name "$node_name" |
217 | +json_attribs "/etc/chef/firstboot.json" |
218 | +file_cache_path "/var/cache/chef" |
219 | +file_backup_path "/var/backups/chef" |
220 | +pid_file "/var/run/chef/client.pid" |
221 | Chef::Log::Formatter.show_time = true |
222 |
A couple things I'd like to see fixed validation. pem). Why is that?
- you added 'environment' and 'node_name' configuration variables, but did not add defaults. That means a cloud-config that would previously have worked will now fail in the rendering of that template. (I think). Please supply default values for those.
- please try to keep lines to less than 80 chars. Some of the lines added are well over that.
- you've changed 'validation_cert' to 'validation_key', and the example even suggest different formatting going into the same file (/etc/chef/