knife-cloud 1.2.1 → 1.2.3
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 +5 -5
- data/LICENSE +1 -1
- data/lib/chef/knife/cloud/chefbootstrap/bootstrap_distribution.rb +2 -2
- data/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb +115 -133
- data/lib/chef/knife/cloud/chefbootstrap/bootstrap_protocol.rb +6 -6
- data/lib/chef/knife/cloud/chefbootstrap/bootstrapper.rb +11 -12
- data/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +49 -54
- data/lib/chef/knife/cloud/chefbootstrap/unix_distribution.rb +3 -3
- data/lib/chef/knife/cloud/chefbootstrap/windows_distribution.rb +3 -3
- data/lib/chef/knife/cloud/chefbootstrap/winrm_bootstrap_protocol.rb +11 -12
- data/lib/chef/knife/cloud/command.rb +24 -27
- data/lib/chef/knife/cloud/exceptions.rb +1 -2
- data/lib/chef/knife/cloud/fog/options.rb +8 -8
- data/lib/chef/knife/cloud/fog/service.rb +54 -60
- data/lib/chef/knife/cloud/helpers.rb +2 -3
- data/lib/chef/knife/cloud/list_resource_command.rb +6 -7
- data/lib/chef/knife/cloud/list_resource_options.rb +5 -5
- data/lib/chef/knife/cloud/server/create_command.rb +30 -35
- data/lib/chef/knife/cloud/server/create_options.rb +33 -34
- data/lib/chef/knife/cloud/server/delete_command.rb +12 -15
- data/lib/chef/knife/cloud/server/delete_options.rb +7 -8
- data/lib/chef/knife/cloud/server/list_command.rb +22 -22
- data/lib/chef/knife/cloud/server/list_options.rb +9 -10
- data/lib/chef/knife/cloud/server/options.rb +7 -7
- data/lib/chef/knife/cloud/server/show_command.rb +5 -5
- data/lib/chef/knife/cloud/server/show_options.rb +5 -6
- data/lib/chef/knife/cloud/service.rb +12 -13
- data/lib/knife-cloud/version.rb +2 -2
- data/lib/test/fixtures/knife.rb +3 -3
- data/lib/test/fixtures/validation.pem +27 -0
- data/lib/test/knife-utils/helper.rb +11 -11
- data/lib/test/knife-utils/knife_test_utils.rb +4 -4
- data/lib/test/knife-utils/matchers.rb +3 -3
- data/lib/test/knife-utils/test_bed.rb +38 -38
- data/lib/test/templates/windows-chef-client-msi.erb +3 -4
- data/lib/test/templates/windows-shell.erb +2 -2
- metadata +12 -152
- data/.gitignore +0 -33
- data/.travis.yml +0 -6
- data/CHANGELOG.md +0 -133
- data/CONTRIBUTING.md +0 -5
- data/Gemfile +0 -9
- data/README.md +0 -421
- data/Rakefile +0 -35
- data/ci.gemfile +0 -18
- data/knife-cloud.gemspec +0 -26
- data/spec/resource_spec_helper.rb +0 -49
- data/spec/server_command_common_spec_helper.rb +0 -48
- data/spec/spec_helper.rb +0 -25
- data/spec/support/shared_examples_for_command.rb +0 -35
- data/spec/support/shared_examples_for_servercreatecommand.rb +0 -144
- data/spec/support/shared_examples_for_serverdeletecommand.rb +0 -77
- data/spec/support/shared_examples_for_service.rb +0 -85
- data/spec/unit/bootstrap_protocol_spec.rb +0 -98
- data/spec/unit/bootstrapper_spec.rb +0 -171
- data/spec/unit/cloud_command_spec.rb +0 -35
- data/spec/unit/command_spec.rb +0 -49
- data/spec/unit/fog_service_spec.rb +0 -163
- data/spec/unit/list_resource_command_spec.rb +0 -140
- data/spec/unit/server_create_command_spec.rb +0 -198
- data/spec/unit/server_delete_command_spec.rb +0 -25
- data/spec/unit/server_list_command_spec.rb +0 -119
- data/spec/unit/server_show_command_spec.rb +0 -64
- data/spec/unit/service_spec.rb +0 -46
- data/spec/unit/ssh_bootstrap_protocol_spec.rb +0 -116
- data/spec/unit/unix_distribution_spec.rb +0 -37
- data/spec/unit/windows_distribution_spec.rb +0 -37
- data/spec/unit/winrm_bootstrap_protocol_spec.rb +0 -108
@@ -1,7 +1,7 @@
|
|
1
1
|
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
2
|
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
3
|
#
|
4
|
-
# Copyright:: Copyright (c) 2013
|
4
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -17,10 +17,9 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
|
20
|
+
require "chef/knife/cloud/chefbootstrap/bootstrap_protocol"
|
21
|
+
require "chef/knife/core/windows_bootstrap_context"
|
22
|
+
require "chef/knife/bootstrap"
|
24
23
|
|
25
24
|
class Chef
|
26
25
|
class Knife
|
@@ -28,7 +27,7 @@ class Chef
|
|
28
27
|
class SshBootstrapProtocol < BootstrapProtocol
|
29
28
|
|
30
29
|
def initialize(config)
|
31
|
-
@bootstrap = (config[:image_os_type] ==
|
30
|
+
@bootstrap = (config[:image_os_type] == "linux") ? Chef::Knife::Bootstrap.new : Chef::Knife::BootstrapWindowsSsh.new
|
32
31
|
super
|
33
32
|
end
|
34
33
|
|
@@ -38,8 +37,8 @@ class Chef
|
|
38
37
|
bootstrap.config[:ssh_port] = locate_config_value(:ssh_port)
|
39
38
|
bootstrap.config[:identity_file] = @config[:identity_file]
|
40
39
|
bootstrap.config[:host_key_verify] = @config[:host_key_verify]
|
41
|
-
bootstrap.config[:use_sudo] = true unless @config[:ssh_user] ==
|
42
|
-
bootstrap.config[:template_file] =
|
40
|
+
bootstrap.config[:use_sudo] = true unless @config[:ssh_user] == "root"
|
41
|
+
bootstrap.config[:template_file] = @config[:template_file]
|
43
42
|
bootstrap.config[:ssh_gateway] = locate_config_value(:ssh_gateway)
|
44
43
|
bootstrap.config[:forward_agent] = locate_config_value(:forward_agent)
|
45
44
|
bootstrap.config[:use_sudo_password] = locate_config_value(:use_sudo_password)
|
@@ -53,17 +52,17 @@ class Chef
|
|
53
52
|
|
54
53
|
# The ssh_gateway & subnet_id are currently supported only in EC2.
|
55
54
|
if ssh_gateway
|
56
|
-
print(".") until tunnel_test_ssh(ssh_gateway, @config[:bootstrap_ip_address])
|
55
|
+
print(".") until tunnel_test_ssh(ssh_gateway, @config[:bootstrap_ip_address]) do
|
57
56
|
@initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10
|
58
57
|
sleep @initial_sleep_delay
|
59
58
|
puts("done")
|
60
|
-
|
59
|
+
end
|
61
60
|
else
|
62
|
-
print(".") until tcp_test_ssh(@config[:bootstrap_ip_address], locate_config_value(:ssh_port))
|
61
|
+
print(".") until tcp_test_ssh(@config[:bootstrap_ip_address], locate_config_value(:ssh_port)) do
|
63
62
|
@initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10
|
64
63
|
sleep @initial_sleep_delay
|
65
64
|
puts("done")
|
66
|
-
|
65
|
+
end
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
@@ -99,58 +98,54 @@ class Chef
|
|
99
98
|
end
|
100
99
|
|
101
100
|
def tcp_test_ssh(hostname, ssh_port)
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
101
|
+
tcp_socket = TCPSocket.new(hostname, ssh_port)
|
102
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
103
|
+
if readable
|
104
|
+
ssh_banner = tcp_socket.gets
|
105
|
+
if ssh_banner.nil? || ssh_banner.empty?
|
115
106
|
false
|
107
|
+
else
|
108
|
+
Chef::Log.debug("ssh accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
|
109
|
+
yield
|
110
|
+
true
|
116
111
|
end
|
117
|
-
|
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
|
112
|
+
else
|
128
113
|
false
|
129
|
-
ensure
|
130
|
-
tcp_socket && tcp_socket.close
|
131
114
|
end
|
115
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
116
|
+
Chef::Log.debug("ssh timed out: #{hostname}")
|
117
|
+
false
|
118
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
119
|
+
Chef::Log.debug("ssh failed to connect: #{hostname}")
|
120
|
+
sleep 2
|
121
|
+
false
|
122
|
+
# This happens on some mobile phone networks
|
123
|
+
rescue Errno::ECONNRESET
|
124
|
+
Chef::Log.debug("ssh reset its connection: #{hostname}")
|
125
|
+
sleep 2
|
126
|
+
false
|
127
|
+
ensure
|
128
|
+
tcp_socket && tcp_socket.close
|
132
129
|
end
|
133
130
|
|
134
131
|
def tunnel_test_ssh(ssh_gateway, hostname, &block)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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
|
132
|
+
status = false
|
133
|
+
gateway = configure_ssh_gateway(ssh_gateway)
|
134
|
+
gateway.open(hostname, locate_config_value(:ssh_port)) do |local_tunnel_port|
|
135
|
+
status = tcp_test_ssh("localhost", local_tunnel_port, &block)
|
147
136
|
end
|
137
|
+
status
|
138
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
|
139
|
+
sleep 2
|
140
|
+
false
|
141
|
+
rescue Errno::EPERM, Errno::ETIMEDOUT
|
142
|
+
false
|
148
143
|
end
|
149
144
|
|
150
145
|
def configure_ssh_gateway(ssh_gateway)
|
151
|
-
gw_host, gw_user = ssh_gateway.split(
|
152
|
-
gw_host, gw_port = gw_host.split(
|
153
|
-
gateway_options = { :
|
146
|
+
gw_host, gw_user = ssh_gateway.split("@").reverse
|
147
|
+
gw_host, gw_port = gw_host.split(":")
|
148
|
+
gateway_options = { port: gw_port || 22 }
|
154
149
|
|
155
150
|
# Load the SSH config for the SSH gateway host.
|
156
151
|
# Set the gateway user if it was not part of the
|
@@ -160,7 +155,7 @@ class Chef
|
|
160
155
|
gw_user ||= ssh_gateway_config[:user]
|
161
156
|
|
162
157
|
# Always use the gateway keys from the SSH Config
|
163
|
-
gateway_keys = ssh_gateway_config[:keys]
|
158
|
+
gateway_keys = ssh_gateway_config[:keys]
|
164
159
|
|
165
160
|
# Use the keys specificed on the command line if available (overrides SSH Config)
|
166
161
|
if locate_config_value(:ssh_gateway_identity)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
-
# Copyright:: Copyright (c) 2013
|
3
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
|
-
require
|
17
|
+
require "chef/knife/cloud/chefbootstrap/bootstrap_distribution"
|
18
18
|
|
19
19
|
class Chef
|
20
20
|
class Knife
|
@@ -23,7 +23,7 @@ class Chef
|
|
23
23
|
|
24
24
|
def initialize(config)
|
25
25
|
super
|
26
|
-
config[:distro] =
|
26
|
+
config[:distro] = config[:distro] || "chef-full"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
|
-
# Copyright:: Copyright (c) 2013
|
3
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -15,8 +15,8 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
-
require
|
19
|
-
require
|
18
|
+
require "chef/knife/cloud/chefbootstrap/bootstrap_distribution"
|
19
|
+
require "chef/knife/bootstrap_windows_base"
|
20
20
|
|
21
21
|
class Chef
|
22
22
|
class Knife
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
2
2
|
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
3
3
|
#
|
4
|
-
# Copyright:: Copyright (c) 2013
|
4
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require
|
20
|
+
require "chef/knife/cloud/chefbootstrap/bootstrap_protocol"
|
21
21
|
|
22
22
|
class Chef
|
23
23
|
class Knife
|
@@ -31,33 +31,33 @@ class Chef
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def load_winrm_deps
|
34
|
-
require
|
35
|
-
require
|
36
|
-
require
|
37
|
-
require
|
34
|
+
require "winrm"
|
35
|
+
require "chef/knife/bootstrap_windows_winrm"
|
36
|
+
require "chef/knife/core/windows_bootstrap_context"
|
37
|
+
require "chef/knife/winrm"
|
38
38
|
end
|
39
39
|
|
40
40
|
def init_bootstrap_options
|
41
|
-
bootstrap.config[:winrm_user] = @config[:winrm_user] ||
|
41
|
+
bootstrap.config[:winrm_user] = @config[:winrm_user] || "Administrator"
|
42
42
|
bootstrap.config[:winrm_password] = @config[:winrm_password]
|
43
43
|
bootstrap.config[:winrm_transport] = @config[:winrm_transport]
|
44
44
|
bootstrap.config[:winrm_port] = @config[:winrm_port]
|
45
|
-
bootstrap.config[:auth_timeout] =
|
45
|
+
bootstrap.config[:auth_timeout] = @config[:auth_timeout]
|
46
46
|
bootstrap.config[:winrm_ssl_verify_mode] = @config[:winrm_ssl_verify_mode]
|
47
47
|
super
|
48
48
|
end
|
49
49
|
|
50
50
|
def wait_for_server_ready
|
51
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])
|
52
|
+
print(".") until tcp_test_winrm(@config[:bootstrap_ip_address], @config[:winrm_port]) do
|
53
53
|
sleep @initial_sleep_delay ||= 10
|
54
54
|
puts("done")
|
55
|
-
|
55
|
+
end
|
56
56
|
end
|
57
57
|
|
58
58
|
def tcp_test_winrm(hostname, port)
|
59
59
|
tcp_socket = TCPSocket.new(hostname, port)
|
60
|
-
|
60
|
+
true
|
61
61
|
rescue SocketError
|
62
62
|
sleep 2
|
63
63
|
false
|
@@ -82,4 +82,3 @@ class Chef
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
3
|
-
# Copyright:: Copyright (c) 2013
|
3
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -16,9 +16,9 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
19
|
+
require "chef/knife"
|
20
20
|
require "chef/knife/cloud/helpers"
|
21
|
-
require
|
21
|
+
require "chef/knife/cloud/exceptions"
|
22
22
|
|
23
23
|
class Chef
|
24
24
|
class Knife
|
@@ -29,41 +29,39 @@ class Chef
|
|
29
29
|
attr_accessor :service, :custom_arguments
|
30
30
|
|
31
31
|
def run
|
32
|
-
begin
|
33
32
|
# Set dafult config
|
34
|
-
|
33
|
+
set_default_config
|
35
34
|
|
36
|
-
|
37
|
-
|
35
|
+
# validate compulsory params
|
36
|
+
validate!
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
# validate command pre-requisites (cli options)
|
39
|
+
validate_params!
|
41
40
|
|
42
|
-
|
43
|
-
|
41
|
+
# setup the service
|
42
|
+
@service = create_service_instance
|
44
43
|
|
45
|
-
|
44
|
+
service.ui = ui # for interactive user prompts/messages
|
46
45
|
|
47
|
-
|
48
|
-
|
46
|
+
# Perform any steps before handling the command
|
47
|
+
before_exec_command
|
49
48
|
|
50
|
-
|
51
|
-
|
49
|
+
# exec the actual cmd
|
50
|
+
execute_command
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
52
|
+
# Perform any steps after handling the command
|
53
|
+
after_exec_command
|
54
|
+
rescue CloudExceptions::KnifeCloudError => e
|
55
|
+
Chef::Log.debug(e.message)
|
56
|
+
exit 1
|
59
57
|
end
|
60
58
|
|
61
59
|
def create_service_instance
|
62
|
-
raise Chef::Exceptions::Override, "You must override create_service_instance in #{self
|
60
|
+
raise Chef::Exceptions::Override, "You must override create_service_instance in #{self} to create cloud specific service"
|
63
61
|
end
|
64
62
|
|
65
63
|
def execute_command
|
66
|
-
raise Chef::Exceptions::Override, "You must override execute_command in #{self
|
64
|
+
raise Chef::Exceptions::Override, "You must override execute_command in #{self}"
|
67
65
|
end
|
68
66
|
|
69
67
|
# Derived classes can override before_exec_command and after_exec_command
|
@@ -84,18 +82,17 @@ class Chef
|
|
84
82
|
errors << "You did not provide a valid '#{pretty_key(k)}' value." if locate_config_value(k).nil?
|
85
83
|
end
|
86
84
|
error_message = ""
|
87
|
-
raise CloudExceptions::ValidationError, error_message if errors.each{|e| ui.error(e); error_message = "#{error_message} #{e}."}.any?
|
85
|
+
raise CloudExceptions::ValidationError, error_message if errors.each { |e| ui.error(e); error_message = "#{error_message} #{e}." }.any?
|
88
86
|
end
|
89
87
|
|
90
88
|
def validate_params!
|
91
89
|
end
|
92
90
|
|
93
91
|
def pretty_key(key)
|
94
|
-
key.to_s.
|
92
|
+
key.to_s.tr("_", " ").gsub(/\w+/) { |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
|
95
93
|
end
|
96
94
|
|
97
95
|
end # class Command
|
98
96
|
end
|
99
97
|
end
|
100
98
|
end
|
101
|
-
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright:: Copyright (c) 2013
|
2
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
3
3
|
# License:: Apache License, Version 2.0
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -36,4 +36,3 @@ class Chef
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
3
|
-
# Copyright:: Copyright (c) 2013
|
3
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
4
4
|
#
|
5
5
|
|
6
6
|
class Chef
|
@@ -11,15 +11,15 @@ class Chef
|
|
11
11
|
def self.included(includer)
|
12
12
|
includer.instance_eval do
|
13
13
|
option :fog_version,
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
14
|
+
long: "--fog-version version",
|
15
|
+
description: "Fog gem version to use. Use the ruby gem version strings",
|
16
|
+
default: "",
|
17
|
+
proc: Proc.new { |v| Chef::Config[:knife][:cloud_fog_version] = v }
|
18
18
|
|
19
19
|
option :api_endpoint,
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
20
|
+
long: "--api-endpoint ENDPOINT",
|
21
|
+
description: "Your API endpoint. Eg, for Eucalyptus it can be 'http://ecc.eucalyptus.com:8773/services/Eucalyptus'",
|
22
|
+
proc: Proc.new { |endpoint| Chef::Config[:knife][:api_endpoint] = endpoint }
|
23
23
|
|
24
24
|
end
|
25
25
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
|
3
3
|
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
4
|
-
# Copyright:: Copyright (c) 2013
|
4
|
+
# Copyright:: Copyright (c) 2013-2016 Chef Software, Inc.
|
5
5
|
#
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
7
|
+
require "chef/knife/cloud/service"
|
8
|
+
require "chef/knife/cloud/exceptions"
|
9
9
|
|
10
10
|
class Chef
|
11
11
|
class Knife
|
@@ -18,26 +18,24 @@ class Chef
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def load_fog_gem
|
21
|
-
begin
|
22
21
|
# Load specific version of fog. Any other classes/modules using fog are loaded after this.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
22
|
+
gem "fog", Chef::Config[:knife][:cloud_fog_version]
|
23
|
+
require "fog"
|
24
|
+
Chef::Log.debug("Using fog version: #{Gem.loaded_specs["fog"].version}")
|
25
|
+
rescue Exception
|
26
|
+
Chef::Log.error "Error loading fog gem."
|
27
|
+
exit 1
|
30
28
|
end
|
31
29
|
|
32
30
|
def connection
|
33
31
|
add_api_endpoint
|
34
32
|
@connection ||= begin
|
35
|
-
|
36
|
-
rescue Excon::
|
33
|
+
Fog::Compute.new(@auth_params)
|
34
|
+
rescue Excon::Error::Unauthorized => e
|
37
35
|
error_message = "Connection failure, please check your username and password."
|
38
36
|
ui.fatal(error_message)
|
39
37
|
raise CloudExceptions::ServiceConnectionError, "#{e.message}. #{error_message}"
|
40
|
-
rescue Excon::
|
38
|
+
rescue Excon::Error::Socket => e
|
41
39
|
error_message = "Connection failure, please check your authentication URL."
|
42
40
|
ui.fatal(error_message)
|
43
41
|
raise CloudExceptions::ServiceConnectionError, "#{e.message}. #{error_message}"
|
@@ -46,12 +44,12 @@ class Chef
|
|
46
44
|
|
47
45
|
def network
|
48
46
|
@network ||= begin
|
49
|
-
|
50
|
-
rescue Excon::
|
47
|
+
Fog::Network.new(@auth_params)
|
48
|
+
rescue Excon::Error::Unauthorized => e
|
51
49
|
error_message = "Connection failure, please check your username and password."
|
52
50
|
ui.fatal(error_message)
|
53
51
|
raise CloudExceptions::ServiceConnectionError, "#{e.message}. #{error_message}"
|
54
|
-
rescue Excon::
|
52
|
+
rescue Excon::Error::Socket => e
|
55
53
|
error_message = "Connection failure, please check your authentication URL."
|
56
54
|
ui.fatal(error_message)
|
57
55
|
raise CloudExceptions::ServiceConnectionError, "#{e.message}. #{error_message}"
|
@@ -67,9 +65,9 @@ class Chef
|
|
67
65
|
begin
|
68
66
|
add_custom_attributes(options[:server_def])
|
69
67
|
server = connection.servers.create(options[:server_def])
|
70
|
-
rescue Excon::
|
68
|
+
rescue Excon::Error::BadRequest => e
|
71
69
|
response = Chef::JSONCompat.from_json(e.response.body)
|
72
|
-
if response[
|
70
|
+
if response["badRequest"]["code"] == 400
|
73
71
|
message = "Bad request (400): #{response['badRequest']['message']}"
|
74
72
|
ui.fatal(message)
|
75
73
|
else
|
@@ -91,26 +89,24 @@ class Chef
|
|
91
89
|
end
|
92
90
|
|
93
91
|
def delete_server(server_name)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
msg_pair("Instance ID", server.id)
|
92
|
+
server = get_server(server_name)
|
93
|
+
msg_pair("Instance Name", get_server_name(server))
|
94
|
+
msg_pair("Instance ID", server.id)
|
98
95
|
|
99
|
-
|
100
|
-
|
96
|
+
puts "\n"
|
97
|
+
ui.confirm("Do you really want to delete this server")
|
101
98
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
99
|
+
# delete the server
|
100
|
+
server.destroy
|
101
|
+
rescue NoMethodError
|
102
|
+
error_message = "Could not locate server '#{server_name}'."
|
103
|
+
ui.error(error_message)
|
104
|
+
raise CloudExceptions::ServerDeleteError, error_message
|
105
|
+
rescue Excon::Error::BadRequest => e
|
106
|
+
handle_excon_exception(CloudExceptions::ServerDeleteError, e)
|
111
107
|
end
|
112
108
|
|
113
|
-
|
109
|
+
%w{servers images networks}.each do |resource_type|
|
114
110
|
define_method("list_#{resource_type}") do
|
115
111
|
begin
|
116
112
|
case resource_type
|
@@ -119,7 +115,7 @@ class Chef
|
|
119
115
|
else
|
120
116
|
connection.method(resource_type).call.all
|
121
117
|
end
|
122
|
-
rescue Excon::
|
118
|
+
rescue Excon::Error::BadRequest => e
|
123
119
|
handle_excon_exception(CloudExceptions::CloudAPIException, e)
|
124
120
|
end
|
125
121
|
end
|
@@ -137,40 +133,38 @@ class Chef
|
|
137
133
|
end
|
138
134
|
|
139
135
|
def list_resource_configurations
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
handle_excon_exception(CloudExceptions::CloudAPIException, e)
|
144
|
-
end
|
136
|
+
connection.flavors.all
|
137
|
+
rescue Excon::Error::BadRequest => e
|
138
|
+
handle_excon_exception(CloudExceptions::CloudAPIException, e)
|
145
139
|
end
|
146
140
|
|
147
141
|
def list_addresses
|
148
142
|
connection.addresses.all
|
149
|
-
rescue Excon::
|
143
|
+
rescue Excon::Error::BadRequest => e
|
150
144
|
handle_excon_exception(CloudExceptions::CloudAPIException, e)
|
151
145
|
end
|
152
146
|
|
153
147
|
def release_address(address_id)
|
154
148
|
response = get_address(address_id)
|
155
|
-
msg_pair(
|
149
|
+
msg_pair("IP address", get_address_ip(response))
|
156
150
|
puts
|
157
|
-
ui.confirm(
|
151
|
+
ui.confirm("Do you really want to delete this ip")
|
158
152
|
connection.release_address(address_id)
|
159
153
|
rescue Fog::Compute::OpenStack::NotFound => e
|
160
|
-
error_message =
|
154
|
+
error_message = "Floating ip not found."
|
161
155
|
ui.error(error_message)
|
162
156
|
raise CloudExceptions::NotFoundError, "#{e.message}"
|
163
|
-
rescue Excon::
|
157
|
+
rescue Excon::Error::BadRequest => e
|
164
158
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
165
159
|
end
|
166
160
|
|
167
161
|
def get_address_ip(response)
|
168
|
-
response.body[
|
162
|
+
response.body["floating_ip"]["ip"] if response.body["floating_ip"]
|
169
163
|
end
|
170
164
|
|
171
165
|
def get_address(address_id)
|
172
166
|
connection.get_address(address_id)
|
173
|
-
rescue Excon::
|
167
|
+
rescue Excon::Error::BadRequest => e
|
174
168
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
175
169
|
end
|
176
170
|
|
@@ -178,29 +172,29 @@ class Chef
|
|
178
172
|
response = connection.allocate_address(pool)
|
179
173
|
response.body
|
180
174
|
rescue Fog::Compute::OpenStack::NotFound => e
|
181
|
-
error_message =
|
175
|
+
error_message = "Floating ip pool not found."
|
182
176
|
ui.error(error_message)
|
183
177
|
raise CloudExceptions::NotFoundError, "#{e.message}"
|
184
|
-
rescue Excon::
|
178
|
+
rescue Excon::Error::Forbidden => e
|
185
179
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
186
|
-
rescue Excon::
|
180
|
+
rescue Excon::Error::BadRequest => e
|
187
181
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
188
182
|
end
|
189
183
|
|
190
184
|
def associate_address(*args)
|
191
185
|
connection.associate_address(*args)
|
192
|
-
rescue Excon::
|
186
|
+
rescue Excon::Error::BadRequest => e
|
193
187
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
194
188
|
end
|
195
189
|
|
196
190
|
def disassociate_address(*args)
|
197
191
|
connection.disassociate_address(*args)
|
198
192
|
rescue Fog::Compute::OpenStack::NotFound
|
199
|
-
error_message =
|
193
|
+
error_message = "Floating ip not found."
|
200
194
|
ui.error(error_message)
|
201
|
-
rescue Excon::
|
195
|
+
rescue Excon::Error::UnprocessableEntity => e
|
202
196
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
203
|
-
rescue Excon::
|
197
|
+
rescue Excon::Error::BadRequest => e
|
204
198
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
205
199
|
end
|
206
200
|
|
@@ -209,7 +203,7 @@ class Chef
|
|
209
203
|
end
|
210
204
|
|
211
205
|
def add_api_endpoint
|
212
|
-
raise Chef::Exceptions::Override, "You must override add_api_endpoint in #{self
|
206
|
+
raise Chef::Exceptions::Override, "You must override add_api_endpoint in #{self} to add endpoint in auth_params for connection"
|
213
207
|
end
|
214
208
|
|
215
209
|
def get_server_name(server)
|
@@ -218,16 +212,16 @@ class Chef
|
|
218
212
|
|
219
213
|
def get_server(instance_id)
|
220
214
|
connection.servers.get(instance_id)
|
221
|
-
rescue Excon::
|
215
|
+
rescue Excon::Error::BadRequest => e
|
222
216
|
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
|
223
217
|
end
|
224
218
|
|
225
219
|
def get_image(name_or_id)
|
226
|
-
connection.images.find{|img| img.name =~ /#{name_or_id}/ || img.id == name_or_id }
|
220
|
+
connection.images.find { |img| img.name =~ /#{name_or_id}/ || img.id == name_or_id }
|
227
221
|
end
|
228
222
|
|
229
223
|
def get_flavor(name_or_id)
|
230
|
-
connection.flavors.find{|f| f.name == name_or_id || f.id == name_or_id }
|
224
|
+
connection.flavors.find { |f| f.name == name_or_id || f.id == name_or_id }
|
231
225
|
end
|
232
226
|
|
233
227
|
def server_summary(server, columns_with_info = [])
|
@@ -249,7 +243,7 @@ class Chef
|
|
249
243
|
|
250
244
|
def is_image_windows?(image)
|
251
245
|
image_info = connection.images.get(image)
|
252
|
-
!image_info.nil? ? image_info.platform ==
|
246
|
+
!image_info.nil? ? image_info.platform == "windows" : false
|
253
247
|
end
|
254
248
|
end
|
255
249
|
end
|