knife-cloud 1.0.0.rc.0
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 +15 -0
- data/.gitignore +33 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +11 -0
- data/CONTRIBUTING.md +5 -0
- data/Gemfile +9 -0
- data/LICENSE +201 -0
- data/README.md +420 -0
- data/Rakefile +35 -0
- data/knife-cloud.gemspec +27 -0
- data/lib/chef/knife/cloud/chefbootstrap/bootstrap_distribution.rb +31 -0
- data/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb +191 -0
- data/lib/chef/knife/cloud/chefbootstrap/bootstrap_protocol.rb +69 -0
- data/lib/chef/knife/cloud/chefbootstrap/bootstrapper.rb +78 -0
- data/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +179 -0
- data/lib/chef/knife/cloud/chefbootstrap/unix_distribution.rb +31 -0
- data/lib/chef/knife/cloud/chefbootstrap/windows_distribution.rb +32 -0
- data/lib/chef/knife/cloud/chefbootstrap/winrm_bootstrap_protocol.rb +85 -0
- data/lib/chef/knife/cloud/command.rb +101 -0
- data/lib/chef/knife/cloud/exceptions.rb +38 -0
- data/lib/chef/knife/cloud/fog/options.rb +29 -0
- data/lib/chef/knife/cloud/fog/service.rb +200 -0
- data/lib/chef/knife/cloud/helpers.rb +39 -0
- data/lib/chef/knife/cloud/list_resource_command.rb +97 -0
- data/lib/chef/knife/cloud/list_resource_options.rb +21 -0
- data/lib/chef/knife/cloud/server/create_command.rb +165 -0
- data/lib/chef/knife/cloud/server/create_options.rb +80 -0
- data/lib/chef/knife/cloud/server/delete_command.rb +68 -0
- data/lib/chef/knife/cloud/server/delete_options.rb +42 -0
- data/lib/chef/knife/cloud/server/list_command.rb +84 -0
- data/lib/chef/knife/cloud/server/list_options.rb +43 -0
- data/lib/chef/knife/cloud/server/options.rb +39 -0
- data/lib/chef/knife/cloud/server/show_command.rb +55 -0
- data/lib/chef/knife/cloud/server/show_options.rb +36 -0
- data/lib/chef/knife/cloud/service.rb +91 -0
- data/lib/knife-cloud/version.rb +6 -0
- data/lib/test/fixtures/knife.rb +9 -0
- data/lib/test/fixtures/validation.pem +27 -0
- data/lib/test/knife-utils/helper.rb +39 -0
- data/lib/test/knife-utils/knife_test_utils.rb +40 -0
- data/lib/test/knife-utils/matchers.rb +29 -0
- data/lib/test/knife-utils/test_bed.rb +56 -0
- data/lib/test/templates/chef-full-chef-zero.erb +67 -0
- data/lib/test/templates/windows-chef-client-msi.erb +231 -0
- data/lib/test/templates/windows-shell.erb +77 -0
- data/spec/resource_spec_helper.rb +49 -0
- data/spec/server_command_common_spec_helper.rb +48 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/shared_examples_for_command.rb +35 -0
- data/spec/support/shared_examples_for_servercreatecommand.rb +144 -0
- data/spec/support/shared_examples_for_serverdeletecommand.rb +77 -0
- data/spec/support/shared_examples_for_service.rb +85 -0
- data/spec/unit/bootstrap_protocol_spec.rb +70 -0
- data/spec/unit/bootstrapper_spec.rb +171 -0
- data/spec/unit/cloud_command_spec.rb +35 -0
- data/spec/unit/command_spec.rb +49 -0
- data/spec/unit/fog_service_spec.rb +138 -0
- data/spec/unit/list_resource_command_spec.rb +136 -0
- data/spec/unit/server_create_command_spec.rb +198 -0
- data/spec/unit/server_delete_command_spec.rb +25 -0
- data/spec/unit/server_list_command_spec.rb +119 -0
- data/spec/unit/server_show_command_spec.rb +64 -0
- data/spec/unit/service_spec.rb +46 -0
- data/spec/unit/ssh_bootstrap_protocol_spec.rb +116 -0
- data/spec/unit/unix_distribution_spec.rb +37 -0
- data/spec/unit/windows_distribution_spec.rb +37 -0
- data/spec/unit/winrm_bootstrap_protocol_spec.rb +106 -0
- metadata +248 -0
@@ -0,0 +1,191 @@
|
|
1
|
+
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
require 'chef/knife/winrm_base'
|
19
|
+
require 'chef/knife/core/bootstrap_context'
|
20
|
+
require 'net/ssh/multi'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
class Cloud
|
25
|
+
# Ideally chef/knife/bootstap should expose this as module.
|
26
|
+
module BootstrapOptions
|
27
|
+
|
28
|
+
def self.included(includer)
|
29
|
+
includer.class_eval do
|
30
|
+
|
31
|
+
deps do
|
32
|
+
require 'chef/json_compat'
|
33
|
+
require 'tempfile'
|
34
|
+
require 'highline'
|
35
|
+
require 'net/ssh'
|
36
|
+
require 'chef/knife/ssh'
|
37
|
+
Chef::Knife::Ssh.load_deps
|
38
|
+
end
|
39
|
+
|
40
|
+
include Chef::Knife::WinrmBase
|
41
|
+
|
42
|
+
option :ssh_user,
|
43
|
+
:short => "-x USERNAME",
|
44
|
+
:long => "--ssh-user USERNAME",
|
45
|
+
:description => "The ssh username",
|
46
|
+
:default => "root"
|
47
|
+
|
48
|
+
option :ssh_password,
|
49
|
+
:short => "-P PASSWORD",
|
50
|
+
:long => "--ssh-password PASSWORD",
|
51
|
+
:description => "The ssh password"
|
52
|
+
|
53
|
+
option :ssh_port,
|
54
|
+
:short => "-p PORT",
|
55
|
+
:long => "--ssh-port PORT",
|
56
|
+
:description => "The ssh port",
|
57
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key },
|
58
|
+
:default => "22"
|
59
|
+
|
60
|
+
option :ssh_gateway,
|
61
|
+
:long => "--ssh-gateway GATEWAY",
|
62
|
+
:description => "The ssh gateway server. Any proxies configured in your ssh config are automatically used by default.",
|
63
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
|
64
|
+
|
65
|
+
option :ssh_gateway_identity,
|
66
|
+
:long => "--ssh-gateway-identity IDENTITY_FILE",
|
67
|
+
:description => "The private key for ssh gateway server",
|
68
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway_identity] = key }
|
69
|
+
|
70
|
+
option :forward_agent,
|
71
|
+
:long => "--forward-agent",
|
72
|
+
:description => "Enable SSH agent forwarding",
|
73
|
+
:boolean => true
|
74
|
+
|
75
|
+
option :identity_file,
|
76
|
+
:short => "-i IDENTITY_FILE",
|
77
|
+
:long => "--identity-file IDENTITY_FILE",
|
78
|
+
:description => "The SSH identity file used for authentication"
|
79
|
+
|
80
|
+
option :chef_node_name,
|
81
|
+
:short => "-N NAME",
|
82
|
+
:long => "--node-name NAME",
|
83
|
+
:description => "The Chef node name for your new node"
|
84
|
+
|
85
|
+
option :prerelease,
|
86
|
+
:long => "--prerelease",
|
87
|
+
:description => "Install the pre-release chef gems"
|
88
|
+
|
89
|
+
option :bootstrap_version,
|
90
|
+
:long => "--bootstrap-version VERSION",
|
91
|
+
:description => "The version of Chef to install",
|
92
|
+
:proc => lambda { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
93
|
+
|
94
|
+
option :bootstrap_proxy,
|
95
|
+
:long => "--bootstrap-proxy PROXY_URL",
|
96
|
+
:description => "The proxy server for the node being bootstrapped",
|
97
|
+
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
98
|
+
|
99
|
+
option :bootstrap_no_proxy,
|
100
|
+
:long => "--bootstrap-no-proxy [NO_PROXY_URL|NO_PROXY_IP]",
|
101
|
+
:description => "Do not proxy locations for the node being bootstrapped; this option is used internally by Opscode",
|
102
|
+
:proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }
|
103
|
+
|
104
|
+
option :distro,
|
105
|
+
:short => "-d DISTRO",
|
106
|
+
:long => "--distro DISTRO",
|
107
|
+
:description => "Bootstrap a distro using a template"
|
108
|
+
|
109
|
+
option :use_sudo,
|
110
|
+
:long => "--sudo",
|
111
|
+
:description => "Execute the bootstrap via sudo",
|
112
|
+
:boolean => true
|
113
|
+
|
114
|
+
option :use_sudo_password,
|
115
|
+
:long => "--use-sudo-password",
|
116
|
+
:description => "Execute the bootstrap via sudo with password",
|
117
|
+
:boolean => false
|
118
|
+
|
119
|
+
option :template_file,
|
120
|
+
:long => "--template-file TEMPLATE",
|
121
|
+
:description => "Full path to location of template to use",
|
122
|
+
:proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
|
123
|
+
:default => false
|
124
|
+
|
125
|
+
option :run_list,
|
126
|
+
:short => "-r RUN_LIST",
|
127
|
+
:long => "--run-list RUN_LIST",
|
128
|
+
:description => "Comma separated list of roles/recipes to apply",
|
129
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
130
|
+
:default => []
|
131
|
+
|
132
|
+
option :first_boot_attributes,
|
133
|
+
:short => "-j JSON_ATTRIBS",
|
134
|
+
:long => "--json-attributes",
|
135
|
+
:description => "A JSON string to be added to the first run of chef-client",
|
136
|
+
:proc => lambda { |o| JSON.parse(o) },
|
137
|
+
:default => {}
|
138
|
+
|
139
|
+
option :host_key_verify,
|
140
|
+
:long => "--[no-]host-key-verify",
|
141
|
+
:description => "Verify host key, enabled by default.",
|
142
|
+
:boolean => true,
|
143
|
+
:default => true
|
144
|
+
|
145
|
+
option :hint,
|
146
|
+
:long => "--hint HINT_NAME[=HINT_FILE]",
|
147
|
+
:description => "Specify Ohai Hint to be set on the bootstrap target. Use multiple --hint options to specify multiple hints.",
|
148
|
+
:proc => Proc.new { |h|
|
149
|
+
Chef::Config[:knife][:hints] ||= Hash.new
|
150
|
+
name, path = h.split("=")
|
151
|
+
Chef::Config[:knife][:hints][name] = path ? JSON.parse(::File.read(path)) : Hash.new }
|
152
|
+
|
153
|
+
option :secret,
|
154
|
+
:short => "-s SECRET",
|
155
|
+
:long => "--secret ",
|
156
|
+
:description => "The secret key to use to encrypt data bag item values"
|
157
|
+
|
158
|
+
option :secret_file,
|
159
|
+
:long => "--secret-file SECRET_FILE",
|
160
|
+
:description => "A file containing the secret key to use to encrypt data bag item values"
|
161
|
+
|
162
|
+
option :bootstrap_url,
|
163
|
+
:long => "--bootstrap-url URL",
|
164
|
+
:description => "URL to a custom installation script",
|
165
|
+
:proc => Proc.new { |u| Chef::Config[:knife][:bootstrap_url] = u }
|
166
|
+
|
167
|
+
option :bootstrap_install_command,
|
168
|
+
:long => "--bootstrap-install-command COMMANDS",
|
169
|
+
:description => "Custom command to install chef-client",
|
170
|
+
:proc => Proc.new { |ic| Chef::Config[:knife][:bootstrap_install_command] = ic }
|
171
|
+
|
172
|
+
option :bootstrap_wget_options,
|
173
|
+
:long => "--bootstrap-wget-options OPTIONS",
|
174
|
+
:description => "Add options to wget when installing chef-client",
|
175
|
+
:proc => Proc.new { |wo| Chef::Config[:knife][:bootstrap_wget_options] = wo }
|
176
|
+
|
177
|
+
option :bootstrap_curl_options,
|
178
|
+
:long => "--bootstrap-curl-options OPTIONS",
|
179
|
+
:description => "Add options to curl when install chef-client",
|
180
|
+
:proc => Proc.new { |co| Chef::Config[:knife][:bootstrap_curl_options] = co }
|
181
|
+
|
182
|
+
option :auth_timeout,
|
183
|
+
:long => "--auth-timeout MINUTES",
|
184
|
+
:description => "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 25 minutes.",
|
185
|
+
:default => 25
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end # module ends
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/knife/core/ui'
|
21
|
+
require 'chef/knife/cloud/helpers'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Knife
|
25
|
+
class Cloud
|
26
|
+
class BootstrapProtocol
|
27
|
+
include Chef::Knife::Cloud::Helpers
|
28
|
+
|
29
|
+
attr_accessor :bootstrap, :ui, :initial_sleep_delay
|
30
|
+
attr_reader :config
|
31
|
+
|
32
|
+
def initialize(config)
|
33
|
+
@config = config
|
34
|
+
@ui ||= Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
|
35
|
+
end
|
36
|
+
|
37
|
+
def wait_for_server_ready
|
38
|
+
raise Chef::Exceptions::Override, "You must override wait_for_server_ready in #{self.to_s}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_bootstrap_command
|
42
|
+
wait_for_server_ready
|
43
|
+
init_bootstrap_options
|
44
|
+
@bootstrap.run
|
45
|
+
end
|
46
|
+
|
47
|
+
def init_bootstrap_options
|
48
|
+
# set the command bootstrap options.
|
49
|
+
bootstrap.name_args = locate_config_value(:bootstrap_ip_address)
|
50
|
+
bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name)
|
51
|
+
bootstrap.config[:run_list] = locate_config_value(:run_list)
|
52
|
+
bootstrap.config[:prerelease] = locate_config_value(:prerelease)
|
53
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
54
|
+
bootstrap.config[:distro] = locate_config_value(:distro)
|
55
|
+
bootstrap.config[:bootstrap_proxy] = locate_config_value(:bootstrap_proxy)
|
56
|
+
bootstrap.config[:environment] = locate_config_value(:environment)
|
57
|
+
# see chef/knife/bootstrap.rb #warn_chef_config_secret_key.
|
58
|
+
bootstrap.config[:encrypted_data_bag_secret] = locate_config_value(:encrypted_data_bag_secret)
|
59
|
+
bootstrap.config[:encrypted_data_bag_secret_file] = locate_config_value(:encrypted_data_bag_secret_file)
|
60
|
+
bootstrap.config[:first_boot_attributes] = locate_config_value(:first_boot_attributes)
|
61
|
+
bootstrap.config[:secret] = locate_config_value(:secret)
|
62
|
+
bootstrap.config[:secret_file] = locate_config_value(:secret_file)
|
63
|
+
bootstrap.config[:template_file] = locate_config_value(:template_file)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/knife/core/ui'
|
21
|
+
require 'chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol'
|
22
|
+
require 'chef/knife/cloud/chefbootstrap/winrm_bootstrap_protocol'
|
23
|
+
require 'chef/knife/cloud/chefbootstrap/windows_distribution'
|
24
|
+
require 'chef/knife/cloud/chefbootstrap/unix_distribution'
|
25
|
+
require 'chef/knife/cloud/exceptions'
|
26
|
+
|
27
|
+
class Chef
|
28
|
+
class Knife
|
29
|
+
class Cloud
|
30
|
+
class Bootstrapper
|
31
|
+
|
32
|
+
def initialize(config)
|
33
|
+
@config = config
|
34
|
+
@ui ||= Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
|
35
|
+
end
|
36
|
+
|
37
|
+
def bootstrap
|
38
|
+
# uses BootstrapDistribution and BootstrapProtocol to perform bootstrap
|
39
|
+
@protocol = create_bootstrap_protocol
|
40
|
+
@distribution = create_bootstrap_distribution
|
41
|
+
begin
|
42
|
+
@protocol.send_bootstrap_command
|
43
|
+
rescue Net::SSH::AuthenticationFailed => e
|
44
|
+
error_message = "Authentication Failed during bootstrapping. #{e.message}."
|
45
|
+
raise CloudExceptions::BootstrapError, error_message
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_bootstrap_protocol
|
50
|
+
if @config[:bootstrap_protocol].nil? or @config[:bootstrap_protocol] == 'ssh'
|
51
|
+
SshBootstrapProtocol.new(@config)
|
52
|
+
elsif @config[:bootstrap_protocol] == 'winrm'
|
53
|
+
WinrmBootstrapProtocol.new(@config)
|
54
|
+
else
|
55
|
+
# raise an exception, invalid bootstrap protocol.
|
56
|
+
error_message = "Invalid bootstrap protocol."
|
57
|
+
ui.fatal(error_message)
|
58
|
+
raise CloudExceptions::BootstrapError, error_message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_bootstrap_distribution
|
63
|
+
if @config[:image_os_type] == 'windows'
|
64
|
+
Chef::Knife::Cloud::WindowsDistribution.new(@config)
|
65
|
+
elsif @config[:image_os_type] == 'linux'
|
66
|
+
Chef::Knife::Cloud::UnixDistribution.new(@config)
|
67
|
+
else
|
68
|
+
# raise an exception, invalid bootstrap distribution.
|
69
|
+
error_message = "Invalid bootstrap distribution. image_os_type should be either windows or linux."
|
70
|
+
ui.fatal(error_message)
|
71
|
+
raise CloudExceptions::BootstrapError, error_message
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/knife/cloud/chefbootstrap/bootstrap_protocol'
|
21
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
22
|
+
require 'chef/knife/bootstrap'
|
23
|
+
|
24
|
+
|
25
|
+
class Chef
|
26
|
+
class Knife
|
27
|
+
class Cloud
|
28
|
+
class SshBootstrapProtocol < BootstrapProtocol
|
29
|
+
|
30
|
+
def initialize(config)
|
31
|
+
@bootstrap = (config[:image_os_type] == 'linux') ? Chef::Knife::Bootstrap.new : Chef::Knife::BootstrapWindowsSsh.new
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def init_bootstrap_options
|
36
|
+
bootstrap.config[:ssh_user] = @config[:ssh_user]
|
37
|
+
bootstrap.config[:ssh_password] = @config[:ssh_password]
|
38
|
+
bootstrap.config[:ssh_port] = locate_config_value(:ssh_port)
|
39
|
+
bootstrap.config[:identity_file] = @config[:identity_file]
|
40
|
+
bootstrap.config[:host_key_verify] = @config[:host_key_verify]
|
41
|
+
bootstrap.config[:use_sudo] = true unless @config[:ssh_user] == 'root'
|
42
|
+
bootstrap.config[:template_file] = @config[:template_file]
|
43
|
+
bootstrap.config[:ssh_gateway] = locate_config_value(:ssh_gateway)
|
44
|
+
bootstrap.config[:forward_agent] = locate_config_value(:forward_agent)
|
45
|
+
bootstrap.config[:use_sudo_password] = locate_config_value(:use_sudo_password)
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def wait_for_server_ready
|
50
|
+
print "\n#{ui.color("Waiting for sshd to host (#{@config[:bootstrap_ip_address]})", :magenta)}"
|
51
|
+
|
52
|
+
ssh_gateway = get_ssh_gateway_for(@config[:bootstrap_ip_address])
|
53
|
+
|
54
|
+
# The ssh_gateway & subnet_id are currently supported only in EC2.
|
55
|
+
if ssh_gateway
|
56
|
+
print(".") until tunnel_test_ssh(ssh_gateway, @config[:bootstrap_ip_address]) {
|
57
|
+
@initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10
|
58
|
+
sleep @initial_sleep_delay
|
59
|
+
puts("done")
|
60
|
+
}
|
61
|
+
else
|
62
|
+
print(".") until tcp_test_ssh(@config[:bootstrap_ip_address], locate_config_value(:ssh_port)) {
|
63
|
+
@initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10
|
64
|
+
sleep @initial_sleep_delay
|
65
|
+
puts("done")
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_ssh_gateway_for(hostname)
|
71
|
+
if locate_config_value(:ssh_gateway)
|
72
|
+
# The ssh_gateway specified in the knife config (if any) takes
|
73
|
+
# precedence over anything in the SSH configuration
|
74
|
+
Chef::Log.debug("Using ssh gateway #{locate_config_value(:ssh_gateway)} from knife config")
|
75
|
+
locate_config_value(:ssh_gateway)
|
76
|
+
else
|
77
|
+
# Next, check if the SSH configuration has a ProxyCommand
|
78
|
+
# directive for this host. If there is one, parse out the
|
79
|
+
# host from the proxy command
|
80
|
+
ssh_proxy = Net::SSH::Config.for(hostname)[:proxy]
|
81
|
+
if ssh_proxy.respond_to?(:command_line_template)
|
82
|
+
# ssh gateway_hostname nc %h %p
|
83
|
+
proxy_pattern = /ssh\s+(\S+)\s+nc/
|
84
|
+
matchdata = proxy_pattern.match(ssh_proxy.command_line_template)
|
85
|
+
if matchdata.nil?
|
86
|
+
Chef::Log.debug("Unable to determine ssh gateway for '#{hostname}' from ssh config template: #{ssh_proxy.command_line_template}")
|
87
|
+
nil
|
88
|
+
else
|
89
|
+
# Return hostname extracted from command line template
|
90
|
+
Chef::Log.debug("Using ssh gateway #{matchdata[1]} from ssh config")
|
91
|
+
matchdata[1]
|
92
|
+
end
|
93
|
+
else
|
94
|
+
# Return nil if we cannot find an ssh_gateway
|
95
|
+
Chef::Log.debug("No ssh gateway found, making a direct connection")
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def tcp_test_ssh(hostname, ssh_port)
|
102
|
+
begin
|
103
|
+
tcp_socket = TCPSocket.new(hostname, ssh_port)
|
104
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
105
|
+
if readable
|
106
|
+
ssh_banner = tcp_socket.gets
|
107
|
+
if ssh_banner.nil? or ssh_banner.empty?
|
108
|
+
false
|
109
|
+
else
|
110
|
+
Chef::Log.debug("ssh accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
|
111
|
+
yield
|
112
|
+
true
|
113
|
+
end
|
114
|
+
else
|
115
|
+
false
|
116
|
+
end
|
117
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
118
|
+
Chef::Log.debug("ssh timed out: #{hostname}")
|
119
|
+
false
|
120
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
121
|
+
Chef::Log.debug("ssh failed to connect: #{hostname}")
|
122
|
+
sleep 2
|
123
|
+
false
|
124
|
+
# This happens on some mobile phone networks
|
125
|
+
rescue Errno::ECONNRESET
|
126
|
+
Chef::Log.debug("ssh reset its connection: #{hostname}")
|
127
|
+
sleep 2
|
128
|
+
false
|
129
|
+
ensure
|
130
|
+
tcp_socket && tcp_socket.close
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def tunnel_test_ssh(ssh_gateway, hostname, &block)
|
135
|
+
begin
|
136
|
+
status = false
|
137
|
+
gateway = configure_ssh_gateway(ssh_gateway)
|
138
|
+
gateway.open(hostname, locate_config_value(:ssh_port)) do |local_tunnel_port|
|
139
|
+
status = tcp_test_ssh('localhost', local_tunnel_port, &block)
|
140
|
+
end
|
141
|
+
status
|
142
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
143
|
+
sleep 2
|
144
|
+
false
|
145
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
146
|
+
false
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def configure_ssh_gateway(ssh_gateway)
|
151
|
+
gw_host, gw_user = ssh_gateway.split('@').reverse
|
152
|
+
gw_host, gw_port = gw_host.split(':')
|
153
|
+
gateway_options = { :port => gw_port || 22 }
|
154
|
+
|
155
|
+
# Load the SSH config for the SSH gateway host.
|
156
|
+
# Set the gateway user if it was not part of the
|
157
|
+
# SSH gateway string, and use any configured
|
158
|
+
# SSH keys.
|
159
|
+
ssh_gateway_config = Net::SSH::Config.for(gw_host)
|
160
|
+
gw_user ||= ssh_gateway_config[:user]
|
161
|
+
|
162
|
+
# Always use the gateway keys from the SSH Config
|
163
|
+
gateway_keys = ssh_gateway_config[:keys]
|
164
|
+
|
165
|
+
# Use the keys specificed on the command line if available (overrides SSH Config)
|
166
|
+
if locate_config_value(:ssh_gateway_identity)
|
167
|
+
gateway_keys = Array(locate_config_value(:ssh_gateway_identity))
|
168
|
+
end
|
169
|
+
|
170
|
+
unless gateway_keys.nil?
|
171
|
+
gateway_options[:keys] = gateway_keys
|
172
|
+
end
|
173
|
+
|
174
|
+
Net::SSH::Gateway.new(gw_host, gw_user, gateway_options)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
require 'chef/knife/cloud/chefbootstrap/bootstrap_distribution'
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class Cloud
|
22
|
+
class UnixDistribution < BootstrapDistribution
|
23
|
+
|
24
|
+
def initialize(config)
|
25
|
+
super
|
26
|
+
config[:distro] = config[:distro] || "chef-full"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
require 'chef/knife/cloud/chefbootstrap/bootstrap_distribution'
|
19
|
+
require 'chef/knife/bootstrap_windows_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class Cloud
|
24
|
+
class WindowsDistribution < BootstrapDistribution
|
25
|
+
def initialize(config)
|
26
|
+
super
|
27
|
+
config[:distro] ||= "windows-chef-client-msi"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (c) 2013 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/knife/cloud/chefbootstrap/bootstrap_protocol'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
class Cloud
|
25
|
+
class WinrmBootstrapProtocol < BootstrapProtocol
|
26
|
+
|
27
|
+
def initialize(config)
|
28
|
+
load_winrm_deps
|
29
|
+
@bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_winrm_deps
|
34
|
+
require 'winrm'
|
35
|
+
require 'em-winrm'
|
36
|
+
require 'chef/knife/bootstrap_windows_winrm'
|
37
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
38
|
+
require 'chef/knife/winrm'
|
39
|
+
end
|
40
|
+
|
41
|
+
def init_bootstrap_options
|
42
|
+
bootstrap.config[:winrm_user] = @config[:winrm_user] || 'Administrator'
|
43
|
+
bootstrap.config[:winrm_password] = @config[:winrm_password]
|
44
|
+
bootstrap.config[:winrm_transport] = @config[:winrm_transport]
|
45
|
+
bootstrap.config[:winrm_port] = @config[:winrm_port]
|
46
|
+
bootstrap.config[:auth_timeout] = @config[:auth_timeout]
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
def wait_for_server_ready
|
51
|
+
print "\n#{ui.color("Waiting for winrm to host (#{@config[:bootstrap_ip_address]})", :magenta)}"
|
52
|
+
print(".") until tcp_test_winrm(@config[:bootstrap_ip_address], @config[:winrm_port]){
|
53
|
+
sleep @initial_sleep_delay ||= 10
|
54
|
+
puts("done")
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def tcp_test_winrm(hostname, port)
|
59
|
+
tcp_socket = TCPSocket.new(hostname, port)
|
60
|
+
return true
|
61
|
+
rescue SocketError
|
62
|
+
sleep 2
|
63
|
+
false
|
64
|
+
rescue Errno::ETIMEDOUT
|
65
|
+
false
|
66
|
+
rescue Errno::EPERM
|
67
|
+
false
|
68
|
+
rescue Errno::ECONNREFUSED
|
69
|
+
sleep 2
|
70
|
+
false
|
71
|
+
rescue Errno::EHOSTUNREACH
|
72
|
+
sleep 2
|
73
|
+
false
|
74
|
+
rescue Errno::ENETUNREACH
|
75
|
+
sleep 2
|
76
|
+
false
|
77
|
+
ensure
|
78
|
+
tcp_socket && tcp_socket.close
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|