chef-metal 0.14.2 → 0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/README.md +2 -257
  4. data/Rakefile +0 -4
  5. data/lib/chef_metal.rb +1 -87
  6. data/lib/chef_metal/action_handler.rb +1 -66
  7. data/lib/chef_metal/add_prefix_action_handler.rb +1 -29
  8. data/lib/chef_metal/chef_image_spec.rb +1 -106
  9. data/lib/chef_metal/chef_machine_spec.rb +1 -82
  10. data/lib/chef_metal/chef_provider_action_handler.rb +1 -72
  11. data/lib/chef_metal/chef_run_data.rb +1 -125
  12. data/lib/chef_metal/convergence_strategy.rb +1 -26
  13. data/lib/chef_metal/convergence_strategy/install_cached.rb +1 -157
  14. data/lib/chef_metal/convergence_strategy/install_msi.rb +1 -56
  15. data/lib/chef_metal/convergence_strategy/install_sh.rb +1 -53
  16. data/lib/chef_metal/convergence_strategy/no_converge.rb +1 -37
  17. data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +1 -181
  18. data/lib/chef_metal/driver.rb +1 -288
  19. data/lib/chef_metal/image_spec.rb +1 -70
  20. data/lib/chef_metal/machine.rb +1 -110
  21. data/lib/chef_metal/machine/basic_machine.rb +1 -82
  22. data/lib/chef_metal/machine/unix_machine.rb +1 -276
  23. data/lib/chef_metal/machine/windows_machine.rb +1 -102
  24. data/lib/chef_metal/machine_spec.rb +1 -78
  25. data/lib/chef_metal/recipe_dsl.rb +1 -94
  26. data/lib/chef_metal/transport.rb +1 -87
  27. data/lib/chef_metal/transport/ssh.rb +1 -288
  28. data/lib/chef_metal/transport/winrm.rb +1 -134
  29. data/lib/chef_metal/version.rb +1 -3
  30. metadata +19 -145
  31. data/bin/metal +0 -275
  32. data/lib/chef/provider/machine.rb +0 -171
  33. data/lib/chef/provider/machine_batch.rb +0 -186
  34. data/lib/chef/provider/machine_execute.rb +0 -30
  35. data/lib/chef/provider/machine_file.rb +0 -49
  36. data/lib/chef/provider/machine_image.rb +0 -54
  37. data/lib/chef/resource/machine.rb +0 -116
  38. data/lib/chef/resource/machine_batch.rb +0 -72
  39. data/lib/chef/resource/machine_execute.rb +0 -22
  40. data/lib/chef/resource/machine_file.rb +0 -28
  41. data/lib/chef/resource/machine_image.rb +0 -29
