chef-provisioning 2.0.0 → 2.0.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +899 -885
- data/Gemfile +17 -17
- data/LICENSE +201 -201
- data/README.md +312 -312
- data/Rakefile +55 -55
- data/chef-provisioning.gemspec +38 -38
- data/lib/chef/provider/load_balancer.rb +75 -75
- data/lib/chef/provider/machine.rb +219 -219
- data/lib/chef/provider/machine_batch.rb +224 -224
- data/lib/chef/provider/machine_execute.rb +36 -35
- data/lib/chef/provider/machine_file.rb +55 -55
- data/lib/chef/provider/machine_image.rb +105 -105
- data/lib/chef/provisioning.rb +110 -110
- data/lib/chef/provisioning/action_handler.rb +68 -68
- data/lib/chef/provisioning/add_prefix_action_handler.rb +35 -35
- data/lib/chef/provisioning/chef_managed_entry_store.rb +128 -128
- data/lib/chef/provisioning/chef_provider_action_handler.rb +74 -74
- data/lib/chef/provisioning/chef_run_data.rb +132 -132
- data/lib/chef/provisioning/convergence_strategy.rb +28 -28
- data/lib/chef/provisioning/convergence_strategy/ignore_convergence_failure.rb +54 -54
- data/lib/chef/provisioning/convergence_strategy/install_cached.rb +188 -188
- data/lib/chef/provisioning/convergence_strategy/install_msi.rb +71 -71
- data/lib/chef/provisioning/convergence_strategy/install_sh.rb +71 -71
- data/lib/chef/provisioning/convergence_strategy/no_converge.rb +35 -35
- data/lib/chef/provisioning/convergence_strategy/precreate_chef_objects.rb +255 -255
- data/lib/chef/provisioning/driver.rb +323 -323
- data/lib/chef/provisioning/load_balancer_spec.rb +14 -14
- data/lib/chef/provisioning/machine.rb +112 -112
- data/lib/chef/provisioning/machine/basic_machine.rb +84 -84
- data/lib/chef/provisioning/machine/unix_machine.rb +288 -288
- data/lib/chef/provisioning/machine/windows_machine.rb +108 -108
- data/lib/chef/provisioning/machine_image_spec.rb +34 -34
- data/lib/chef/provisioning/machine_spec.rb +58 -58
- data/lib/chef/provisioning/managed_entry.rb +121 -121
- data/lib/chef/provisioning/managed_entry_store.rb +136 -136
- data/lib/chef/provisioning/recipe_dsl.rb +99 -99
- data/lib/chef/provisioning/rspec.rb +27 -27
- data/lib/chef/provisioning/transport.rb +100 -100
- data/lib/chef/provisioning/transport/ssh.rb +403 -403
- data/lib/chef/provisioning/transport/winrm.rb +144 -156
- data/lib/chef/provisioning/version.rb +5 -5
- data/lib/chef/resource/chef_data_bag_resource.rb +146 -146
- data/lib/chef/resource/load_balancer.rb +57 -57
- data/lib/chef/resource/machine.rb +128 -128
- data/lib/chef/resource/machine_batch.rb +78 -78
- data/lib/chef/resource/machine_execute.rb +30 -29
- data/lib/chef/resource/machine_file.rb +34 -34
- data/lib/chef/resource/machine_image.rb +35 -35
- data/lib/chef_metal.rb +1 -1
- data/spec/chef/provisioning/convergence_strategy/ignore_convergence_failure_spec.rb +86 -86
- data/spec/spec_helper.rb +27 -27
- metadata +5 -5
@@ -1,71 +1,71 @@
|
|
1
|
-
require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
|
2
|
-
require 'mixlib/install/script_generator'
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
class Chef
|
6
|
-
module Provisioning
|
7
|
-
class ConvergenceStrategy
|
8
|
-
class InstallMsi < PrecreateChefObjects
|
9
|
-
def initialize(convergence_options, config)
|
10
|
-
super
|
11
|
-
@chef_version ||= convergence_options[:chef_version]
|
12
|
-
@prerelease ||= convergence_options[:prerelease]
|
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 :chef_version
|
17
|
-
attr_reader :prerelease
|
18
|
-
attr_reader :install_msi_url
|
19
|
-
attr_reader :install_msi_path
|
20
|
-
|
21
|
-
def setup_convergence(action_handler, machine)
|
22
|
-
if !convergence_options.has_key?(:client_rb_path) || !convergence_options.has_key?(:client_pem_path)
|
23
|
-
system_drive = machine.system_drive
|
24
|
-
@convergence_options = Cheffish::MergedConfig.new(convergence_options, {
|
25
|
-
:client_rb_path => "#{system_drive}\\chef\\client.rb",
|
26
|
-
:client_pem_path => "#{system_drive}\\chef\\client.pem",
|
27
|
-
:install_script_path => "#{system_drive}\\chef\\\install.ps1"
|
28
|
-
})
|
29
|
-
end
|
30
|
-
|
31
|
-
opts = {"prerelease" => prerelease}
|
32
|
-
if convergence_options[:bootstrap_proxy]
|
33
|
-
opts["http_proxy"] = convergence_options[:bootstrap_proxy]
|
34
|
-
opts["https_proxy"] = convergence_options[:bootstrap_proxy]
|
35
|
-
end
|
36
|
-
opts["install_msi_url"] = convergence_options[:install_msi_url] if convergence_options[:install_msi_url]
|
37
|
-
super
|
38
|
-
|
39
|
-
install_command = Mixlib::Install::ScriptGenerator.new(chef_version, true, opts).install_command
|
40
|
-
machine.write_file(action_handler, convergence_options[:install_script_path], install_command)
|
41
|
-
|
42
|
-
action_handler.open_stream(machine.node['name']) do |stdout|
|
43
|
-
action_handler.open_stream(machine.node['name']) do |stderr|
|
44
|
-
machine.execute(action_handler, "
|
45
|
-
:
|
46
|
-
:
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
command_line = "
|
58
|
-
command_line << "
|
59
|
-
|
60
|
-
|
61
|
-
:stream_stdout => stdout,
|
62
|
-
:stream_stderr => stderr,
|
63
|
-
:timeout => @chef_client_timeout)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
1
|
+
require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
|
2
|
+
require 'mixlib/install/script_generator'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
module Provisioning
|
7
|
+
class ConvergenceStrategy
|
8
|
+
class InstallMsi < PrecreateChefObjects
|
9
|
+
def initialize(convergence_options, config)
|
10
|
+
super
|
11
|
+
@chef_version ||= convergence_options[:chef_version]
|
12
|
+
@prerelease ||= convergence_options[:prerelease]
|
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 :chef_version
|
17
|
+
attr_reader :prerelease
|
18
|
+
attr_reader :install_msi_url
|
19
|
+
attr_reader :install_msi_path
|
20
|
+
|
21
|
+
def setup_convergence(action_handler, machine)
|
22
|
+
if !convergence_options.has_key?(:client_rb_path) || !convergence_options.has_key?(:client_pem_path)
|
23
|
+
system_drive = machine.system_drive
|
24
|
+
@convergence_options = Cheffish::MergedConfig.new(convergence_options, {
|
25
|
+
:client_rb_path => "#{system_drive}\\chef\\client.rb",
|
26
|
+
:client_pem_path => "#{system_drive}\\chef\\client.pem",
|
27
|
+
:install_script_path => "#{system_drive}\\chef\\\install.ps1"
|
28
|
+
})
|
29
|
+
end
|
30
|
+
|
31
|
+
opts = {"prerelease" => prerelease}
|
32
|
+
if convergence_options[:bootstrap_proxy]
|
33
|
+
opts["http_proxy"] = convergence_options[:bootstrap_proxy]
|
34
|
+
opts["https_proxy"] = convergence_options[:bootstrap_proxy]
|
35
|
+
end
|
36
|
+
opts["install_msi_url"] = convergence_options[:install_msi_url] if convergence_options[:install_msi_url]
|
37
|
+
super
|
38
|
+
|
39
|
+
install_command = Mixlib::Install::ScriptGenerator.new(chef_version, true, opts).install_command
|
40
|
+
machine.write_file(action_handler, convergence_options[:install_script_path], install_command)
|
41
|
+
|
42
|
+
action_handler.open_stream(machine.node['name']) do |stdout|
|
43
|
+
action_handler.open_stream(machine.node['name']) do |stderr|
|
44
|
+
machine.execute(action_handler, "& \"#{convergence_options[:install_script_path]}\"",
|
45
|
+
:stream_stdout => stdout,
|
46
|
+
:stream_stderr => stderr)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def converge(action_handler, machine)
|
52
|
+
super
|
53
|
+
|
54
|
+
action_handler.open_stream(machine.node['name']) do |stdout|
|
55
|
+
action_handler.open_stream(machine.node['name']) do |stderr|
|
56
|
+
# We just installed chef in this shell so refresh PATH from System.Environment
|
57
|
+
command_line = "$env:path = [System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE');"
|
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
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,71 +1,71 @@
|
|
1
|
-
require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
|
2
|
-
require 'pathname'
|
3
|
-
require 'mixlib/install/script_generator'
|
4
|
-
|
5
|
-
class Chef
|
6
|
-
module Provisioning
|
7
|
-
class ConvergenceStrategy
|
8
|
-
class InstallSh < PrecreateChefObjects
|
9
|
-
@@install_sh_cache = {}
|
10
|
-
|
11
|
-
def initialize(convergence_options, config)
|
12
|
-
convergence_options = Cheffish::MergedConfig.new(convergence_options, {
|
13
|
-
:client_rb_path => '/etc/chef/client.rb',
|
14
|
-
:client_pem_path => '/etc/chef/client.pem'
|
15
|
-
})
|
16
|
-
super(convergence_options, config)
|
17
|
-
@client_rb_path ||= convergence_options[:client_rb_path]
|
18
|
-
@install_sh_path = convergence_options[:install_sh_path] || '/tmp/chef-install.sh'
|
19
|
-
@chef_version = convergence_options[:chef_version]
|
20
|
-
@prerelease = convergence_options[:prerelease]
|
21
|
-
@install_sh_arguments = convergence_options[:install_sh_arguments]
|
22
|
-
@bootstrap_env = convergence_options[:bootstrap_proxy] ? "http_proxy=#{convergence_options[:bootstrap_proxy]} https_proxy=$http_proxy " : ""
|
23
|
-
@chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
|
24
|
-
end
|
25
|
-
|
26
|
-
attr_reader :client_rb_path
|
27
|
-
attr_reader :chef_version
|
28
|
-
attr_reader :prerelease
|
29
|
-
attr_reader :install_sh_path
|
30
|
-
attr_reader :install_sh_arguments
|
31
|
-
attr_reader :bootstrap_env
|
32
|
-
|
33
|
-
def setup_convergence(action_handler, machine)
|
34
|
-
super
|
35
|
-
|
36
|
-
opts = {"prerelease" => prerelease}
|
37
|
-
if convergence_options[:bootstrap_proxy]
|
38
|
-
opts["http_proxy"] = convergence_options[:bootstrap_proxy]
|
39
|
-
opts["https_proxy"] = convergence_options[:bootstrap_proxy]
|
40
|
-
end
|
41
|
-
|
42
|
-
opts["omnibus_url"] = convergence_options[:install_sh_url] if convergence_options[:install_sh_url]
|
43
|
-
|
44
|
-
if convergence_options[:install_sh_arguments]
|
45
|
-
opts['install_flags'] = convergence_options[:install_sh_arguments]
|
46
|
-
end
|
47
|
-
|
48
|
-
install_command = Mixlib::Install::ScriptGenerator.new(chef_version, false, opts).install_command
|
49
|
-
machine.write_file(action_handler, install_sh_path, install_command, :ensure_dir => true)
|
50
|
-
machine.set_attributes(action_handler, install_sh_path, :mode => '0755')
|
51
|
-
machine.execute(action_handler, "sh -c #{install_sh_path}")
|
52
|
-
end
|
53
|
-
|
54
|
-
def converge(action_handler, machine)
|
55
|
-
super
|
56
|
-
|
57
|
-
action_handler.open_stream(machine.node['name']) do |stdout|
|
58
|
-
action_handler.open_stream(machine.node['name']) do |stderr|
|
59
|
-
command_line = "chef-client"
|
60
|
-
command_line << " -c #{@client_rb_path} -l #{config[:log_level].to_s}" if config[:log_level]
|
61
|
-
machine.execute(action_handler, command_line,
|
62
|
-
:stream_stdout => stdout,
|
63
|
-
:stream_stderr => stderr,
|
64
|
-
:timeout => @chef_client_timeout)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
1
|
+
require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
|
2
|
+
require 'pathname'
|
3
|
+
require 'mixlib/install/script_generator'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
module Provisioning
|
7
|
+
class ConvergenceStrategy
|
8
|
+
class InstallSh < PrecreateChefObjects
|
9
|
+
@@install_sh_cache = {}
|
10
|
+
|
11
|
+
def initialize(convergence_options, config)
|
12
|
+
convergence_options = Cheffish::MergedConfig.new(convergence_options, {
|
13
|
+
:client_rb_path => '/etc/chef/client.rb',
|
14
|
+
:client_pem_path => '/etc/chef/client.pem'
|
15
|
+
})
|
16
|
+
super(convergence_options, config)
|
17
|
+
@client_rb_path ||= convergence_options[:client_rb_path]
|
18
|
+
@install_sh_path = convergence_options[:install_sh_path] || '/tmp/chef-install.sh'
|
19
|
+
@chef_version = convergence_options[:chef_version]
|
20
|
+
@prerelease = convergence_options[:prerelease]
|
21
|
+
@install_sh_arguments = convergence_options[:install_sh_arguments]
|
22
|
+
@bootstrap_env = convergence_options[:bootstrap_proxy] ? "http_proxy=#{convergence_options[:bootstrap_proxy]} https_proxy=$http_proxy " : ""
|
23
|
+
@chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :client_rb_path
|
27
|
+
attr_reader :chef_version
|
28
|
+
attr_reader :prerelease
|
29
|
+
attr_reader :install_sh_path
|
30
|
+
attr_reader :install_sh_arguments
|
31
|
+
attr_reader :bootstrap_env
|
32
|
+
|
33
|
+
def setup_convergence(action_handler, machine)
|
34
|
+
super
|
35
|
+
|
36
|
+
opts = {"prerelease" => prerelease}
|
37
|
+
if convergence_options[:bootstrap_proxy]
|
38
|
+
opts["http_proxy"] = convergence_options[:bootstrap_proxy]
|
39
|
+
opts["https_proxy"] = convergence_options[:bootstrap_proxy]
|
40
|
+
end
|
41
|
+
|
42
|
+
opts["omnibus_url"] = convergence_options[:install_sh_url] if convergence_options[:install_sh_url]
|
43
|
+
|
44
|
+
if convergence_options[:install_sh_arguments]
|
45
|
+
opts['install_flags'] = convergence_options[:install_sh_arguments]
|
46
|
+
end
|
47
|
+
|
48
|
+
install_command = Mixlib::Install::ScriptGenerator.new(chef_version, false, opts).install_command
|
49
|
+
machine.write_file(action_handler, install_sh_path, install_command, :ensure_dir => true)
|
50
|
+
machine.set_attributes(action_handler, install_sh_path, :mode => '0755')
|
51
|
+
machine.execute(action_handler, "sh -c #{install_sh_path}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def converge(action_handler, machine)
|
55
|
+
super
|
56
|
+
|
57
|
+
action_handler.open_stream(machine.node['name']) do |stdout|
|
58
|
+
action_handler.open_stream(machine.node['name']) do |stderr|
|
59
|
+
command_line = "chef-client"
|
60
|
+
command_line << " -c #{@client_rb_path} -l #{config[:log_level].to_s}" if config[:log_level]
|
61
|
+
machine.execute(action_handler, command_line,
|
62
|
+
:stream_stdout => stdout,
|
63
|
+
:stream_stderr => stderr,
|
64
|
+
:timeout => @chef_client_timeout)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,35 +1,35 @@
|
|
1
|
-
require 'chef/provisioning/convergence_strategy'
|
2
|
-
require 'pathname'
|
3
|
-
require 'cheffish'
|
4
|
-
|
5
|
-
class Chef
|
6
|
-
module Provisioning
|
7
|
-
class ConvergenceStrategy
|
8
|
-
class NoConverge < ConvergenceStrategy
|
9
|
-
def chef_server
|
10
|
-
@chef_server ||= convergence_options[:chef_server] || Cheffish.default_chef_server(config)
|
11
|
-
end
|
12
|
-
|
13
|
-
def setup_convergence(action_handler, machine)
|
14
|
-
end
|
15
|
-
|
16
|
-
def converge(action_handler, machine)
|
17
|
-
end
|
18
|
-
|
19
|
-
def cleanup_convergence(action_handler, machine_spec)
|
20
|
-
_self = self
|
21
|
-
Chef::Provisioning.inline_resource(action_handler) do
|
22
|
-
chef_node machine_spec.name do
|
23
|
-
chef_server _self.chef_server
|
24
|
-
action :delete
|
25
|
-
end
|
26
|
-
chef_client machine_spec.name do
|
27
|
-
chef_server _self.chef_server
|
28
|
-
action :delete
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
1
|
+
require 'chef/provisioning/convergence_strategy'
|
2
|
+
require 'pathname'
|
3
|
+
require 'cheffish'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
module Provisioning
|
7
|
+
class ConvergenceStrategy
|
8
|
+
class NoConverge < ConvergenceStrategy
|
9
|
+
def chef_server
|
10
|
+
@chef_server ||= convergence_options[:chef_server] || Cheffish.default_chef_server(config)
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup_convergence(action_handler, machine)
|
14
|
+
end
|
15
|
+
|
16
|
+
def converge(action_handler, machine)
|
17
|
+
end
|
18
|
+
|
19
|
+
def cleanup_convergence(action_handler, machine_spec)
|
20
|
+
_self = self
|
21
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
22
|
+
chef_node machine_spec.name do
|
23
|
+
chef_server _self.chef_server
|
24
|
+
action :delete
|
25
|
+
end
|
26
|
+
chef_client machine_spec.name do
|
27
|
+
chef_server _self.chef_server
|
28
|
+
action :delete
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,255 +1,255 @@
|
|
1
|
-
require 'chef/provisioning/convergence_strategy'
|
2
|
-
require 'pathname'
|
3
|
-
require 'cheffish'
|
4
|
-
require 'chef_zero/socketless_server_map'
|
5
|
-
require_relative 'ignore_convergence_failure'
|
6
|
-
|
7
|
-
class Chef
|
8
|
-
module Provisioning
|
9
|
-
class ConvergenceStrategy
|
10
|
-
class PrecreateChefObjects < ConvergenceStrategy
|
11
|
-
|
12
|
-
def initialize(convergence_options, config)
|
13
|
-
super
|
14
|
-
if convergence_options[:ignore_failure]
|
15
|
-
extend IgnoreConvergenceFailure
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def chef_server
|
20
|
-
@chef_server ||= convergence_options[:chef_server] || Cheffish.default_chef_server(config)
|
21
|
-
end
|
22
|
-
|
23
|
-
def setup_convergence(action_handler, machine)
|
24
|
-
# Create keys on machine
|
25
|
-
private_key, public_key = create_keys(action_handler, machine)
|
26
|
-
# Create node and client on chef server
|
27
|
-
create_chef_objects(action_handler, machine, private_key, public_key)
|
28
|
-
|
29
|
-
# If the chef server lives on localhost, tunnel the port through to the guest
|
30
|
-
# (we need to know what got tunneled!)
|
31
|
-
chef_server_url = chef_server[:chef_server_url]
|
32
|
-
chef_server_url = machine.make_url_available_to_remote(chef_server_url)
|
33
|
-
|
34
|
-
# Support for multiple ohai hints, required on some platforms
|
35
|
-
create_ohai_files(action_handler, machine)
|
36
|
-
|
37
|
-
# Create client.rb and client.pem on machine
|
38
|
-
content = client_rb_content(chef_server_url, machine.node['name'])
|
39
|
-
machine.write_file(action_handler, convergence_options[:client_rb_path], content, :ensure_dir => true)
|
40
|
-
end
|
41
|
-
|
42
|
-
def converge(action_handler, machine)
|
43
|
-
machine.make_url_available_to_remote(chef_server[:chef_server_url])
|
44
|
-
end
|
45
|
-
|
46
|
-
def cleanup_convergence(action_handler, machine_spec)
|
47
|
-
_self = self
|
48
|
-
Chef::Provisioning.inline_resource(action_handler) do
|
49
|
-
chef_node machine_spec.name do
|
50
|
-
chef_server _self.chef_server
|
51
|
-
action :delete
|
52
|
-
end
|
53
|
-
chef_client machine_spec.name do
|
54
|
-
chef_server _self.chef_server
|
55
|
-
action :delete
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
protected
|
61
|
-
|
62
|
-
def create_keys(action_handler, machine)
|
63
|
-
server_private_key = machine.read_file(convergence_options[:client_pem_path])
|
64
|
-
if server_private_key
|
65
|
-
begin
|
66
|
-
server_private_key, format = Cheffish::KeyFormatter.decode(server_private_key)
|
67
|
-
rescue
|
68
|
-
server_private_key = nil
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
if server_private_key
|
73
|
-
if source_key && server_private_key.to_pem != source_key.to_pem
|
74
|
-
# If the server private key does not match our source key, overwrite it
|
75
|
-
server_private_key = source_key
|
76
|
-
if convergence_options[:allow_overwrite_keys]
|
77
|
-
machine.write_file(action_handler, convergence_options[:client_pem_path], server_private_key.to_pem, :ensure_dir => true)
|
78
|
-
else
|
79
|
-
raise "Private key on machine #{machine.name} does not match desired input key."
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
else
|
84
|
-
|
85
|
-
# If the server does not already have keys, create them and upload
|
86
|
-
_convergence_options = convergence_options
|
87
|
-
Chef::Provisioning.inline_resource(action_handler) do
|
88
|
-
private_key 'in_memory' do
|
89
|
-
path :none
|
90
|
-
if _convergence_options[:private_key_options]
|
91
|
-
_convergence_options[:private_key_options].each_pair do |key,value|
|
92
|
-
send(key, value)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
after { |resource, private_key| server_private_key = private_key }
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
machine.write_file(action_handler, convergence_options[:client_pem_path], server_private_key.to_pem, :ensure_dir => true)
|
100
|
-
end
|
101
|
-
|
102
|
-
# We shouldn't be returning this: see https://github.com/chef/chef-provisioning/issues/292
|
103
|
-
[ server_private_key, server_private_key.public_key ]
|
104
|
-
end
|
105
|
-
|
106
|
-
def is_localhost(host)
|
107
|
-
host == '127.0.0.1' || host == 'localhost' || host == '[::1]'
|
108
|
-
end
|
109
|
-
|
110
|
-
def source_key
|
111
|
-
if convergence_options[:source_key].is_a?(String)
|
112
|
-
key, format = Cheffish::KeyFormatter.decode(convergence_options[:source_key], convergence_options[:source_key_pass_phrase])
|
113
|
-
key
|
114
|
-
elsif convergence_options[:source_key]
|
115
|
-
convergence_options[:source_key]
|
116
|
-
elsif convergence_options[:source_key_path]
|
117
|
-
key, format = Cheffish::KeyFormatter.decode(IO.read(convergence_options[:source_key_path]), convergence_options[:source_key_pass_phrase], convergence_options[:source_key_path])
|
118
|
-
key
|
119
|
-
else
|
120
|
-
nil
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# Create the ohai file(s)
|
125
|
-
def create_ohai_files(action_handler, machine)
|
126
|
-
if convergence_options[:ohai_hints]
|
127
|
-
convergence_options[:ohai_hints].each_pair do |hint, data|
|
128
|
-
# The location of the ohai hint
|
129
|
-
ohai_hint = "/etc/chef/ohai/hints/#{hint}.json"
|
130
|
-
# It's in a different path on windows
|
131
|
-
if machine.machine_spec.reference['is_windows']
|
132
|
-
ohai_hint = [machine.system_drive, ohai_hint.split('/')[2..-1]].join('\\')
|
133
|
-
end
|
134
|
-
machine.write_file(action_handler, ohai_hint, data.to_json, :ensure_dir => true)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def create_chef_objects(action_handler, machine, private_key, public_key)
|
140
|
-
_convergence_options = convergence_options
|
141
|
-
_chef_server = chef_server
|
142
|
-
_format = _convergence_options[:public_key_format]
|
143
|
-
# Save the node and create the client keys and client.
|
144
|
-
Chef::Provisioning.inline_resource(action_handler) do
|
145
|
-
# Create client
|
146
|
-
chef_client machine.name do
|
147
|
-
chef_server _chef_server
|
148
|
-
source_key public_key
|
149
|
-
output_key_path _convergence_options[:public_key_path]
|
150
|
-
output_key_format _format if _format
|
151
|
-
admin _convergence_options[:admin]
|
152
|
-
validator _convergence_options[:validator]
|
153
|
-
end
|
154
|
-
|
155
|
-
# Create node
|
156
|
-
# TODO strip automatic attributes first so we don't race with "current state"
|
157
|
-
chef_node machine.name do
|
158
|
-
chef_server _chef_server
|
159
|
-
raw_json machine.node
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
# If using enterprise/hosted chef, fix acls
|
164
|
-
if chef_server[:chef_server_url] =~ /\/+organizations\/.+/
|
165
|
-
grant_client_node_permissions(action_handler, chef_server, machine, ["read", "update"], private_key)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
# Grant the client permissions to the node
|
170
|
-
# This procedure assumes that the client name and node name are the same
|
171
|
-
def grant_client_node_permissions(action_handler, chef_server, machine, perms, private_key)
|
172
|
-
node_name = machine.name
|
173
|
-
api = Cheffish.chef_server_api(chef_server)
|
174
|
-
node_perms = api.get("/nodes/#{node_name}/_acl")
|
175
|
-
|
176
|
-
begin
|
177
|
-
perms.each do |p|
|
178
|
-
if !node_perms[p]['actors'].include?(node_name)
|
179
|
-
action_handler.perform_action "Add #{node_name} to client #{p} ACLs" do
|
180
|
-
node_perms[p]['actors'] << node_name
|
181
|
-
api.put("/nodes/#{node_name}/_acl/#{p}", p => node_perms[p])
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
rescue Net::HTTPServerException => e
|
186
|
-
if e.response.code == "400"
|
187
|
-
action_handler.perform_action "Delete #{node_name} and recreate as client #{node_name}" do
|
188
|
-
api.delete("/nodes/#{node_name}")
|
189
|
-
as_user = chef_server.dup
|
190
|
-
as_user[:options] = as_user[:options].merge(
|
191
|
-
client_name: node_name,
|
192
|
-
signing_key_filename: nil,
|
193
|
-
raw_key: private_key.to_pem
|
194
|
-
)
|
195
|
-
as_user_api = Cheffish.chef_server_api(as_user)
|
196
|
-
as_user_api.post("/nodes", machine.node)
|
197
|
-
end
|
198
|
-
else
|
199
|
-
raise
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def client_rb_content(chef_server_url, node_name)
|
205
|
-
# Chef stores a 'port registry' of chef zero URLs. If we set the remote host's
|
206
|
-
# chef_server_url to a `chefzero` url it will fail because it does not know
|
207
|
-
# about the workstation's chef zero server
|
208
|
-
uri = URI.parse(chef_server_url)
|
209
|
-
if uri.scheme == 'chefzero' && uri.host == 'localhost'
|
210
|
-
if !Chef::Config[:listen]
|
211
|
-
raise "The remote host is configured to access the local chefzero host, but " +
|
212
|
-
"the local chefzero host is not configured to listen. Provide --listen or " +
|
213
|
-
"set `listen true` in the chef config."
|
214
|
-
end
|
215
|
-
# Once chef and chef-dk are using chef-zero which supports this, we can
|
216
|
-
# remove the else block and the if check
|
217
|
-
if ChefZero::SocketlessServerMap.respond_to?(:server_on_port)
|
218
|
-
chef_server_url = ChefZero::SocketlessServerMap.server_on_port(uri.port).url
|
219
|
-
else
|
220
|
-
chef_server_url = chef_server_url.gsub(/^chefzero/, 'http')
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
ssl_verify_mode = convergence_options[:ssl_verify_mode]
|
225
|
-
ssl_verify_mode ||= if chef_server_url.downcase.start_with?("https")
|
226
|
-
:verify_peer
|
227
|
-
else
|
228
|
-
:verify_none
|
229
|
-
end
|
230
|
-
|
231
|
-
content = <<-EOM
|
232
|
-
chef_server_url #{chef_server_url.inspect}
|
233
|
-
node_name #{node_name.inspect}
|
234
|
-
client_key #{convergence_options[:client_pem_path].inspect}
|
235
|
-
ssl_verify_mode #{ssl_verify_mode.to_sym.inspect}
|
236
|
-
EOM
|
237
|
-
if convergence_options[:bootstrap_proxy]
|
238
|
-
content << <<-EOM
|
239
|
-
http_proxy #{convergence_options[:bootstrap_proxy].inspect}
|
240
|
-
https_proxy #{convergence_options[:bootstrap_proxy].inspect}
|
241
|
-
EOM
|
242
|
-
end
|
243
|
-
if convergence_options[:bootstrap_no_proxy]
|
244
|
-
content << <<-EOM
|
245
|
-
no_proxy #{convergence_options[:bootstrap_no_proxy].inspect}
|
246
|
-
EOM
|
247
|
-
end
|
248
|
-
content.gsub!(/^\s+/, "")
|
249
|
-
content << convergence_options[:chef_config] if convergence_options[:chef_config]
|
250
|
-
content
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
1
|
+
require 'chef/provisioning/convergence_strategy'
|
2
|
+
require 'pathname'
|
3
|
+
require 'cheffish'
|
4
|
+
require 'chef_zero/socketless_server_map'
|
5
|
+
require_relative 'ignore_convergence_failure'
|
6
|
+
|
7
|
+
class Chef
|
8
|
+
module Provisioning
|
9
|
+
class ConvergenceStrategy
|
10
|
+
class PrecreateChefObjects < ConvergenceStrategy
|
11
|
+
|
12
|
+
def initialize(convergence_options, config)
|
13
|
+
super
|
14
|
+
if convergence_options[:ignore_failure]
|
15
|
+
extend IgnoreConvergenceFailure
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def chef_server
|
20
|
+
@chef_server ||= convergence_options[:chef_server] || Cheffish.default_chef_server(config)
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_convergence(action_handler, machine)
|
24
|
+
# Create keys on machine
|
25
|
+
private_key, public_key = create_keys(action_handler, machine)
|
26
|
+
# Create node and client on chef server
|
27
|
+
create_chef_objects(action_handler, machine, private_key, public_key)
|
28
|
+
|
29
|
+
# If the chef server lives on localhost, tunnel the port through to the guest
|
30
|
+
# (we need to know what got tunneled!)
|
31
|
+
chef_server_url = chef_server[:chef_server_url]
|
32
|
+
chef_server_url = machine.make_url_available_to_remote(chef_server_url)
|
33
|
+
|
34
|
+
# Support for multiple ohai hints, required on some platforms
|
35
|
+
create_ohai_files(action_handler, machine)
|
36
|
+
|
37
|
+
# Create client.rb and client.pem on machine
|
38
|
+
content = client_rb_content(chef_server_url, machine.node['name'])
|
39
|
+
machine.write_file(action_handler, convergence_options[:client_rb_path], content, :ensure_dir => true)
|
40
|
+
end
|
41
|
+
|
42
|
+
def converge(action_handler, machine)
|
43
|
+
machine.make_url_available_to_remote(chef_server[:chef_server_url])
|
44
|
+
end
|
45
|
+
|
46
|
+
def cleanup_convergence(action_handler, machine_spec)
|
47
|
+
_self = self
|
48
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
49
|
+
chef_node machine_spec.name do
|
50
|
+
chef_server _self.chef_server
|
51
|
+
action :delete
|
52
|
+
end
|
53
|
+
chef_client machine_spec.name do
|
54
|
+
chef_server _self.chef_server
|
55
|
+
action :delete
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
|
62
|
+
def create_keys(action_handler, machine)
|
63
|
+
server_private_key = machine.read_file(convergence_options[:client_pem_path])
|
64
|
+
if server_private_key
|
65
|
+
begin
|
66
|
+
server_private_key, format = Cheffish::KeyFormatter.decode(server_private_key)
|
67
|
+
rescue
|
68
|
+
server_private_key = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if server_private_key
|
73
|
+
if source_key && server_private_key.to_pem != source_key.to_pem
|
74
|
+
# If the server private key does not match our source key, overwrite it
|
75
|
+
server_private_key = source_key
|
76
|
+
if convergence_options[:allow_overwrite_keys]
|
77
|
+
machine.write_file(action_handler, convergence_options[:client_pem_path], server_private_key.to_pem, :ensure_dir => true)
|
78
|
+
else
|
79
|
+
raise "Private key on machine #{machine.name} does not match desired input key."
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
else
|
84
|
+
|
85
|
+
# If the server does not already have keys, create them and upload
|
86
|
+
_convergence_options = convergence_options
|
87
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
88
|
+
private_key 'in_memory' do
|
89
|
+
path :none
|
90
|
+
if _convergence_options[:private_key_options]
|
91
|
+
_convergence_options[:private_key_options].each_pair do |key,value|
|
92
|
+
send(key, value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
after { |resource, private_key| server_private_key = private_key }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
machine.write_file(action_handler, convergence_options[:client_pem_path], server_private_key.to_pem, :ensure_dir => true)
|
100
|
+
end
|
101
|
+
|
102
|
+
# We shouldn't be returning this: see https://github.com/chef/chef-provisioning/issues/292
|
103
|
+
[ server_private_key, server_private_key.public_key ]
|
104
|
+
end
|
105
|
+
|
106
|
+
def is_localhost(host)
|
107
|
+
host == '127.0.0.1' || host == 'localhost' || host == '[::1]'
|
108
|
+
end
|
109
|
+
|
110
|
+
def source_key
|
111
|
+
if convergence_options[:source_key].is_a?(String)
|
112
|
+
key, format = Cheffish::KeyFormatter.decode(convergence_options[:source_key], convergence_options[:source_key_pass_phrase])
|
113
|
+
key
|
114
|
+
elsif convergence_options[:source_key]
|
115
|
+
convergence_options[:source_key]
|
116
|
+
elsif convergence_options[:source_key_path]
|
117
|
+
key, format = Cheffish::KeyFormatter.decode(IO.read(convergence_options[:source_key_path]), convergence_options[:source_key_pass_phrase], convergence_options[:source_key_path])
|
118
|
+
key
|
119
|
+
else
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Create the ohai file(s)
|
125
|
+
def create_ohai_files(action_handler, machine)
|
126
|
+
if convergence_options[:ohai_hints]
|
127
|
+
convergence_options[:ohai_hints].each_pair do |hint, data|
|
128
|
+
# The location of the ohai hint
|
129
|
+
ohai_hint = "/etc/chef/ohai/hints/#{hint}.json"
|
130
|
+
# It's in a different path on windows
|
131
|
+
if machine.machine_spec.reference['is_windows']
|
132
|
+
ohai_hint = [machine.system_drive, ohai_hint.split('/')[2..-1]].join('\\')
|
133
|
+
end
|
134
|
+
machine.write_file(action_handler, ohai_hint, data.to_json, :ensure_dir => true)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def create_chef_objects(action_handler, machine, private_key, public_key)
|
140
|
+
_convergence_options = convergence_options
|
141
|
+
_chef_server = chef_server
|
142
|
+
_format = _convergence_options[:public_key_format]
|
143
|
+
# Save the node and create the client keys and client.
|
144
|
+
Chef::Provisioning.inline_resource(action_handler) do
|
145
|
+
# Create client
|
146
|
+
chef_client machine.name do
|
147
|
+
chef_server _chef_server
|
148
|
+
source_key public_key
|
149
|
+
output_key_path _convergence_options[:public_key_path]
|
150
|
+
output_key_format _format if _format
|
151
|
+
admin _convergence_options[:admin]
|
152
|
+
validator _convergence_options[:validator]
|
153
|
+
end
|
154
|
+
|
155
|
+
# Create node
|
156
|
+
# TODO strip automatic attributes first so we don't race with "current state"
|
157
|
+
chef_node machine.name do
|
158
|
+
chef_server _chef_server
|
159
|
+
raw_json machine.node
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# If using enterprise/hosted chef, fix acls
|
164
|
+
if chef_server[:chef_server_url] =~ /\/+organizations\/.+/
|
165
|
+
grant_client_node_permissions(action_handler, chef_server, machine, ["read", "update"], private_key)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Grant the client permissions to the node
|
170
|
+
# This procedure assumes that the client name and node name are the same
|
171
|
+
def grant_client_node_permissions(action_handler, chef_server, machine, perms, private_key)
|
172
|
+
node_name = machine.name
|
173
|
+
api = Cheffish.chef_server_api(chef_server)
|
174
|
+
node_perms = api.get("/nodes/#{node_name}/_acl")
|
175
|
+
|
176
|
+
begin
|
177
|
+
perms.each do |p|
|
178
|
+
if !node_perms[p]['actors'].include?(node_name)
|
179
|
+
action_handler.perform_action "Add #{node_name} to client #{p} ACLs" do
|
180
|
+
node_perms[p]['actors'] << node_name
|
181
|
+
api.put("/nodes/#{node_name}/_acl/#{p}", p => node_perms[p])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
rescue Net::HTTPServerException => e
|
186
|
+
if e.response.code == "400"
|
187
|
+
action_handler.perform_action "Delete #{node_name} and recreate as client #{node_name}" do
|
188
|
+
api.delete("/nodes/#{node_name}")
|
189
|
+
as_user = chef_server.dup
|
190
|
+
as_user[:options] = as_user[:options].merge(
|
191
|
+
client_name: node_name,
|
192
|
+
signing_key_filename: nil,
|
193
|
+
raw_key: private_key.to_pem
|
194
|
+
)
|
195
|
+
as_user_api = Cheffish.chef_server_api(as_user)
|
196
|
+
as_user_api.post("/nodes", machine.node)
|
197
|
+
end
|
198
|
+
else
|
199
|
+
raise
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def client_rb_content(chef_server_url, node_name)
|
205
|
+
# Chef stores a 'port registry' of chef zero URLs. If we set the remote host's
|
206
|
+
# chef_server_url to a `chefzero` url it will fail because it does not know
|
207
|
+
# about the workstation's chef zero server
|
208
|
+
uri = URI.parse(chef_server_url)
|
209
|
+
if uri.scheme == 'chefzero' && uri.host == 'localhost'
|
210
|
+
if !Chef::Config[:listen]
|
211
|
+
raise "The remote host is configured to access the local chefzero host, but " +
|
212
|
+
"the local chefzero host is not configured to listen. Provide --listen or " +
|
213
|
+
"set `listen true` in the chef config."
|
214
|
+
end
|
215
|
+
# Once chef and chef-dk are using chef-zero which supports this, we can
|
216
|
+
# remove the else block and the if check
|
217
|
+
if ChefZero::SocketlessServerMap.respond_to?(:server_on_port)
|
218
|
+
chef_server_url = ChefZero::SocketlessServerMap.server_on_port(uri.port).url
|
219
|
+
else
|
220
|
+
chef_server_url = chef_server_url.gsub(/^chefzero/, 'http')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
ssl_verify_mode = convergence_options[:ssl_verify_mode]
|
225
|
+
ssl_verify_mode ||= if chef_server_url.downcase.start_with?("https")
|
226
|
+
:verify_peer
|
227
|
+
else
|
228
|
+
:verify_none
|
229
|
+
end
|
230
|
+
|
231
|
+
content = <<-EOM
|
232
|
+
chef_server_url #{chef_server_url.inspect}
|
233
|
+
node_name #{node_name.inspect}
|
234
|
+
client_key #{convergence_options[:client_pem_path].inspect}
|
235
|
+
ssl_verify_mode #{ssl_verify_mode.to_sym.inspect}
|
236
|
+
EOM
|
237
|
+
if convergence_options[:bootstrap_proxy]
|
238
|
+
content << <<-EOM
|
239
|
+
http_proxy #{convergence_options[:bootstrap_proxy].inspect}
|
240
|
+
https_proxy #{convergence_options[:bootstrap_proxy].inspect}
|
241
|
+
EOM
|
242
|
+
end
|
243
|
+
if convergence_options[:bootstrap_no_proxy]
|
244
|
+
content << <<-EOM
|
245
|
+
no_proxy #{convergence_options[:bootstrap_no_proxy].inspect}
|
246
|
+
EOM
|
247
|
+
end
|
248
|
+
content.gsub!(/^\s+/, "")
|
249
|
+
content << convergence_options[:chef_config] if convergence_options[:chef_config]
|
250
|
+
content
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|