chef-provisioning 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|