@@ -1,157 +1 @@
1
- require 'chef_metal/convergence_strategy/precreate_chef_objects'
2
- require 'pathname'
3
- require 'fileutils'
4
- require 'digest/md5'
5
- require 'thread'
6
-
7
- module ChefMetal
8
- class ConvergenceStrategy
9
- class InstallCached < PrecreateChefObjects
10
- # convergence_options is a hash of setup convergence_options, including:
11
- # - :chef_server
12
- # - :allow_overwrite_keys
13
- # - :source_key, :source_key_path, :source_key_pass_phrase
14
- # - :private_key_options
15
- # - :ohai_hints
16
- # - :public_key_path, :public_key_format
17
- # - :admin, :validator
18
- # - :chef_client_timeout
19
- # - :client_rb_path, :client_pem_path
20
- # - :chef_version, :prerelease, :package_cache_path
21
- def initialize(convergence_options, config)
22
- convergence_options = Cheffish::MergedConfig.new(convergence_options, {
23
- :client_rb_path => '/etc/chef/client.rb',
24
- :client_pem_path => '/etc/chef/client.pem'
25
- })
26
- super(convergence_options, config)
27
- @chef_version ||= convergence_options[:chef_version]
28
- @prerelease ||= convergence_options[:prerelease]
29
- @package_cache_path ||= convergence_options[:package_cache_path] || "#{ENV['HOME']}/.chef/package_cache"
30
- @package_cache = {}
31
- @tmp_dir = '/tmp'
32
- @chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
33
- FileUtils.mkdir_p(@package_cache_path)
34
- @package_cache_lock = Mutex.new
35
- end
36
-
37
- attr_reader :client_rb_path
38
- attr_reader :client_pem_path
39
-
40
- def setup_convergence(action_handler, machine)
41
- super
42
-
43
- # Install chef-client. TODO check and update version if not latest / not desired
44
- if machine.execute_always('chef-client -v').exitstatus != 0
45
- platform, platform_version, machine_architecture = machine.detect_os(action_handler)
46
- package_file = download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
47
- remote_package_file = "#{@tmp_dir}/#{File.basename(package_file)}"
48
- machine.upload_file(action_handler, package_file, remote_package_file)
49
- install_package(action_handler, machine, remote_package_file)
50
- end
51
- end
52
-
53
- def converge(action_handler, machine)
54
- super
55
-
56
- action_handler.open_stream(machine.node['name']) do |stdout|
57
- action_handler.open_stream(machine.node['name']) do |stderr|
58
- command_line = "chef-client"
59
- command_line << " -l #{config[:log_level].to_s}" if config[:log_level]
60
- machine.execute(action_handler, command_line,
61
- :stream_stdout => stdout,
62
- :stream_stderr => stderr,
63
- :timeout => @chef_client_timeout)
64
- end
65
- end
66
- end
67
-
68
- private
69
-
70
- def download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
71
- @package_cache_lock.synchronize do
72
- @package_cache ||= {}
73
- @package_cache[platform] ||= {}
74
- @package_cache[platform][platform_version] ||= {}
75
- @package_cache[platform][platform_version][machine_architecture] ||= { :lock => Mutex.new }
76
- end
77
- @package_cache[platform][platform_version][machine_architecture][:lock].synchronize do
78
- if !@package_cache[platform][platform_version][machine_architecture][:file]
79
- #
80
- # Grab metadata
81
- #
82
- metadata = download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
83
-
84
- # Download actual package desired by metadata
85
- package_file = "#{@package_cache_path}/#{URI(metadata['url']).path.split('/')[-1]}"
86
-
87
- ChefMetal.inline_resource(action_handler) do
88
- remote_file package_file do
89
- source metadata['url']
90
- checksum metadata['sha256']
91
- end
92
- end
93
-
94
- @package_cache[platform][platform_version][machine_architecture][:file] = package_file
95
- end
96
- end
97
- @package_cache[platform][platform_version][machine_architecture][:file]
98
- end
99
-
100
- def download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
101
- #
102
- # Figure out the URL to the metadata
103
- #
104
- metadata_url="https://www.opscode.com/chef/metadata"
105
- metadata_url << "?v=#{@chef_version}"
106
- metadata_url << "&prerelease=#{@prerelease ? 'true' : 'false'}"
107
- metadata_url << "&p=#{platform.strip}"
108
- metadata_url << "&pv=#{platform_version.strip}"
109
- metadata_url << "&m=#{machine_architecture.strip}"
110
- use_ssl = true
111
-
112
- # solaris 9 lacks openssl, solaris 10 lacks recent enough credentials - your base O/S is completely insecure, please upgrade
113
- if platform == 'solaris2' && (platform_version == '5.9' || platform_version == '5.10')
114
- metadata_url.sub(/^https/, 'http')
115
- use_ssl = false
116
- end
117
-
118
- # Download and parse the metadata
119
- Chef::Log.debug("Getting metadata for machine #{machine.node['name']}: #{metadata_url}")
120
- uri = URI(metadata_url)
121
- http = Net::HTTP.new(uri.host, uri.port)
122
- http.use_ssl = use_ssl
123
- request = Net::HTTP::Get.new(uri.request_uri)
124
- response = http.request(request)
125
- metadata_str = response.body
126
- metadata = {}
127
- metadata_str.each_line do |line|
128
- key, value = line.split("\t", 2)
129
- metadata[key] = value
130
- end
131
- metadata
132
- end
133
-
134
- def install_package(action_handler, machine, remote_package_file)
135
- extension = File.extname(remote_package_file)
136
- result = case extension
137
- when '.rpm'
138
- machine.execute(action_handler, "rpm -Uvh --oldpackage --replacepkgs \"#{remote_package_file}\"")
139
- when '.deb'
140
- machine.execute(action_handler, "dpkg -i \"#{remote_package_file}\"")
141
- when '.solaris'
142
- machine.write_file(action_handler, "#{@tmp_dir}/nocheck", <<EOM)
143
- conflict=nocheck
144
- action=nocheck
145
- mail=
146
- EOM
147
- machine.execute(action_handler, "pkgrm -a \"#{@tmp_dir}/nocheck\" -n chef")
148
- machine.execute(action_handler, "pkgadd -n -d \"#{remote_package_file}\" -a \"#{@tmp_dir}/nocheck\" chef")
149
- when '.sh'
150
- machine.execute(action_handler, "sh \"#{remote_package_file}\"")
151
- else
152
- raise "Unknown package extension '#{extension}' for file #{remote_package_file}"
153
- end
154
- end
155
- end
156
- end
157
- end
1
+ require "chef/provisioning/convergence_strategy/install_cached"
@@ -1,56 +1 @@
1
- require 'chef_metal/convergence_strategy/precreate_chef_objects'
2
- require 'pathname'
3
-
4
- module ChefMetal
5
- class ConvergenceStrategy
6
- class InstallMsi < PrecreateChefObjects
7
- @@install_msi_cache = {}
8
-
9
- def initialize(convergence_options, config)
10
- super
11
- @install_msi_url = convergence_options[:install_msi_url] || 'http://www.opscode.com/chef/install.msi'
12
- @install_msi_path = convergence_options[:install_msi_path] || "$env:TEMP\\#{File.basename(@install_msi_url)}"
13
- @chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
14
- end
15
-
16
- attr_reader :install_msi_url
17
- attr_reader :install_msi_path
18
-
19
- def setup_convergence(action_handler, machine)
20
- if !convergence_options.has_key?(:client_rb_path) || !convergence_options.has_key?(:client_pem_path)
21
- system_drive = machine.execute_always('$env:SystemDrive').stdout.strip
22
- @convergence_options = Cheffish::MergedConfig.new(convergence_options, {
23
- :client_rb_path => "#{system_drive}\\chef\\client.rb",
24
- :client_pem_path => "#{system_drive}\\chef\\client.pem"
25
- })
26
- end
27
-
28
- super
29
-
30
- # Install chef-client. TODO check and update version if not latest / not desired
31
- if machine.execute_always('chef-client -v').exitstatus != 0
32
- # TODO ssh verification of install.msi before running arbtrary code would be nice?
33
- # TODO find a way to cache this on the host like with the Unix stuff.
34
- # Limiter is we don't know how to efficiently upload large files to
35
- # the remote machine with WMI.
36
- machine.execute(action_handler, "(New-Object System.Net.WebClient).DownloadFile(#{machine.escape(install_msi_url)}, #{machine.escape(install_msi_path)})")
37
- machine.execute(action_handler, "msiexec /qn /i #{machine.escape(install_msi_path)}")
38
- end
39
- end
40
-
41
- def converge(action_handler, machine)
42
- super
43
-
44
- # TODO For some reason I get a 500 back if I don't do -l debug
45
- action_handler.open_stream(machine.node['name']) do |stdout|
46
- action_handler.open_stream(machine.node['name']) do |stderr|
47
- machine.execute(action_handler, "chef-client -l debug",
48
- :stream_stdout => stdout,
49
- :stream_stderr => stderr,
50
- :timeout => @chef_client_timeout)
51
- end
52
- end
53
- end
54
- end
55
- end
56
- end
1
+ require "chef/provisioning/convergence_strategy/install_msi"
@@ -1,53 +1 @@
1
- require 'chef_metal/convergence_strategy/precreate_chef_objects'
2
- require 'pathname'
3
-
4
- module ChefMetal
5
- class ConvergenceStrategy
6
- class InstallSh < PrecreateChefObjects
7
- @@install_sh_cache = {}
8
-
9
- def initialize(convergence_options, config)
10
- convergence_options = Cheffish::MergedConfig.new(convergence_options, {
11
- :client_rb_path => '/etc/chef/client.rb',
12
- :client_pem_path => '/etc/chef/client.pem'
13
- })
14
- super(convergence_options, config)
15
- @install_sh_url = convergence_options[:install_sh_url] || 'http://www.opscode.com/chef/install.sh'
16
- @install_sh_path = convergence_options[:install_sh_path] || '/tmp/chef-install.sh'
17
- @bootstrap_env = convergence_options[:bootstrap_proxy] ? "http_proxy=#{convergence_options[:bootstrap_proxy]}" : ""
18
- @chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
19
- end
20
-
21
- attr_reader :install_sh_url
22
- attr_reader :install_sh_path
23
- attr_reader :bootstrap_env
24
-
25
- def setup_convergence(action_handler, machine)
26
- super
27
-
28
- # Install chef-client. TODO check and update version if not latest / not desired
29
- if machine.execute_always('chef-client -v').exitstatus != 0
30
- # TODO ssh verification of install.sh before running arbtrary code would be nice?
31
- @@install_sh_cache[install_sh_url] ||= Net::HTTP.get(URI(install_sh_url))
32
- machine.write_file(action_handler, install_sh_path, @@install_sh_cache[install_sh_url], :ensure_dir => true)
33
- machine.execute(action_handler, "bash -c '#{bootstrap_env} bash #{install_sh_path}'")
34
- end
35
- end
36
-
37
- def converge(action_handler, machine)
38
- super
39
-
40
- action_handler.open_stream(machine.node['name']) do |stdout|
41
- action_handler.open_stream(machine.node['name']) do |stderr|
42
- command_line = "chef-client"
43
- command_line << " -l #{config[:log_level].to_s}" if config[:log_level]
44
- machine.execute(action_handler, command_line,
45
- :stream_stdout => stdout,
46
- :stream_stderr => stderr,
47
- :timeout => @chef_client_timeout)
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end
1
+ require "chef/provisioning/convergence_strategy/install_sh"
@@ -1,37 +1 @@
1
- require 'chef_metal/convergence_strategy'
2
- require 'pathname'
3
- require 'cheffish'
4
-
5
- module ChefMetal
6
- class ConvergenceStrategy
7
- class NoConverge < ConvergenceStrategy
8
- def initialize(convergence_options, config)
9
- super
10
- end
11
-
12
- def chef_server
13
- @chef_server ||= convergence_options[:chef_server] || Cheffish.default_chef_server(config)
14
- end
15
-
16
- def setup_convergence(action_handler, machine)
17
- end
18
-
19
- def converge(action_handler, machine)
20
- end
21
-
22
- def cleanup_convergence(action_handler, machine_spec)
23
- _self = self
24
- ChefMetal.inline_resource(action_handler) do
25
- chef_node machine_spec.name do
26
- chef_server _self.chef_server
27
- action :delete
28
- end
29
- chef_client machine_spec.name do
30
- chef_server _self.chef_server
31
- action :delete
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
1
+ require "chef/provisioning/convergence_strategy/no_converge"
@@ -1,181 +1 @@
1
- require 'chef_metal/convergence_strategy'
2
- require 'pathname'
3
- require 'cheffish'
4
-
5
- module ChefMetal
6
- class ConvergenceStrategy
7
- class PrecreateChefObjects < ConvergenceStrategy
8
- def initialize(convergence_options, config)
9
- super
10
- end
11
-
12
- def chef_server
13
- @chef_server ||= convergence_options[:chef_server] || Cheffish.default_chef_server(config)
14
- end
15
-
16
- def setup_convergence(action_handler, machine)
17
- # Create keys on machine
18
- public_key = create_keys(action_handler, machine)
19
- # Create node and client on chef server
20
- create_chef_objects(action_handler, machine, public_key)
21
-
22
- # If the chef server lives on localhost, tunnel the port through to the guest
23
- # (we need to know what got tunneled!)
24
- chef_server_url = chef_server[:chef_server_url]
25
- chef_server_url = machine.make_url_available_to_remote(chef_server_url)
26
-
27
- # Support for multiple ohai hints, required on some platforms
28
- create_ohai_files(action_handler, machine)
29
-
30
- # Create client.rb and client.pem on machine
31
- content = client_rb_content(chef_server_url, machine.node['name'])
32
- machine.write_file(action_handler, convergence_options[:client_rb_path], content, :ensure_dir => true)
33
- end
34
-
35
- def converge(action_handler, machine)
36
- machine.make_url_available_to_remote(chef_server[:chef_server_url])
37
- end
38
-
39
- def cleanup_convergence(action_handler, machine_spec)
40
- _self = self
41
- ChefMetal.inline_resource(action_handler) do
42
- chef_node machine_spec.name do
43
- chef_server _self.chef_server
44
- action :delete
45
- end
46
- chef_client machine_spec.name do
47
- chef_server _self.chef_server
48
- action :delete
49
- end
50
- end
51
- end
52
-
53
- protected
54
-
55
- def create_keys(action_handler, machine)
56
- server_private_key = machine.read_file(convergence_options[:client_pem_path])
57
- if server_private_key
58
- begin
59
- server_private_key, format = Cheffish::KeyFormatter.decode(server_private_key)
60
- rescue
61
- server_private_key = nil
62
- end
63
- end
64
-
65
- if server_private_key
66
- if source_key && server_private_key.to_pem != source_key.to_pem
67
- # If the server private key does not match our source key, overwrite it
68
- server_private_key = source_key
69
- if convergence_options[:allow_overwrite_keys]
70
- machine.write_file(action_handler, convergence_options[:client_pem_path], server_private_key.to_pem, :ensure_dir => true)
71
- else
72
- raise "Private key on machine #{machine.name} does not match desired input key."
73
- end
74
- end
75
-
76
- else
77
-
78
- # If the server does not already have keys, create them and upload
79
- _convergence_options = convergence_options
80
- ChefMetal.inline_resource(action_handler) do
81
- private_key 'in_memory' do
82
- path :none
83
- if _convergence_options[:private_key_options]
84
- _convergence_options[:private_key_options].each_pair do |key,value|
85
- send(key, value)
86
- end
87
- end
88
- after { |resource, private_key| server_private_key = private_key }
89
- end
90
- end
91
-
92
- machine.write_file(action_handler, convergence_options[:client_pem_path], server_private_key.to_pem, :ensure_dir => true)
93
- end
94
-
95
- server_private_key.public_key
96
- end
97
-
98
- def is_localhost(host)
99
- host == '127.0.0.1' || host == 'localhost' || host == '[::1]'
100
- end
101
-
102
- def source_key
103
- if convergence_options[:source_key].is_a?(String)
104
- key, format = Cheffish::KeyFormatter.decode(convergence_options[:source_key], convergence_options[:source_key_pass_phrase])
105
- key
106
- elsif convergence_options[:source_key]
107
- convergence_options[:source_key]
108
- elsif convergence_options[:source_key_path]
109
- key, format = Cheffish::KeyFormatter.decode(IO.read(convergence_options[:source_key_path]), convergence_options[:source_key_pass_phrase], convergence_options[:source_key_path])
110
- key
111
- else
112
- nil
113
- end
114
- end
115
-
116
- # Create the ohai file(s)
117
- def create_ohai_files(action_handler, machine)
118
- if convergence_options[:ohai_hints]
119
- convergence_options[:ohai_hints].each_pair do |hint, data|
120
- # The location of the ohai hint
121
- ohai_hint = "/etc/chef/ohai/hints/#{hint}.json"
122
- machine.write_file(action_handler, ohai_hint, data.to_json, :ensure_dir => true)
123
- end
124
- end
125
- end
126
-
127
- def create_chef_objects(action_handler, machine, public_key)
128
- _convergence_options = convergence_options
129
- _chef_server = chef_server
130
- # Save the node and create the client keys and client.
131
- ChefMetal.inline_resource(action_handler) do
132
- # Create client
133
- chef_client machine.name do
134
- chef_server _chef_server
135
- source_key public_key
136
- output_key_path _convergence_options[:public_key_path]
137
- output_key_format _convergence_options[:public_key_format]
138
- admin _convergence_options[:admin]
139
- validator _convergence_options[:validator]
140
- end
141
-
142
- # Create node
143
- # TODO strip automatic attributes first so we don't race with "current state"
144
- chef_node machine.name do
145
- chef_server _chef_server
146
- raw_json machine.node
147
- end
148
- end
149
-
150
- # If using enterprise/hosted chef, fix acls
151
- if chef_server[:chef_server_url] =~ /\/+organizations\/.+/
152
- grant_client_node_permissions(action_handler, chef_server, machine.name, ["read", "update"])
153
- end
154
- end
155
-
156
- # Grant the client permissions to the node
157
- # This procedure assumes that the client name and node name are the same
158
- def grant_client_node_permissions(action_handler, chef_server, node_name, perms)
159
- api = Cheffish.chef_server_api(chef_server)
160
- node_perms = api.get("/nodes/#{node_name}/_acl")
161
- perms.each do |p|
162
- if !node_perms[p]['actors'].include?(node_name)
163
- action_handler.perform_action "Add #{node_name} to client #{p} ACLs" do
164
- node_perms[p]['actors'] << node_name
165
- api.put("/nodes/#{node_name}/_acl/#{p}", p => node_perms[p])
166
- end
167
- end
168
- end
169
- end
170
-
171
- def client_rb_content(chef_server_url, node_name)
172
- <<EOM
173
- chef_server_url #{chef_server_url.inspect}
174
- node_name #{node_name.inspect}
175
- client_key #{convergence_options[:client_pem_path].inspect}
176
- ssl_verify_mode :verify_none
177
- EOM
178
- end
179
- end
180
- end
181
- end
1
+ require "chef/provisioning/convergence_strategy/precreate_chef_objects"