ridley 0.12.4 → 1.0.0.rc1
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.
- data/Gemfile +1 -1
- data/lib/ridley.rb +3 -3
- data/lib/ridley/bootstrap_context.rb +100 -0
- data/lib/ridley/bootstrap_context/unix.rb +74 -0
- data/lib/ridley/bootstrap_context/windows.rb +120 -0
- data/lib/ridley/chef_objects/node_object.rb +8 -5
- data/lib/ridley/host_commander.rb +207 -0
- data/lib/ridley/host_connector.rb +49 -87
- data/lib/ridley/host_connector/ssh.rb +153 -39
- data/lib/ridley/host_connector/winrm.rb +164 -39
- data/lib/ridley/resources/node_resource.rb +52 -56
- data/lib/ridley/version.rb +1 -1
- data/ridley.gemspec +0 -2
- data/spec/spec_helper.rb +4 -4
- data/spec/support/chef_server.rb +9 -3
- data/spec/unit/ridley/{bootstrap_bindings/unix_template_binding_spec.rb → bootstrap_context/unix_spec.rb} +2 -2
- data/spec/unit/ridley/{bootstrap_bindings/windows_template_binding_spec.rb → bootstrap_context/windows_spec.rb} +2 -2
- data/spec/unit/ridley/{mixin/bootstrap_binding_spec.rb → bootstrap_context_spec.rb} +2 -6
- data/spec/unit/ridley/host_commander_spec.rb +208 -0
- data/spec/unit/ridley/host_connector/ssh_spec.rb +37 -31
- data/spec/unit/ridley/host_connector/winrm_spec.rb +124 -31
- data/spec/unit/ridley/host_connector_spec.rb +23 -147
- data/spec/unit/ridley/resources/node_resource_spec.rb +55 -115
- metadata +17 -66
- data/lib/ridley/bootstrap_bindings.rb +0 -3
- data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +0 -108
- data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +0 -163
- data/lib/ridley/bootstrapper.rb +0 -89
- data/lib/ridley/bootstrapper/context.rb +0 -81
- data/lib/ridley/host_connector/response_set.rb +0 -98
- data/lib/ridley/host_connector/ssh/worker.rb +0 -135
- data/lib/ridley/host_connector/winrm/worker.rb +0 -159
- data/lib/ridley/log.rb +0 -10
- data/lib/ridley/mixin/bootstrap_binding.rb +0 -77
- data/spec/unit/ridley/bootstrapper/context_spec.rb +0 -45
- data/spec/unit/ridley/bootstrapper_spec.rb +0 -96
- data/spec/unit/ridley/host_connector/response_set_spec.rb +0 -112
- data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +0 -57
- data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +0 -139
data/Gemfile
CHANGED
data/lib/ridley.rb
CHANGED
@@ -16,15 +16,15 @@ module Ridley
|
|
16
16
|
CHEF_VERSION = '11.4.0'.freeze
|
17
17
|
|
18
18
|
require_relative 'ridley/mixin'
|
19
|
-
require_relative 'ridley/
|
20
|
-
require_relative 'ridley/
|
19
|
+
require_relative 'ridley/logging'
|
20
|
+
require_relative 'ridley/bootstrap_context'
|
21
21
|
require_relative 'ridley/chef_object'
|
22
22
|
require_relative 'ridley/chef_objects'
|
23
23
|
require_relative 'ridley/client'
|
24
24
|
require_relative 'ridley/connection'
|
25
25
|
require_relative 'ridley/chef'
|
26
|
+
require_relative 'ridley/host_commander'
|
26
27
|
require_relative 'ridley/host_connector'
|
27
|
-
require_relative 'ridley/logging'
|
28
28
|
require_relative 'ridley/middleware'
|
29
29
|
require_relative 'ridley/resource'
|
30
30
|
require_relative 'ridley/resources'
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
|
3
|
+
module Ridley
|
4
|
+
module BootstrapContext
|
5
|
+
class Base
|
6
|
+
class << self
|
7
|
+
def validate_options(options = {})
|
8
|
+
if options[:server_url].nil?
|
9
|
+
raise Errors::ArgumentError, "A server_url is required for bootstrapping"
|
10
|
+
end
|
11
|
+
|
12
|
+
if options[:validator_path].nil?
|
13
|
+
raise Errors::ArgumentError, "A path to a validator is required for bootstrapping"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :template_file
|
19
|
+
attr_reader :bootstrap_proxy
|
20
|
+
attr_reader :chef_version
|
21
|
+
attr_reader :validator_path
|
22
|
+
attr_reader :encrypted_data_bag_secret
|
23
|
+
attr_reader :server_url
|
24
|
+
attr_reader :validator_client
|
25
|
+
attr_reader :node_name
|
26
|
+
attr_reader :attributes
|
27
|
+
attr_reader :run_list
|
28
|
+
attr_reader :environment
|
29
|
+
attr_reader :hints
|
30
|
+
|
31
|
+
def initialize(options = {})
|
32
|
+
options = options.reverse_merge(
|
33
|
+
validator_client: "chef-validator",
|
34
|
+
attributes: Hash.new,
|
35
|
+
run_list: Array.new,
|
36
|
+
environment: "_default",
|
37
|
+
sudo: true,
|
38
|
+
hints: Hash.new,
|
39
|
+
chef_version: "latest"
|
40
|
+
)
|
41
|
+
options[:template] ||= default_template
|
42
|
+
self.class.validate_options(options)
|
43
|
+
|
44
|
+
@template_file = options[:template]
|
45
|
+
@bootstrap_proxy = options[:bootstrap_proxy]
|
46
|
+
@chef_version = options[:chef_version]
|
47
|
+
@sudo = options[:sudo]
|
48
|
+
@validator_path = options[:validator_path]
|
49
|
+
@encrypted_data_bag_secret = options[:encrypted_data_bag_secret]
|
50
|
+
@hints = options[:hints]
|
51
|
+
@server_url = options[:server_url]
|
52
|
+
@validator_client = options[:validator_client]
|
53
|
+
@node_name = options[:node_name]
|
54
|
+
@attributes = options[:attributes]
|
55
|
+
@run_list = options[:run_list]
|
56
|
+
@environment = options[:environment]
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [String]
|
60
|
+
def bootstrap_command
|
61
|
+
raise RuntimeError, "abstract function: must be implemented on includer"
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String]
|
65
|
+
def default_template
|
66
|
+
raise RuntimeError, "abstract function: must be implemented on includer"
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Pathname]
|
70
|
+
def templates_path
|
71
|
+
Ridley.root.join('bootstrappers')
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [String]
|
75
|
+
def first_boot
|
76
|
+
JSON.fast_generate(attributes.merge(run_list: run_list))
|
77
|
+
end
|
78
|
+
|
79
|
+
# The validation key to create a new client for the node
|
80
|
+
#
|
81
|
+
# @raise [Ridley::Errors::ValidatorNotFound]
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
def validation_key
|
85
|
+
IO.read(File.expand_path(validator_path)).chomp
|
86
|
+
rescue Errno::ENOENT
|
87
|
+
raise Errors::ValidatorNotFound, "Error bootstrapping: Validator not found at '#{validator_path}'"
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Erubis::Eruby]
|
91
|
+
def template
|
92
|
+
Erubis::Eruby.new(IO.read(template_file).chomp)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
Dir["#{File.dirname(__FILE__)}/bootstrap_context/*.rb"].sort.each do |path|
|
99
|
+
require_relative "bootstrap_context/#{File.basename(path, '.rb')}"
|
100
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Ridley
|
2
|
+
module BootstrapContext
|
3
|
+
# Represents a binding that will be evaluated as an ERB template. When bootstrapping
|
4
|
+
# nodes, an instance of this class represents the customizable and necessary configurations
|
5
|
+
# needed by the Host in order to install and connect to Chef. By default, this class will be used
|
6
|
+
# when SSH is the best way to connect to the node.
|
7
|
+
#
|
8
|
+
# @author Kyle Allan <kallan@riotgames.com>
|
9
|
+
class Unix < BootstrapContext::Base
|
10
|
+
attr_reader :sudo
|
11
|
+
|
12
|
+
# @option options [Boolean] :sudo (true)
|
13
|
+
# bootstrap with sudo (default: true)
|
14
|
+
def initialize(options = {})
|
15
|
+
options = options.reverse_merge(sudo: true)
|
16
|
+
@sudo = options[:sudo]
|
17
|
+
super(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String]
|
21
|
+
def boot_command
|
22
|
+
cmd = template.evaluate(self)
|
23
|
+
|
24
|
+
if sudo
|
25
|
+
cmd = "sudo #{cmd}"
|
26
|
+
end
|
27
|
+
|
28
|
+
cmd
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String]
|
32
|
+
def chef_config
|
33
|
+
body = <<-CONFIG
|
34
|
+
log_level :info
|
35
|
+
log_location STDOUT
|
36
|
+
chef_server_url "#{server_url}"
|
37
|
+
validation_client_name "#{validator_client}"
|
38
|
+
CONFIG
|
39
|
+
|
40
|
+
if node_name.present?
|
41
|
+
body << %Q{node_name "#{node_name}"\n}
|
42
|
+
else
|
43
|
+
body << "# Using default node name (fqdn)\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
if bootstrap_proxy.present?
|
47
|
+
body << %Q{http_proxy "#{bootstrap_proxy}"\n}
|
48
|
+
body << %Q{https_proxy "#{bootstrap_proxy}"\n}
|
49
|
+
end
|
50
|
+
|
51
|
+
if encrypted_data_bag_secret.present?
|
52
|
+
body << %Q{encrypted_data_bag_secret "#{bootstrap_directory}/encrypted_data_bag_secret"\n}
|
53
|
+
end
|
54
|
+
|
55
|
+
body
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [String]
|
59
|
+
def bootstrap_directory
|
60
|
+
"/etc/chef"
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String]
|
64
|
+
def chef_run
|
65
|
+
"chef-client -j #{bootstrap_directory}/first-boot.json -E #{environment}"
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
def default_template
|
70
|
+
templates_path.join('unix_omnibus.erb').to_s
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Ridley
|
2
|
+
module BootstrapContext
|
3
|
+
# Represents a binding that will be evaluated as an ERB template. When bootstrapping
|
4
|
+
# nodes, an instance of this class represents the customizable and necessary configurations
|
5
|
+
# needed by the Host in order to install and connect to Chef. By default, this class will be used
|
6
|
+
# when WinRM is the best way to connect to the node.
|
7
|
+
#
|
8
|
+
# @author Kyle Allan <kallan@riotgames.com>
|
9
|
+
#
|
10
|
+
# Windows Specific code written by Seth Chisamore (<schisamo@opscode.com>) in knife-windows
|
11
|
+
# https://github.com/opscode/knife-windows/blob/3b8886ddcfb928ca0958cd05b22f8c3d78bee86e/lib/chef/knife/bootstrap/windows-chef-client-msi.erb
|
12
|
+
# https://github.com/opscode/knife-windows/blob/78d38bbed358ac20107fc2b5b427f4b5e52e5cb2/lib/chef/knife/core/windows_bootstrap_context.rb
|
13
|
+
class Windows < BootstrapContext::Base
|
14
|
+
# @return [String]
|
15
|
+
def boot_command
|
16
|
+
template.evaluate(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
def chef_config
|
21
|
+
body = <<-CONFIG
|
22
|
+
log_level :info
|
23
|
+
log_location STDOUT
|
24
|
+
chef_server_url "#{server_url}"
|
25
|
+
validation_client_name "#{validator_client}"
|
26
|
+
CONFIG
|
27
|
+
|
28
|
+
if node_name.present?
|
29
|
+
body << %Q{node_name "#{node_name}"\n}
|
30
|
+
else
|
31
|
+
body << "# Using default node name (fqdn)\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
if bootstrap_proxy.present?
|
35
|
+
body << %Q{http_proxy "#{bootstrap_proxy}"\n}
|
36
|
+
body << %Q{https_proxy "#{bootstrap_proxy}"\n}
|
37
|
+
end
|
38
|
+
|
39
|
+
if encrypted_data_bag_secret.present?
|
40
|
+
body << %Q{encrypted_data_bag_secret '#{bootstrap_directory}\\encrypted_data_bag_secret'\n}
|
41
|
+
end
|
42
|
+
|
43
|
+
escape_and_echo(body)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [String]
|
47
|
+
def bootstrap_directory
|
48
|
+
"C:\\chef"
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [String]
|
52
|
+
def validation_key
|
53
|
+
escape_and_echo(super)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def chef_run
|
58
|
+
"chef-client -j #{bootstrap_directory}\\first-boot.json -E #{environment}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String]
|
62
|
+
def default_template
|
63
|
+
templates_path.join('windows_omnibus.erb').to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [String]
|
67
|
+
def encrypted_data_bag_secret
|
68
|
+
return unless @encrypted_data_bag_secret
|
69
|
+
|
70
|
+
escape_and_echo(@encrypted_data_bag_secret)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Implements a Powershell script that attempts a simple
|
74
|
+
# 'wget' to download the Chef msi
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
def windows_wget_powershell
|
78
|
+
win_wget_ps = <<-WGET_PS
|
79
|
+
param(
|
80
|
+
[String] $remoteUrl,
|
81
|
+
[String] $localPath
|
82
|
+
)
|
83
|
+
|
84
|
+
$webClient = new-object System.Net.WebClient;
|
85
|
+
|
86
|
+
$webClient.DownloadFile($remoteUrl, $localPath);
|
87
|
+
WGET_PS
|
88
|
+
|
89
|
+
escape_and_echo(win_wget_ps)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [String]
|
93
|
+
def install_chef
|
94
|
+
'msiexec /qb /i "%LOCAL_DESTINATION_MSI_PATH%"'
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [String]
|
98
|
+
def first_boot
|
99
|
+
escape_and_echo(super)
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [String]
|
103
|
+
def set_path
|
104
|
+
"SET \"PATH=%PATH%;C:\\ruby\\bin;C:\\opscode\\chef\\bin;C:\\opscode\\chef\\embedded\\bin\"\n"
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [String]
|
108
|
+
def local_download_path
|
109
|
+
"%TEMP%\\chef-client-#{chef_version}.msi"
|
110
|
+
end
|
111
|
+
|
112
|
+
# escape WIN BATCH special chars
|
113
|
+
# and prefixes each line with an
|
114
|
+
# echo
|
115
|
+
def escape_and_echo(file_contents)
|
116
|
+
file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -144,14 +144,17 @@ module Ridley
|
|
144
144
|
# @option options [Hash] :attributes
|
145
145
|
# attributes of normal precedence to merge
|
146
146
|
#
|
147
|
-
# @return [Ridley::
|
147
|
+
# @return [Ridley::NodeObject]
|
148
148
|
def merge_data(options = {})
|
149
|
-
|
150
|
-
|
149
|
+
new_run_list = Array(options[:run_list])
|
150
|
+
new_attributes = options[:attributes]
|
151
|
+
|
152
|
+
unless new_run_list.empty?
|
153
|
+
self.run_list = self.run_list | new_run_list
|
151
154
|
end
|
152
155
|
|
153
|
-
unless
|
154
|
-
self.normal = self.normal.deep_merge(
|
156
|
+
unless new_attributes.nil?
|
157
|
+
self.normal = self.normal.deep_merge(new_attributes)
|
155
158
|
end
|
156
159
|
|
157
160
|
self
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
module Ridley
|
5
|
+
class ConnectorSupervisor < ::Celluloid::SupervisionGroup
|
6
|
+
# @param [Celluloid::Registry] registry
|
7
|
+
def initialize(registry)
|
8
|
+
super(registry)
|
9
|
+
supervise_as :ssh, HostConnector::SSH
|
10
|
+
supervise_as :winrm, HostConnector::WinRM
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class HostCommander
|
15
|
+
class << self
|
16
|
+
# Checks to see if the given port is open for TCP connections
|
17
|
+
# on the given host.
|
18
|
+
#
|
19
|
+
# @param [String] host
|
20
|
+
# the host to attempt to connect to
|
21
|
+
# @param [Fixnum] port
|
22
|
+
# the port to attempt to connect on
|
23
|
+
# @param [Float] timeout
|
24
|
+
# the number of seconds to wait (default: {PORT_CHECK_TIMEOUT})
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
def connector_port_open?(host, port, timeout = nil)
|
28
|
+
Timeout.timeout(timeout || PORT_CHECK_TIMEOUT) { TCPSocket.new(host, port).close; true }
|
29
|
+
rescue Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EADDRNOTAVAIL => ex
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
include Celluloid
|
35
|
+
include Ridley::Logging
|
36
|
+
|
37
|
+
PORT_CHECK_TIMEOUT = 3
|
38
|
+
|
39
|
+
finalizer :finalize_callback
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@connector_registry = Celluloid::Registry.new
|
43
|
+
@connector_supervisor = ConnectorSupervisor.new_link(@connector_registry)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Execute a shell command on a node
|
47
|
+
#
|
48
|
+
# @param [String] host
|
49
|
+
# the host to perform the action on
|
50
|
+
# @param [String] command
|
51
|
+
#
|
52
|
+
# @option options [Hash] :ssh
|
53
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on
|
54
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
55
|
+
# * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
|
56
|
+
# * :timeout (Float) timeout value for SSH bootstrap (5.0)
|
57
|
+
# * :sudo (Boolean) run as sudo
|
58
|
+
# @option options [Hash] :winrm
|
59
|
+
# * :user (String) a user that will login to each node and perform the bootstrap command on
|
60
|
+
# * :password (String) the password for the user that will perform the bootstrap (required)
|
61
|
+
# * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
|
62
|
+
#
|
63
|
+
# @return [HostConnector::Response]
|
64
|
+
def run(host, command, options = {})
|
65
|
+
execute(__method__, host, command, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Bootstrap a node
|
69
|
+
#
|
70
|
+
# @param [String] host
|
71
|
+
# the host to perform the action on
|
72
|
+
#
|
73
|
+
# @option options [Hash] :ssh
|
74
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on
|
75
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
76
|
+
# * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
|
77
|
+
# * :timeout (Float) timeout value for SSH bootstrap (5.0)
|
78
|
+
# * :sudo (Boolean) run as sudo
|
79
|
+
# @option options [Hash] :winrm
|
80
|
+
# * :user (String) a user that will login to each node and perform the bootstrap command on
|
81
|
+
# * :password (String) the password for the user that will perform the bootstrap (required)
|
82
|
+
# * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
|
83
|
+
#
|
84
|
+
# @return [HostConnector::Response]
|
85
|
+
def bootstrap(host, options = {})
|
86
|
+
execute(__method__, host, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Perform a chef client run on a node
|
90
|
+
#
|
91
|
+
# @param [String] host
|
92
|
+
# the host to perform the action on
|
93
|
+
#
|
94
|
+
# @option options [Hash] :ssh
|
95
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on
|
96
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
97
|
+
# * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
|
98
|
+
# * :timeout (Float) timeout value for SSH bootstrap (5.0)
|
99
|
+
# * :sudo (Boolean) run as sudo
|
100
|
+
# @option options [Hash] :winrm
|
101
|
+
# * :user (String) a user that will login to each node and perform the bootstrap command on
|
102
|
+
# * :password (String) the password for the user that will perform the bootstrap (required)
|
103
|
+
# * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
|
104
|
+
#
|
105
|
+
# @return [HostConnector::Response]
|
106
|
+
def chef_client(host, options = {})
|
107
|
+
execute(__method__, host, options)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Write your encrypted data bag secret on a node
|
111
|
+
#
|
112
|
+
# @param [String] host
|
113
|
+
# the host to perform the action on
|
114
|
+
# @param [String] secret
|
115
|
+
# your organization's encrypted data bag secret
|
116
|
+
#
|
117
|
+
# @option options [Hash] :ssh
|
118
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on
|
119
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
120
|
+
# * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
|
121
|
+
# * :timeout (Float) timeout value for SSH bootstrap (5.0)
|
122
|
+
# * :sudo (Boolean) run as sudo
|
123
|
+
# @option options [Hash] :winrm
|
124
|
+
# * :user (String) a user that will login to each node and perform the bootstrap command on
|
125
|
+
# * :password (String) the password for the user that will perform the bootstrap (required)
|
126
|
+
# * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
|
127
|
+
#
|
128
|
+
# @return [HostConnector::Response]
|
129
|
+
def put_secret(host, secret, options = {})
|
130
|
+
execute(__method__, host, secret, options)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Execute line(s) of Ruby code on a node using Chef's embedded Ruby
|
134
|
+
#
|
135
|
+
# @param [String] host
|
136
|
+
# the host to perform the action on
|
137
|
+
# @param [Array<String>] command_lines
|
138
|
+
# An Array of lines of the command to be executed
|
139
|
+
#
|
140
|
+
# @option options [Hash] :ssh
|
141
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on
|
142
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
143
|
+
# * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
|
144
|
+
# * :timeout (Float) timeout value for SSH bootstrap (5.0)
|
145
|
+
# * :sudo (Boolean) run as sudo
|
146
|
+
# @option options [Hash] :winrm
|
147
|
+
# * :user (String) a user that will login to each node and perform the bootstrap command on
|
148
|
+
# * :password (String) the password for the user that will perform the bootstrap (required)
|
149
|
+
# * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
|
150
|
+
#
|
151
|
+
# @return [HostConnector::Response]
|
152
|
+
def ruby_script(host, command_lines, options = {})
|
153
|
+
execute(__method__, host, command_lines, options)
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def execute(method, host, *args)
|
159
|
+
options = args.last.is_a?(Hash) ? args.pop : Hash.new
|
160
|
+
|
161
|
+
connector_for(host, options).send(method, host, *args, options)
|
162
|
+
rescue Errors::HostConnectionError => ex
|
163
|
+
abort(ex)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Finds and returns the best HostConnector for a given host
|
167
|
+
#
|
168
|
+
# @param [String] host
|
169
|
+
# the host to attempt to connect to
|
170
|
+
# @option options [Hash] :ssh
|
171
|
+
# * :port (Fixnum) the ssh port to connect on the node the bootstrap will be performed on (22)
|
172
|
+
# * :timeout (Float) [5.0] timeout value for testing SSH connection
|
173
|
+
# @option options [Hash] :winrm
|
174
|
+
# * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
|
175
|
+
# @param block [Proc]
|
176
|
+
# an optional block that is yielded the best HostConnector
|
177
|
+
#
|
178
|
+
# @return [Symbol]
|
179
|
+
def connector_for(host, options = {})
|
180
|
+
options = options.reverse_merge(ssh: Hash.new, winrm: Hash.new)
|
181
|
+
options[:ssh][:port] ||= HostConnector::SSH::DEFAULT_PORT
|
182
|
+
options[:winrm][:port] ||= HostConnector::WinRM::DEFAULT_PORT
|
183
|
+
|
184
|
+
if self.class.connector_port_open?(host, options[:winrm][:port])
|
185
|
+
options.delete(:ssh)
|
186
|
+
winrm
|
187
|
+
elsif self.class.connector_port_open?(host, options[:ssh][:port], options[:ssh][:timeout])
|
188
|
+
options.delete(:winrm)
|
189
|
+
ssh
|
190
|
+
else
|
191
|
+
raise Errors::HostConnectionError, "No connector ports open on '#{host}'"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def finalize_callback
|
196
|
+
@connector_supervisor.terminate if @connector_supervisor && @connector_supervisor.alive?
|
197
|
+
end
|
198
|
+
|
199
|
+
def ssh
|
200
|
+
@connector_registry[:ssh]
|
201
|
+
end
|
202
|
+
|
203
|
+
def winrm
|
204
|
+
@connector_registry[:winrm]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|