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
=== added file 'cloudinit/CloudConfig/cc_chef.py'
--- cloudinit/CloudConfig/cc_chef.py 1970-01-01 00:00:00 +0000
+++ cloudinit/CloudConfig/cc_chef.py 2011-04-30 14:22:28 +0000
@@ -0,0 +1,80 @@
1# vi: ts=4 expandtab
2#
3# Author: Avishai Ish-Shalom <avishai@fewbytes.com>
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3, as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16import os
17import pwd
18import socket
19import subprocess
20import StringIO
21import ConfigParser
22import cloudinit.CloudConfig as cc
23import cloudinit.util as util
24
25ruby_packages = {'1.8': ('ruby', 'rubygems', 'ruby-dev', 'libopenssl-ruby'),
26 '1.9.1': ('ruby1.9.1', 'ruby1.9.1-dev', 'libruby1.9.1'),
27 '1.9': ('ruby1.9', 'ruby1.9-dev', 'libruby1.9') }
28
29def handle(name,cfg,cloud,log,args):
30 # If there isn't a chef key in the configuration don't do anything
31 if not cfg.has_key('chef'): return
32 chef_cfg = cfg['chef']
33
34 # Install chef packages from selected source
35 if not os.path.isfile('/usr/bin/chef-client'):
36 if chef_cfg['install_type'] == "gems":
37 if chef_cfg.has_key('version'):
38 chef_version = chef_cfg['version']
39 else:
40 chef_version = None
41 install_chef_from_gems(
42 util.get_cfg_option_str(chef_cfg, 'ruby_version', '1.8'),
43 chef_version)
44 else:
45 cc.install_packages(('chef',))
46
47 # set the validation cert
48 if chef_cfg.has_key('validation_cert'):
49 with open('/etc/chef/validation.cert', 'w') as validation_cert_fh:
50 validation_cert_fh.write(chef_cfg['validation_cert'])
51
52 # create the chef config from template
53 util.render_to_file('chef_client.rb', '/etc/chef/client.rb',
54 {'server_url': chef_cfg['server_url'], 'validation_name': chef_cfg['validation_name'] || 'chef-validator'})
55
56 chef_args = ['-d']
57 # set the firstboot json
58 if chef_cfg.has_key('run_list'):
59 with open('/etc/chef/firstboot.json') as firstboot_json_fh:
60 firstboot_json_fh.write("{\n\"run_list\":\n[\n")
61 for runlist_item in chef_cfg['run_list']:
62 firstboot_json_fh.write(runlist_item + "\n")
63 firstboot_json_fh.write("]\n\}")
64 chef_args.append('-j /etc/chef/firstboot.json')
65
66 # and finally, run chef
67 subprocess.check_call(['/usr/bin/chef-client'] + chef_args)
68
69def install_chef_from_gems(ruby_version, chef_version = None):
70 cc.install_packages(ruby_packages[ruby_version])
71 chef_version_arg = ""
72 if chef_version: chef_version_arg = "-v %s" % chef_version
73 subprocess.check_call([gem_bin,'install','chef',chef_version_arg, '--no-ri','--no-rdoc','--no-test','-q'])
74 os.mkdirs('/etc/chef', '/var/log/chef', '/var/lib/chef', '/var/cache/chef', '/var/backups/chef', '/var/run/chef')
75 os.symlink('/var/lib/gem/%s/bin/chef-client' % ruby_version, '/usr/bin/chef-client')
76 # Ohai ruby plugin breaks if there is no ruby or gem binaries at /usr/bin, so
77 try: os.symlink('/usr/bin/gem%s' % ruby_version, '/usr/bin/gem')
78 except: pass
79 try: os.symlink('/usr/bin/ruby%s' % ruby_version, '/usr/bin/ruby')
80 except: pass
081
=== modified file 'cloudinit/CloudConfig/cc_set_hostname.py'
--- cloudinit/CloudConfig/cc_set_hostname.py 2011-01-26 14:03:46 +0000
+++ cloudinit/CloudConfig/cc_set_hostname.py 2011-04-30 14:22:28 +0000
@@ -24,7 +24,12 @@
24 return(True)24 return(True)
2525
26 try:26 try:
27 hostname = util.get_cfg_option_str(cfg,"hostname",cloud.get_hostname())27 hostname_prefix = util.get_cfg_option_str(cfg, "hostname_prefix", None)
28 hostname_attr = util.get_cfg_option_str(cfg, "hostname_attribute", "hostname")
29 hostname_function = getattr(cloud, 'get_' + hostname_attr, None)
30 if hostname_fucntion is None: hostname_fucntion = cloud.get_hostname
31 hostname = util.get_cfg_option_str(cfg,"hostname", hostname_function)
32 if hostname_prefix: hostname = hostname_prefix + "-" + hostname
28 set_hostname(hostname, log)33 set_hostname(hostname, log)
29 except Exception as e:34 except Exception as e:
30 util.logexc(log)35 util.logexc(log)
3136
=== added file 'doc/examples/cloud-config-chef.txt'
--- doc/examples/cloud-config-chef.txt 1970-01-01 00:00:00 +0000
+++ doc/examples/cloud-config-chef.txt 2011-04-30 14:22:28 +0000
@@ -0,0 +1,38 @@
1#cloud-config
2#
3# This is an example file to automatically setup and run puppetd
4# when the instance boots for the first time.
5# Make sure that this file is valid yaml before starting instances.
6# It should be passed as user-data when starting the instance.
7
8# The default is to install from packages. If you want the latest packages from Opscode, be sure to add their repo:
9apt_mirror: http://apt.opscode.com/
10
11chef:
12 # If you want to install from rubygems:
13 install_type: "gems"
14
15 # Chef settings
16 server_url: "https://chef.yourorg.com:4000"
17
18 # Default validation name is chef-validator
19 validation_name: "yourorg-validator"
20 validation_cert: |
21 -----BEGIN CERTIFICATE-----
22 MIICCTCCAXKgAwIBAgIBATANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJjYTAe
23 Fw0xMDAyMTUxNzI5MjFaFw0xNTAyMTQxNzI5MjFaMA0xCzAJBgNVBAMMAmNhMIGf
24 MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCu7Q40sm47/E1Pf+r8AYb/V/FWGPgc
25 b014OmNoX7dgCxTDvps/h8Vw555PdAFsW5+QhsGr31IJNI3kSYprFQcYf7A8tNWu
26 1MASW2CfaEiOEi9F1R3R4Qlz4ix+iNoHiUDTjazw/tZwEdxaQXQVLwgTGRwVa+aA
27 qbutJKi93MILLwIDAQABo3kwdzA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1Ynkv
28 T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDwYDVR0TAQH/BAUwAwEB/zAd
29 BgNVHQ4EFgQUu4+jHB+GYE5Vxo+ol1OAhevspjAwCwYDVR0PBAQDAgEGMA0GCSqG
30 SIb3DQEBBQUAA4GBAH/rxlUIjwNb3n7TXJcDJ6MMHUlwjr03BDJXKb34Ulndkpaf
31 +GAlzPXWa7bO908M9I8RnPfvtKnteLbvgTK+h+zX1XCty+S2EQWk29i2AdoqOTxb
32 hppiGMp0tT5Havu4aceCXiy2crVcudj3NFciy8X66SoECemW9UYDCb9T5D0d
33 -----END CERTIFICATE-----
34
35 # A run list for a first boot json
36 run_list:
37 - "recipe[apache2]"
38 - "role[db]"
039
=== added file 'templates/chef_client.rb.tmpl'
--- templates/chef_client.rb.tmpl 1970-01-01 00:00:00 +0000
+++ templates/chef_client.rb.tmpl 2011-04-30 14:22:28 +0000
@@ -0,0 +1,12 @@
1log_level :info
2log_location "/var/log/chef/client.log"
3ssl_verify_mode :verify_none
4validation_client_name "$validation_name"
5validation_key "/etc/chef/validation.pem"
6client_key "/etc/chef/client.pem"
7chef_server_url "$server_url"
8file_cache_path "/var/cache/chef"
9file_backup_path "/var/backups/chef"
10pid_file "/var/run/chef/client.pid"
11Chef::Log::Formatter.show_time = true
12
013
=== added file 'tools/write-mime-multipart.py'
--- tools/write-mime-multipart.py 1970-01-01 00:00:00 +0000
+++ tools/write-mime-multipart.py 2011-04-30 14:22:28 +0000
@@ -0,0 +1,51 @@
1#! /usr/bin/env python
2
3import sys, os
4import email
5import mimetypes
6import re
7
8mimetypes.types_map['.sh'] = 'text/x-shellscript'
9cloud_config_mark_strings = { '#!': 'text/x-shellscript', '#include': 'text/x-include-url',
10 '#cloud-config': 'text/cloud-config', '#upstart-job': 'text/upstart-job',
11 '#cloud-boothook': 'text/cloud-boothook'
12 }
13def write_mime_multipart():
14 multipart_msg = email.mime.Multipart.MIMEMultipart()
15 for arg in sys.argv[1:]:
16 if ',' in arg:
17 (msg_file, msg_type) = arg.split(',')
18 else:
19 msg_file = arg
20 msg_type = None
21
22 msg_file = os.path.expanduser(msg_file)
23 if not os.path.isfile(msg_file):
24 print >> sys.stderr, "Can't find file %s" % arg
25 exit(1)
26
27 if not msg_type: msg_type = get_type_from_file(arg)
28 msg = email.mime.base.MIMEBase(*msg_type.split('/'))
29 msg.set_payload(open(msg_file, 'r').read())
30 multipart_msg.attach(msg)
31
32 print multipart_msg.as_string()
33
34def get_type_from_file(filename):
35 first_line = open(filename).readline()
36 m = re.match('Content-Type: (\w+/\w+)', first_line)
37 if m:
38 return m.groups[1]
39 else:
40 for mark_string, mime_type in cloud_config_mark_strings.items():
41 if first_line.startswith(mark_string):
42 return mime_type
43 return mimetypes.guess_type(filename)[0] or 'text/plain'
44
45if __name__ == '__main__':
46 if len(sys.argv) == 1 or '-h' in sys.argv or '--help' in sys.argv:
47 print "Usage: %s file1,application/cloud-config file2.sh ..." % os.path.basename(sys.argv[0])
48 print "MIME Multipart message will be written to STDOUT"
49 exit(0)
50 write_mime_multipart()
51