knife-cloud 1.0.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +33 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +11 -0
  5. data/CONTRIBUTING.md +5 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE +201 -0
  8. data/README.md +420 -0
  9. data/Rakefile +35 -0
  10. data/knife-cloud.gemspec +27 -0
  11. data/lib/chef/knife/cloud/chefbootstrap/bootstrap_distribution.rb +31 -0
  12. data/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb +191 -0
  13. data/lib/chef/knife/cloud/chefbootstrap/bootstrap_protocol.rb +69 -0
  14. data/lib/chef/knife/cloud/chefbootstrap/bootstrapper.rb +78 -0
  15. data/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +179 -0
  16. data/lib/chef/knife/cloud/chefbootstrap/unix_distribution.rb +31 -0
  17. data/lib/chef/knife/cloud/chefbootstrap/windows_distribution.rb +32 -0
  18. data/lib/chef/knife/cloud/chefbootstrap/winrm_bootstrap_protocol.rb +85 -0
  19. data/lib/chef/knife/cloud/command.rb +101 -0
  20. data/lib/chef/knife/cloud/exceptions.rb +38 -0
  21. data/lib/chef/knife/cloud/fog/options.rb +29 -0
  22. data/lib/chef/knife/cloud/fog/service.rb +200 -0
  23. data/lib/chef/knife/cloud/helpers.rb +39 -0
  24. data/lib/chef/knife/cloud/list_resource_command.rb +97 -0
  25. data/lib/chef/knife/cloud/list_resource_options.rb +21 -0
  26. data/lib/chef/knife/cloud/server/create_command.rb +165 -0
  27. data/lib/chef/knife/cloud/server/create_options.rb +80 -0
  28. data/lib/chef/knife/cloud/server/delete_command.rb +68 -0
  29. data/lib/chef/knife/cloud/server/delete_options.rb +42 -0
  30. data/lib/chef/knife/cloud/server/list_command.rb +84 -0
  31. data/lib/chef/knife/cloud/server/list_options.rb +43 -0
  32. data/lib/chef/knife/cloud/server/options.rb +39 -0
  33. data/lib/chef/knife/cloud/server/show_command.rb +55 -0
  34. data/lib/chef/knife/cloud/server/show_options.rb +36 -0
  35. data/lib/chef/knife/cloud/service.rb +91 -0
  36. data/lib/knife-cloud/version.rb +6 -0
  37. data/lib/test/fixtures/knife.rb +9 -0
  38. data/lib/test/fixtures/validation.pem +27 -0
  39. data/lib/test/knife-utils/helper.rb +39 -0
  40. data/lib/test/knife-utils/knife_test_utils.rb +40 -0
  41. data/lib/test/knife-utils/matchers.rb +29 -0
  42. data/lib/test/knife-utils/test_bed.rb +56 -0
  43. data/lib/test/templates/chef-full-chef-zero.erb +67 -0
  44. data/lib/test/templates/windows-chef-client-msi.erb +231 -0
  45. data/lib/test/templates/windows-shell.erb +77 -0
  46. data/spec/resource_spec_helper.rb +49 -0
  47. data/spec/server_command_common_spec_helper.rb +48 -0
  48. data/spec/spec_helper.rb +25 -0
  49. data/spec/support/shared_examples_for_command.rb +35 -0
  50. data/spec/support/shared_examples_for_servercreatecommand.rb +144 -0
  51. data/spec/support/shared_examples_for_serverdeletecommand.rb +77 -0
  52. data/spec/support/shared_examples_for_service.rb +85 -0
  53. data/spec/unit/bootstrap_protocol_spec.rb +70 -0
  54. data/spec/unit/bootstrapper_spec.rb +171 -0
  55. data/spec/unit/cloud_command_spec.rb +35 -0
  56. data/spec/unit/command_spec.rb +49 -0
  57. data/spec/unit/fog_service_spec.rb +138 -0
  58. data/spec/unit/list_resource_command_spec.rb +136 -0
  59. data/spec/unit/server_create_command_spec.rb +198 -0
  60. data/spec/unit/server_delete_command_spec.rb +25 -0
  61. data/spec/unit/server_list_command_spec.rb +119 -0
  62. data/spec/unit/server_show_command_spec.rb +64 -0
  63. data/spec/unit/service_spec.rb +46 -0
  64. data/spec/unit/ssh_bootstrap_protocol_spec.rb +116 -0
  65. data/spec/unit/unix_distribution_spec.rb +37 -0
  66. data/spec/unit/windows_distribution_spec.rb +37 -0
  67. data/spec/unit/winrm_bootstrap_protocol_spec.rb +106 -0
  68. 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
+