chef-metal 0.14.2 → 0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"