Merge lp:~avishai-ish-shalom/cloud-init/chef into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Avishai Ish-Shalom
Status: Superseded
Proposed branch: lp:~avishai-ish-shalom/cloud-init/chef
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 218 lines (+187/-1)
5 files modified
cloudinit/CloudConfig/cc_chef.py (+80/-0)
cloudinit/CloudConfig/cc_set_hostname.py (+6/-1)
doc/examples/cloud-config-chef.txt (+38/-0)
templates/chef_client.rb.tmpl (+12/-0)
tools/write-mime-multipart.py (+51/-0)
To merge this branch: bzr merge lp:~avishai-ish-shalom/cloud-init/chef
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+59513@code.launchpad.net

This proposal has been superseded by a proposal from 2011-06-30.

Description of the change

Added hostname prefix option, custom hostname attribute.
Added chef plugin.

To post a comment you must log in.
396. By Avishai Ish-Shalom

Added missing write-mime-multipart.py

397. By Avishai Ish-Shalom

Fixed review rejects: firstboot.json write, gem_binary not defined, wrong validation cert name

398. By Avishai Ish-Shalom

Fixed wrong firstboot json format

399. By Avishai Ish-Shalom

Merged main branch

400. By Avishai Ish-Shalom

Added environment and initial attributes support

Unmerged revisions

400. By Avishai Ish-Shalom

Added environment and initial attributes support

399. By Avishai Ish-Shalom

