knife-cloud 1.2.1 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|