cluster_chef-knife 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +51 -0
  2. data/.rspec +3 -0
  3. data/CHANGELOG.md +63 -0
  4. data/Gemfile +18 -0
  5. data/LICENSE +201 -0
  6. data/README.md +332 -0
  7. data/Rakefile +92 -0
  8. data/TODO.md +8 -0
  9. data/VERSION +1 -0
  10. data/chefignore +41 -0
  11. data/cluster_chef-knife.gemspec +111 -0
  12. data/clusters/website_demo.rb +65 -0
  13. data/config/client.rb +59 -0
  14. data/lib/chef/knife/bootstrap/ubuntu10.04-basic.erb +78 -0
  15. data/lib/chef/knife/bootstrap/ubuntu10.04-cluster_chef.erb +139 -0
  16. data/lib/chef/knife/bootstrap/ubuntu11.10-cluster_chef.erb +128 -0
  17. data/lib/chef/knife/cluster_bootstrap.rb +69 -0
  18. data/lib/chef/knife/cluster_kick.rb +86 -0
  19. data/lib/chef/knife/cluster_kill.rb +73 -0
  20. data/lib/chef/knife/cluster_launch.rb +168 -0
  21. data/lib/chef/knife/cluster_list.rb +50 -0
  22. data/lib/chef/knife/cluster_proxy.rb +118 -0
  23. data/lib/chef/knife/cluster_show.rb +56 -0
  24. data/lib/chef/knife/cluster_ssh.rb +94 -0
  25. data/lib/chef/knife/cluster_start.rb +32 -0
  26. data/lib/chef/knife/cluster_stop.rb +37 -0
  27. data/lib/chef/knife/cluster_sync.rb +76 -0
  28. data/lib/chef/knife/generic_command.rb +66 -0
  29. data/lib/chef/knife/knife_common.rb +199 -0
  30. data/notes/aws_console_screenshot.jpg +0 -0
  31. data/rspec.watchr +29 -0
  32. data/spec/cluster_chef/cluster_spec.rb +13 -0
  33. data/spec/cluster_chef/facet_spec.rb +70 -0
  34. data/spec/cluster_chef/server_slice_spec.rb +19 -0
  35. data/spec/cluster_chef/server_spec.rb +112 -0
  36. data/spec/cluster_chef_spec.rb +193 -0
  37. data/spec/spec_helper/dummy_chef.rb +25 -0
  38. data/spec/spec_helper.rb +50 -0
  39. data/spec/test_config.rb +20 -0
  40. data/tasks/chef_config.rb +38 -0
  41. data/tasks/jeweler_use_alt_branch.rb +47 -0
  42. metadata +223 -0