Merged main branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'cloudinit/CloudConfig/cc_chef.py'
2--- cloudinit/CloudConfig/cc_chef.py 1970-01-01 00:00:00 +0000
3+++ cloudinit/CloudConfig/cc_chef.py 2011-04-30 14:22:28 +0000
4@@ -0,0 +1,80 @@
5+# vi: ts=4 expandtab
6+#
7+# Author: Avishai Ish-Shalom <avishai@fewbytes.com>
8+#
9+# This program is free software: you can redistribute it and/or modify
10+# it under the terms of the GNU General Public License version 3, as
11+# published by the Free Software Foundation.
12+#
13+# This program is distributed in the hope that it will be useful,
14+# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+# GNU General Public License for more details.
17+#
18+# You should have received a copy of the GNU General Public License
19+# along with this program. If not, see <http://www.gnu.org/licenses/>.
20+import os
21+import pwd
22+import socket
23+import subprocess
24+import StringIO
25+import ConfigParser
26+import cloudinit.CloudConfig as cc
27+import cloudinit.util as util
28+
29+ruby_packages = {'1.8': ('ruby', 'rubygems', 'ruby-dev', 'libopenssl-ruby'),
30+ '1.9.1': ('ruby1.9.1', 'ruby1.9.1-dev', 'libruby1.9.1'),
31+ '1.9': ('ruby1.9', 'ruby1.9-dev', 'libruby1.9') }
32+
33+def handle(name,cfg,cloud,log,args):
34+ # If there isn't a chef key in the configuration don't do anything
35+ if not cfg.has_key('chef'): return
36+ chef_cfg = cfg['chef']
37+
38+ # Install chef packages from selected source
39+ if not os.path.isfile('/usr/bin/chef-client'):
40+ if chef_cfg['install_type'] == "gems":
41+ if chef_cfg.has_key('version'):
42+ chef_version = chef_cfg['version']
43+ else:
44+ chef_version = None
45+ install_chef_from_gems(
46+ util.get_cfg_option_str(chef_cfg, 'ruby_version', '1.8'),
47+ chef_version)
48+ else:
49+ cc.install_packages(('chef',))
50+
51+ # set the validation cert
52+ if chef_cfg.has_key('validation_cert'):
53+ with open('/etc/chef/validation.cert', 'w') as validation_cert_fh:
54+ validation_cert_fh.write(chef_cfg['validation_cert'])
55+
56+ # create the chef config from template
57+ util.render_to_file('chef_client.rb', '/etc/chef/client.rb',
58+ {'server_url': chef_cfg['server_url'], 'validation_name': chef_cfg['validation_name'] || 'chef-validator'})
59+
60+ chef_args = ['-d']
61+ # set the firstboot json
62+ if chef_cfg.has_key('run_list'):
63+ with open('/etc/chef/firstboot.json') as firstboot_json_fh:
64+ firstboot_json_fh.write("{\n\"run_list\":\n[\n")
65+ for runlist_item in chef_cfg['run_list']:
66+ firstboot_json_fh.write(runlist_item + "\n")
67+ firstboot_json_fh.write("]\n\}")
68+ chef_args.append('-j /etc/chef/firstboot.json')
69+
70+ # and finally, run chef
71+ subprocess.check_call(['/usr/bin/chef-client'] + chef_args)
72+
73+def install_chef_from_gems(ruby_version, chef_version = None):
74+ cc.install_packages(ruby_packages[ruby_version])
75+ chef_version_arg = ""
76+ if chef_version: chef_version_arg = "-v %s" % chef_version
77+ subprocess.check_call([gem_bin,'install','chef',chef_version_arg, '--no-ri','--no-rdoc','--no-test','-q'])
78+ os.mkdirs('/etc/chef', '/var/log/chef', '/var/lib/chef', '/var/cache/chef', '/var/backups/chef', '/var/run/chef')
79+ os.symlink('/var/lib/gem/%s/bin/chef-client' % ruby_version, '/usr/bin/chef-client')
80+ # Ohai ruby plugin breaks if there is no ruby or gem binaries at /usr/bin, so
81+ try: os.symlink('/usr/bin/gem%s' % ruby_version, '/usr/bin/gem')
82+ except: pass
83+ try: os.symlink('/usr/bin/ruby%s' % ruby_version, '/usr/bin/ruby')
84+ except: pass
85
86=== modified file 'cloudinit/CloudConfig/cc_set_hostname.py'
87--- cloudinit/CloudConfig/cc_set_hostname.py 2011-01-26 14:03:46 +0000
88+++ cloudinit/CloudConfig/cc_set_hostname.py 2011-04-30 14:22:28 +0000
89@@ -24,7 +24,12 @@
90 return(True)
91
92 try:
93- hostname = util.get_cfg_option_str(cfg,"hostname",cloud.get_hostname())
94+ hostname_prefix = util.get_cfg_option_str(cfg, "hostname_prefix", None)
95+ hostname_attr = util.get_cfg_option_str(cfg, "hostname_attribute", "hostname")
96+ hostname_function = getattr(cloud, 'get_' + hostname_attr, None)
97+ if hostname_fucntion is None: hostname_fucntion = cloud.get_hostname
98+ hostname = util.get_cfg_option_str(cfg,"hostname", hostname_function)
99+ if hostname_prefix: hostname = hostname_prefix + "-" + hostname
100 set_hostname(hostname, log)
101 except Exception as e:
102 util.logexc(log)
103
104=== added file 'doc/examples/cloud-config-chef.txt'
105--- doc/examples/cloud-config-chef.txt 1970-01-01 00:00:00 +0000
106+++ doc/examples/cloud-config-chef.txt 2011-04-30 14:22:28 +0000
107@@ -0,0 +1,38 @@
108+#cloud-config
109+#
110+# This is an example file to automatically setup and run puppetd
111+# when the instance boots for the first time.
112+# Make sure that this file is valid yaml before starting instances.
113+# It should be passed as user-data when starting the instance.
114+
115+# The default is to install from packages. If you want the latest packages from Opscode, be sure to add their repo:
116+apt_mirror: http://apt.opscode.com/
117+
118+chef:
119+ # If you want to install from rubygems:
120+ install_type: "gems"
121+
122+ # Chef settings
123+ server_url: "https://chef.yourorg.com:4000"
124+
125+ # Default validation name is chef-validator
126+ validation_name: "yourorg-validator"
127+ validation_cert: |
128+ -----BEGIN CERTIFICATE-----
129+ MIICCTCCAXKgAwIBAgIBATANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJjYTAe
130+ Fw0xMDAyMTUxNzI5MjFaFw0xNTAyMTQxNzI5MjFaMA0xCzAJBgNVBAMMAmNhMIGf
131+ MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCu7Q40sm47/E1Pf+r8AYb/V/FWGPgc
132+ b014OmNoX7dgCxTDvps/h8Vw555PdAFsW5+QhsGr31IJNI3kSYprFQcYf7A8tNWu
133+ 1MASW2CfaEiOEi9F1R3R4Qlz4ix+iNoHiUDTjazw/tZwEdxaQXQVLwgTGRwVa+aA
134+ qbutJKi93MILLwIDAQABo3kwdzA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1Ynkv
135+ T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDwYDVR0TAQH/BAUwAwEB/zAd
136+ BgNVHQ4EFgQUu4+jHB+GYE5Vxo+ol1OAhevspjAwCwYDVR0PBAQDAgEGMA0GCSqG
137+ SIb3DQEBBQUAA4GBAH/rxlUIjwNb3n7TXJcDJ6MMHUlwjr03BDJXKb34Ulndkpaf
138+ +GAlzPXWa7bO908M9I8RnPfvtKnteLbvgTK+h+zX1XCty+S2EQWk29i2AdoqOTxb
139+ hppiGMp0tT5Havu4aceCXiy2crVcudj3NFciy8X66SoECemW9UYDCb9T5D0d
140+ -----END CERTIFICATE-----
141+
142+ # A run list for a first boot json
143+ run_list:
144+ - "recipe[apache2]"
145+ - "role[db]"
146
147=== added file 'templates/chef_client.rb.tmpl'
148--- templates/chef_client.rb.tmpl 1970-01-01 00:00:00 +0000
149+++ templates/chef_client.rb.tmpl 2011-04-30 14:22:28 +0000
150@@ -0,0 +1,12 @@
151+log_level :info
152+log_location "/var/log/chef/client.log"
153+ssl_verify_mode :verify_none
154+validation_client_name "$validation_name"
155+validation_key "/etc/chef/validation.pem"
156+client_key "/etc/chef/client.pem"
157+chef_server_url "$server_url"
158+file_cache_path "/var/cache/chef"
159+file_backup_path "/var/backups/chef"
160+pid_file "/var/run/chef/client.pid"
161+Chef::Log::Formatter.show_time = true
162+
163
164=== added file 'tools/write-mime-multipart.py'
165--- tools/write-mime-multipart.py 1970-01-01 00:00:00 +0000
166+++ tools/write-mime-multipart.py 2011-04-30 14:22:28 +0000
167@@ -0,0 +1,51 @@
168+#! /usr/bin/env python
169+
170+import sys, os
171+import email
172+import mimetypes
173+import re
174+
175+mimetypes.types_map['.sh'] = 'text/x-shellscript'
176+cloud_config_mark_strings = { '#!': 'text/x-shellscript', '#include': 'text/x-include-url',
177+ '#cloud-config': 'text/cloud-config', '#upstart-job': 'text/upstart-job',
178+ '#cloud-boothook': 'text/cloud-boothook'
179+ }
180+def write_mime_multipart():
181+ multipart_msg = email.mime.Multipart.MIMEMultipart()
182+ for arg in sys.argv[1:]:
183+ if ',' in arg:
184+ (msg_file, msg_type) = arg.split(',')
185+ else:
186+ msg_file = arg
187+ msg_type = None
188+
189+ msg_file = os.path.expanduser(msg_file)
190+ if not os.path.isfile(msg_file):
191+ print >> sys.stderr, "Can't find file %s" % arg
192+ exit(1)
193+
194+ if not msg_type: msg_type = get_type_from_file(arg)
195+ msg = email.mime.base.MIMEBase(*msg_type.split('/'))
196+ msg.set_payload(open(msg_file, 'r').read())
197+ multipart_msg.attach(msg)
198+
199+ print multipart_msg.as_string()
200+
201+def get_type_from_file(filename):
202+ first_line = open(filename).readline()
203+ m = re.match('Content-Type: (\w+/\w+)', first_line)
204+ if m:
205+ return m.groups[1]
206+ else:
207+ for mark_string, mime_type in cloud_config_mark_strings.items():
208+ if first_line.startswith(mark_string):
209+ return mime_type
210+ return mimetypes.guess_type(filename)[0] or 'text/plain'
211+
212+if __name__ == '__main__':
213+ if len(sys.argv) == 1 or '-h' in sys.argv or '--help' in sys.argv:
214+ print "Usage: %s file1,application/cloud-config file2.sh ..." % os.path.basename(sys.argv[0])
215+ print "MIME Multipart message will be written to STDOUT"
216+ exit(0)
217+ write_mime_multipart()
218+