data/Rakefile ADDED
@@ -0,0 +1,92 @@
1
+ #
2
+ # Rakefile for Cluster Chef Knife plugins
3
+ #
4
+ # Author:: Adam Jacob (<adam@opscode.com>)
5
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+
21
+ require 'rubygems' unless defined?(Gem)
22
+ require 'bundler'
23
+ begin
24
+ Bundler.setup(:default, :development)
25
+ rescue Bundler::BundlerError => e
26
+ $stderr.puts e.message
27
+ $stderr.puts "Run `bundle install` to install missing gems"
28
+ exit e.status_code
29
+ end
30
+ require 'json'
31
+ require 'jeweler'
32
+ require 'rspec/core/rake_task'
33
+ require 'yard'
34
+
35
+ # Load constants from rake config file.
36
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '*.rb')].sort.each{|f| p f ; require f }
37
+
38
+ $jeweler_push_from_branch = 'version_3'
39
+
40
+ # ---------------------------------------------------------------------------
41
+ #
42
+ # Jeweler -- release cluster_chef as a gem
43
+ #
44
+ Jeweler::Tasks.new do |gem|
45
+ gem.name = ENV['CLUSTER_CHEF_NAME'] || "cluster_chef-knife"
46
+ gem.homepage = "http://infochimps.com/labs"
47
+ gem.license = NEW_COOKBOOK_LICENSE.to_s
48
+ gem.summary = %Q{cluster_chef allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks.}
49
+ gem.description = %Q{cluster_chef allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks.}
50
+ gem.email = SSL_EMAIL_ADDRESS
51
+ gem.authors = ["Infochimps"]
52
+
53
+ ignores = File.readlines(".gitignore").grep(/^[^#]\S+/).map{|s| s.chomp }
54
+ dotfiles = [".gemtest", ".gitignore", ".rspec", ".yardopts"]
55
+ gem.files = dotfiles + Dir["**/*"].
56
+ reject{|f| f =~ %r{^cookbooks/} }.
57
+ reject{|f| File.directory?(f) }.
58
+ reject{|f| ignores.any?{|i| File.fnmatch(i, f) || File.fnmatch(i+'/*', f) || File.fnmatch(i+'/**/*', f) } }
59
+ gem.test_files = gem.files.grep(/^spec\//)
60
+ gem.require_paths = ['lib']
61
+
62
+ if gem.name == 'cluster_chef'
63
+ gem.files.reject!{|f| f =~ %r{^(cluster_chef-knife.gemspec|lib/chef/knife/)} }
64
+ else
65
+ gem.files.reject!{|f| f =~ %r{^(cluster_chef.gemspec|lib/cluster_chef)} }
66
+ end
67
+ end
68
+ Jeweler::RubygemsDotOrgTasks.new
69
+
70
+ # ---------------------------------------------------------------------------
71
+ #
72
+ # RSpec -- testing
73
+ #
74
+ RSpec::Core::RakeTask.new(:spec) do |spec|
75
+ spec.pattern = FileList['spec/**/*_spec.rb']
76
+ end
77
+
78
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
79
+ spec.pattern = 'spec/**/*_spec.rb'
80
+ spec.rcov = true
81
+ spec.rcov_opts = %w[ --exclude .rvm --no-comments --text-summary]
82
+ end
83
+
84
+ # ---------------------------------------------------------------------------
85
+ #
86
+ # Yard -- documentation
87
+ #
88
+ YARD::Rake::YardocTask.new
89
+
90
+ # ---------------------------------------------------------------------------
91
+
92
+ task :default => :spec
data/TODO.md ADDED
@@ -0,0 +1,8 @@
1
+ ### From Nathan
2
+ - syntactic sugar for ```server(0).fullname('blah')```
3
+
4
+ ### Knife commands
5
+
6
+ * knife cluster kick fails if service isn't running
7
+ * make clear directions for installing `cluster_chef` and its initial use.
8
+ * knife cluster launch should fail differently if you give it a facet that doesn't exist
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 3.0.5
data/chefignore ADDED
@@ -0,0 +1,41 @@
1
+ # Put files/directories that should be ignored in this file.
2
+ # Lines that start with '# ' are comments.
3
+
4
+ ## OS
5
+ .DS_Store
6
+ Icon?
7
+ nohup.out
8
+
9
+ ## EDITORS
10
+ \#*
11
+ .#*
12
+ *~
13
+ *.sw[a-z]
14
+ *.bak
15
+ REVISION
16
+ TAGS*
17
+ tmtags
18
+ *_flymake.*
19
+ *_flymake
20
+ *.tmproj
21
+ .project
22
+ .settings
23
+ mkmf.log
24
+
25
+ ## COMPILED
26
+ a.out
27
+ *.o
28
+ *.pyc
29
+ *.so
30
+
31
+ ## OTHER SCM
32
+ */.bzr/*
33
+ */.hg/*
34
+ */.svn/*
35
+
36
+ ## Don't send rspecs up in cookbook
37
+ .watchr
38
+ .rspec
39
+ spec/*
40
+ spec/fixtures/*
41
+
@@ -0,0 +1,111 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "cluster_chef-knife"
8
+ s.version = "3.0.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Infochimps"]
12
+ s.date = "2011-12-11"
13
+ s.description = "cluster_chef allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks."
14
+ s.email = "coders@infochimps.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ ".rspec",
22
+ "CHANGELOG.md",
23
+ "Gemfile",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "TODO.md",
28
+ "VERSION",
29
+ "chefignore",
30
+ "cluster_chef-knife.gemspec",
31
+ "clusters/website_demo.rb",
32
+ "config/client.rb",
33
+ "lib/chef/knife/bootstrap/ubuntu10.04-basic.erb",
34
+ "lib/chef/knife/bootstrap/ubuntu10.04-cluster_chef.erb",
35
+ "lib/chef/knife/bootstrap/ubuntu11.10-cluster_chef.erb",
36
+ "lib/chef/knife/cluster_bootstrap.rb",
37
+ "lib/chef/knife/cluster_kick.rb",
38
+ "lib/chef/knife/cluster_kill.rb",
39
+ "lib/chef/knife/cluster_launch.rb",
40
+ "lib/chef/knife/cluster_list.rb",
41
+ "lib/chef/knife/cluster_proxy.rb",
42
+ "lib/chef/knife/cluster_show.rb",
43
+ "lib/chef/knife/cluster_ssh.rb",
44
+ "lib/chef/knife/cluster_start.rb",
45
+ "lib/chef/knife/cluster_stop.rb",
46
+ "lib/chef/knife/cluster_sync.rb",
47
+ "lib/chef/knife/generic_command.rb",
48
+ "lib/chef/knife/knife_common.rb",
49
+ "notes/aws_console_screenshot.jpg",
50
+ "rspec.watchr",
51
+ "spec/cluster_chef/cluster_spec.rb",
52
+ "spec/cluster_chef/facet_spec.rb",
53
+ "spec/cluster_chef/server_slice_spec.rb",
54
+ "spec/cluster_chef/server_spec.rb",
55
+ "spec/cluster_chef_spec.rb",
56
+ "spec/spec_helper.rb",
57
+ "spec/spec_helper/dummy_chef.rb",
58
+ "spec/test_config.rb",
59
+ "tasks/chef_config.rb",
60
+ "tasks/jeweler_use_alt_branch.rb"
61
+ ]
62
+ s.homepage = "http://infochimps.com/labs"
63
+ s.licenses = ["apachev2"]
64
+ s.require_paths = ["lib"]
65
+ s.rubygems_version = "1.8.11"
66
+ s.summary = "cluster_chef allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks."
67
+ s.test_files = ["spec/cluster_chef/cluster_spec.rb", "spec/cluster_chef/facet_spec.rb", "spec/cluster_chef/server_slice_spec.rb", "spec/cluster_chef/server_spec.rb", "spec/cluster_chef_spec.rb", "spec/spec_helper/dummy_chef.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
68
+
69
+ if s.respond_to? :specification_version then
70
+ s.specification_version = 3
71
+
72
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
73
+ s.add_runtime_dependency(%q<chef>, ["~> 0.10.4"])
74
+ s.add_runtime_dependency(%q<fog>, ["~> 1.1.1"])
75
+ s.add_runtime_dependency(%q<formatador>, ["~> 0.2.1"])
76
+ s.add_runtime_dependency(%q<gorillib>, ["~> 0.1.7"])
77
+ s.add_development_dependency(%q<bundler>, ["~> 1"])
78
+ s.add_development_dependency(%q<yard>, ["~> 0.6.7"])
79
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
80
+ s.add_development_dependency(%q<rspec>, ["~> 2.7.0"])
81
+ s.add_development_dependency(%q<configliere>, ["~> 0.4.8"])
82
+ s.add_development_dependency(%q<spork>, ["~> 0.9.0.rc5"])
83
+ s.add_development_dependency(%q<watchr>, ["~> 0.7"])
84
+ else
85
+ s.add_dependency(%q<chef>, ["~> 0.10.4"])
86
+ s.add_dependency(%q<fog>, ["~> 1.1.1"])
87
+ s.add_dependency(%q<formatador>, ["~> 0.2.1"])
88
+ s.add_dependency(%q<gorillib>, ["~> 0.1.7"])
89
+ s.add_dependency(%q<bundler>, ["~> 1"])
90
+ s.add_dependency(%q<yard>, ["~> 0.6.7"])
91
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
92
+ s.add_dependency(%q<rspec>, ["~> 2.7.0"])
93
+ s.add_dependency(%q<configliere>, ["~> 0.4.8"])
94
+ s.add_dependency(%q<spork>, ["~> 0.9.0.rc5"])
95
+ s.add_dependency(%q<watchr>, ["~> 0.7"])
96
+ end
97
+ else
98
+ s.add_dependency(%q<chef>, ["~> 0.10.4"])
99
+ s.add_dependency(%q<fog>, ["~> 1.1.1"])
100
+ s.add_dependency(%q<formatador>, ["~> 0.2.1"])
101
+ s.add_dependency(%q<gorillib>, ["~> 0.1.7"])
102
+ s.add_dependency(%q<bundler>, ["~> 1"])
103
+ s.add_dependency(%q<yard>, ["~> 0.6.7"])
104
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
105
+ s.add_dependency(%q<rspec>, ["~> 2.7.0"])
106
+ s.add_dependency(%q<configliere>, ["~> 0.4.8"])
107
+ s.add_dependency(%q<spork>, ["~> 0.9.0.rc5"])
108
+ s.add_dependency(%q<watchr>, ["~> 0.7"])
109
+ end
110
+ end
111
+
@@ -0,0 +1,65 @@
1
+ ClusterChef.cluster 'webserver_demo' do
2
+ cloud :ec2 do
3
+ defaults
4
+ availability_zones ['us-east-1d']
5
+ flavor 't1.micro' # change to something larger for serious use
6
+ backing 'ebs'
7
+ image_name 'natty'
8
+ bootstrap_distro 'ubuntu10.04-cluster_chef'
9
+ chef_client_script 'client.rb'
10
+ mount_ephemerals(:tags => { :scratch_dirs => true })
11
+ end
12
+
13
+ role "nfs_client"
14
+ recipe "package_set"
15
+
16
+ facet :webnode do
17
+ instances 6
18
+ role "nginx"
19
+ role "redis_client"
20
+ role "mysql_client"
21
+ role "elasticsearch_client"
22
+ role "awesome_website"
23
+ role "web_server" # this triggers opening appropriate ports
24
+ # Rotate nodes among availability zones
25
+ azs = ['us-east-1d', 'us-east-1b', 'us-east-1c']
26
+ (0...instances).each do |idx|
27
+ server(idx).cloud.availability_zones [azs[ idx % azs.length ]]
28
+ end
29
+ # Rote nodes among A/B testing groups
30
+ (0..instances).each do |idx|
31
+ server(idx).chef_node.normal[:split_testing] = ( (idx % 2 == 0) ? 'A' : 'B' )
32
+ end
33
+ end
34
+
35
+ facet :dbnode do
36
+ instances 2
37
+ role "mysql_server"
38
+ role "redis_client"
39
+ # burly master, wussier slaves
40
+ cloud.flavor "m1.large"
41
+ server(0) do
42
+ cloud.flavor "c1.xlarge"
43
+ end
44
+
45
+ volume(:data) do
46
+ size 50
47
+ keep true
48
+ device '/dev/sdi'
49
+ mount_point '/data/db'
50
+ mount_options 'defaults,nouuid,noatime'
51
+ fstype 'xfs'
52
+ snapshot_id 'snap-d9c1edb1'
53
+ end
54
+ end
55
+
56
+ facet :esnode do
57
+ instances 1
58
+ role "nginx"
59
+ role "redis_server"
60
+ role "elasticsearch_data_esnode"
61
+ role "elasticsearch_http_esnode"
62
+ #
63
+ cloud.flavor "m1.large"
64
+ end
65
+ end
data/config/client.rb ADDED
@@ -0,0 +1,59 @@
1
+ require "ohai"
2
+ require "json"
3
+
4
+ #
5
+ # Load configuration
6
+ #
7
+
8
+ def merge_safely hsh
9
+ hsh.merge!( yield ) rescue Mash.new
10
+ end
11
+
12
+ def create_file_if_empty(filename, str)
13
+ unless File.exists?(filename)
14
+ puts "Populating #{filename}" ;
15
+ File.open(filename, "w", 0600){|f| f.puts(str) }
16
+ end
17
+ end
18
+
19
+ def present?(config, key)
20
+ not config[key].to_s.empty?
21
+ end
22
+
23
+ # Start with a set of defaults
24
+ chef_config = Mash.new
25
+
26
+ # Extract client configuration from EC2 user-data
27
+ OHAI_INFO = Ohai::System.new
28
+ OHAI_INFO.all_plugins
29
+ merge_safely(chef_config){ JSON.parse(OHAI_INFO[:ec2][:userdata]) }
30
+
31
+ #
32
+ # Configure chef run
33
+ #
34
+
35
+ log_level :info
36
+ log_location STDOUT
37
+ node_name chef_config["node_name"] if chef_config["node_name"]
38
+ chef_server_url chef_config["chef_server"] if chef_config["chef_server"]
39
+ validation_client_name chef_config["validation_client_name"] if chef_config["validation_client_name"]
40
+ validation_key "/etc/chef/validation.pem"
41
+ client_key "/etc/chef/client.pem"
42
+ node_attrs_file "/etc/chef/first-boot.json"
43
+
44
+ # If the client file is missing, write the validation key out so chef-client can register
45
+ unless File.exists?(client_key)
46
+ if present?(chef_config, "client_key") then create_file_if_empty(client_key, chef_config["client_key"])
47
+ elsif present?(chef_config, "validation_key") then create_file_if_empty(validation_key, chef_config["validation_key"])
48
+ else warn "Yikes -- I have no client key or validation key!!"
49
+ end
50
+ end
51
+
52
+ reduced_chef_config = chef_config.reject{|k,v| k.to_s =~ /(_key|run_list)$/ }
53
+ unless File.exists?(node_attrs_file)
54
+ create_file_if_empty(node_attrs_file, JSON.pretty_generate(reduced_chef_config))
55
+ end
56
+ json_attribs node_attrs_file
57
+
58
+ Chef::Log.debug(JSON.generate(chef_config))
59
+ Chef::Log.info("=> chef client #{node_name} on #{chef_server_url} in cluster +#{chef_config["cluster_name"]}+")
@@ -0,0 +1,78 @@
1
+ bash -c '
2
+
3
+ # This is the ubuntu-10.04-gems script from opscode, but it installs the chef-client service and kicks off the first run of chef
4
+
5
+ set -v
6
+
7
+ <%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>
8
+ eval `cat /etc/lsb-release `
9
+ export DEBIAN_FRONTEND=noninteractive
10
+
11
+ if [ ! -f /usr/bin/chef-client ]; then
12
+ apt-get update
13
+ apt-get install -y ruby ruby1.8-dev build-essential wget libruby-extras libruby1.8-extras
14
+ cd /tmp
15
+ wget <%= "--proxy=on " if knife_config[:bootstrap_proxy] %>http://production.cf.rubygems.org/rubygems/rubygems-1.6.2.tgz
16
+ tar zxf rubygems-1.6.2.tgz
17
+ cd rubygems-1.6.2
18
+ ruby setup.rb --no-format-executable
19
+ fi
20
+
21
+ gem update --no-rdoc --no-ri
22
+ gem install ohai --no-rdoc --no-ri --verbose
23
+ gem install chef --no-rdoc --no-ri --verbose <%= bootstrap_version_string %>
24
+
25
+ echo -e "`date` \n\n**** \n**** Knifing in the chef client config files:\n****\n"
26
+ mkdir -p /etc/chef
27
+
28
+ (
29
+ cat <<'EOP'
30
+ <%= validation_key %>
31
+ EOP
32
+ ) > /tmp/validation.pem
33
+ awk NF /tmp/validation.pem > /etc/chef/validation.pem
34
+ rm /tmp/validation.pem
35
+
36
+ echo -e "`date` \n\n**** \n**** Creating chef client script:\n****\n"
37
+
38
+ (
39
+ cat <<'EOP'
40
+ <%= config_content %>
41
+ EOP
42
+ ) > /etc/chef/client.rb
43
+
44
+ (
45
+ cat <<'EOP'
46
+ <%= { "run_list" => @run_list, "cluster_name" => @config[:node].cluster_name, "facet_name" => @config[:node].facet_name, "facet_index" => @config[:node].facet_index }.to_json %>
47
+ EOP
48
+ ) > /etc/chef/first-boot.json
49
+
50
+ echo -e "`date` \n\n**** \n**** Adding chef client runit scripts:\n****\n"
51
+ service chef-client stop 2>/dev/null ; sleep 1 ; killall chef-client 2>/dev/null
52
+ mkdir -p /var/log/chef /var/chef /etc/sv/chef-client/log/main /etc/sv/chef-client/supervise
53
+ cat > /etc/sv/chef-client/log/run <<EOF
54
+ #!/bin/bash
55
+ exec svlogd -tt ./main
56
+ EOF
57
+ cat > /etc/sv/chef-client/run <<EOF
58
+ #!/bin/bash
59
+ exec 2>&1
60
+ exec /usr/bin/env chef-client -i 43200 -s 20 -L /var/log/chef/client.log
61
+ EOF
62
+ chmod +x /etc/sv/chef-client/log/run /etc/sv/chef-client/run
63
+ ln -nfs /usr/bin/sv /etc/init.d/chef-client
64
+
65
+ <%- if (@config[:bootstrap_runs_chef_client].to_s == 'true') || (@chef_config.knife[:bootstrap_runs_chef_client].to_s == 'true') %>
66
+ echo -e "`date` \n\n**** \n**** First run of chef:\n****\n"
67
+ <%= start_chef %>
68
+ <%- end %>
69
+
70
+ echo -e "`date` \n\n**** \n**** Cleanup:\n****\n"
71
+ updatedb
72
+
73
+ echo -e "`date` \n\n**** \n**** Enabling chef client service:\n****\n"
74
+ ln -nfs /etc/sv/chef-client /etc/service/chef-client
75
+ service chef-client start
76
+
77
+ echo -e "`date` \n\n**** \n**** Cluster Chef client bootstrap complete\n****\n"
78
+ '
@@ -0,0 +1,139 @@
1
+ bash -c '
2
+
3
+ # This is the ubuntu-10.04-gems script from opscode, but it
4
+ # * installs ruby 1.9.2, not 1.8.7
5
+ # * upgrades rubygems rather than installing from source
6
+ # * pushes the node identity into the first-boot.json
7
+ # * installs the chef-client service and kicks off the first run of chef
8
+
9
+ <%= (@config[:verbosity].to_i > 1 ? 'set -v' : '') %>
10
+
11
+ mkdir -p /tmp/knife-bootstrap ; chmod 700 /tmp/knife-bootstrap
12
+ cd /tmp/knife-bootstrap
13
+
14
+ RUBY_VERSION=1.9.2-p290
15
+
16
+ <%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>
17
+ eval `cat /etc/lsb-release `
18
+ export DEBIAN_FRONTEND=noninteractive
19
+
20
+ if [ ! -f /usr/bin/chef-client ]; then
21
+ echo -e "`date` \n\n**** \n**** apt update:\n****\n"
22
+ apt-get update
23
+ apt-get -y upgrade
24
+
25
+ echo -e "`date` \n\n**** \n**** Installing base packages:\n****\n"
26
+ apt-get install -y build-essential wget runit runit-services zlib1g-dev libssl-dev openssl libcurl4-openssl-dev libreadline6-dev libyaml-dev
27
+
28
+ echo -e "`date` \n\n**** \n**** Installing ruby version ${RUBY_VERSION}:\n****\n"
29
+
30
+ wget ftp://ftp.ruby-lang.org//pub/ruby/1.9/ruby-${RUBY_VERSION}.tar.gz
31
+ tar xzf ruby-${RUBY_VERSION}.tar.gz
32
+ cd ruby-${RUBY_VERSION}
33
+ ./configure --with-ruby-version=${RUBY_VERSION} --prefix=/usr --program-suffix=${RUBY_VERSION}
34
+ make -j2
35
+ make install
36
+
37
+ sudo update-alternatives --remove-all gem && true
38
+ update-alternatives \
39
+ --install /usr/bin/ruby ruby /usr/bin/ruby${RUBY_VERSION} 400 \
40
+ --slave /usr/bin/ri ri /usr/bin/ri${RUBY_VERSION} \
41
+ --slave /usr/bin/irb irb /usr/bin/irb${RUBY_VERSION} \
42
+ --slave /usr/bin/erb erb /usr/bin/erb${RUBY_VERSION} \
43
+ --slave /usr/bin/gem gem /usr/bin/gem${RUBY_VERSION} \
44
+ --slave /usr/share/man/man1/ruby.1.gz ruby.1.gz \
45
+ /usr/share/man/man1/ruby${RUBY_VERSION}.1
46
+
47
+ if ruby -e "exit(%x{gem --version} < \"1.6.2\" ? 0 : -1 )" ; then
48
+ echo -e "`date` \n\n**** \n**** Updating rubygems:\n****\n"
49
+ gem install --no-rdoc --no-ri rubygems-update --version=1.6.2
50
+ update_rubygems --version=1.6.2
51
+ fi
52
+
53
+ echo -e "`date` \n\n**** \n**** Installing chef:\n****\n"
54
+ gem install ohai --no-rdoc --no-ri
55
+ gem install chef --no-rdoc --no-ri <%= bootstrap_version_string %>
56
+ gem install --no-rdoc --no-ri extlib json ruby-shadow right_aws
57
+
58
+ else # no chef-client
59
+ echo -e "`date` \n\n**** \n**** Chef is present -- skipping apt/ruby/chef installation\n****\n"
60
+ fi
61
+
62
+ # fix a bug in chef that prevents debugging template errors
63
+ bad_template_file='/usr/lib/ruby/gems/1.9.2-p290/gems/chef-0.10.4/lib/chef/mixin/template.rb'
64
+ if echo "0505c482b8b0b333ac71bbc8a1795d19 $bad_template_file" | md5sum -c - 2>/dev/null ; then
65
+ curl https://github.com/mrflip/chef/commit/655a1967253a8759afb54f30b818bbcb7c309198.patch | sudo patch $bad_template_file
66
+ fi
67
+
68
+ echo -e "`date` \n\n**** \n**** Knifing in the chef client config files:\n****\n"
69
+ mkdir -p /etc/chef
70
+
71
+ <%- if @config[:client_key] %>
72
+ (
73
+ cat <<'EOP'
74
+ <%= @config[:client_key] %>
75
+ EOP
76
+ ) > /tmp/knife-bootstrap/client.pem
77
+ awk NF /tmp/knife-bootstrap/client.pem > /etc/chef/client.pem
78
+ <%- else %>
79
+ (
80
+ cat <<'EOP'
81
+ <%= validation_key %>
82
+ EOP
83
+ ) > /tmp/knife-bootstrap/validation.pem
84
+ awk NF /tmp/knife-bootstrap/validation.pem > /etc/chef/validation.pem
85
+ <%- end %>
86
+
87
+ echo -e "`date` \n\n**** \n**** Nuking our temp files:\n****\n"
88
+
89
+ cd /tmp
90
+ # rm -rf /tmp/knife-bootstrap
91
+
92
+ echo -e "`date` \n\n**** \n**** Creating chef client script:\n****\n"
93
+
94
+ (
95
+ cat <<'EOP'
96
+ <%= config_content %>
97
+ <%= @config[:node].chef_client_script_content %>
98
+ EOP
99
+ ) > /etc/chef/client.rb
100
+
101
+ (
102
+ cat <<'EOP'
103
+ <%= { "run_list" => @run_list, "cluster_name" => @config[:node].cluster_name, "facet_name" => @config[:node].facet_name, "facet_index" => @config[:node].facet_index }.to_json %>
104
+ EOP
105
+ ) > /etc/chef/first-boot.json
106
+
107
+ echo -e "`date` \n\n**** \n**** Adding chef client runit scripts:\n****\n"
108
+ service chef-client stop >/dev/null 2>&1 ; sleep 1 ; killall chef-client 2>/dev/null ; true
109
+ mkdir -p /var/log/chef /var/chef /etc/service /etc/sv/chef-client/{log/main,supervise}
110
+ cat > /etc/sv/chef-client/log/run <<EOF
111
+ #!/bin/bash
112
+ exec svlogd -tt ./main
113
+ EOF
114
+ cat > /etc/sv/chef-client/run <<EOF
115
+ #!/bin/bash
116
+ exec 2>&1
117
+ exec /usr/bin/env chef-client -i 43200 -s 20 -L /var/log/chef/client.log
118
+ EOF
119
+ chmod +x /etc/sv/chef-client/log/run /etc/sv/chef-client/run
120
+ ln -nfs /usr/bin/sv /etc/init.d/chef-client
121
+
122
+ service chef-client stop ; true
123
+
124
+ <%- if (@config[:bootstrap_runs_chef_client].to_s == 'true') || (@chef_config.knife[:bootstrap_runs_chef_client].to_s == 'true') %>
125
+ echo -e "`date` \n\n**** \n**** First run of chef:\n****\n"
126
+ set -e
127
+ <%= start_chef %>
128
+ set +e
129
+ <%- end %>
130
+
131
+ echo -e "`date` \n\n**** \n**** Cleanup:\n****\n"
132
+ updatedb
133
+
134
+ echo -e "`date` \n\n**** \n**** Enabling chef client service:\n****\n"
135
+ ln -nfs /etc/sv/chef-client /etc/service/chef-client
136
+ service chef-client start
137
+
138
+ echo -e "`date` \n\n**** \n**** Cluster Chef client bootstrap complete\n****\n"
139
+ '