knife-azure 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +22 -0
- data/Guardfile +8 -0
- data/LICENSE +201 -0
- data/Rakefile +51 -0
- data/knife-azure.gemspec +106 -0
- data/lib/azure/connection.rb +75 -0
- data/lib/azure/deploy.rb +114 -0
- data/lib/azure/disk.rb +62 -0
- data/lib/azure/host.rb +90 -0
- data/lib/azure/image.rb +58 -0
- data/lib/azure/rest.rb +97 -0
- data/lib/azure/role.rb +182 -0
- data/lib/azure/utility.rb +29 -0
- data/lib/chef/knife/azure_base.rb +102 -0
- data/lib/chef/knife/azure_image_list.rb +58 -0
- data/lib/chef/knife/azure_server_create.rb +283 -0
- data/lib/chef/knife/azure_server_delete.rb +103 -0
- data/lib/chef/knife/azure_server_describe.rb +85 -0
- data/lib/chef/knife/azure_server_list.rb +70 -0
- data/lib/knife-azure/version.rb +7 -0
- data/readme.rdoc +210 -0
- data/spec/functional/deploys_test.rb +39 -0
- data/spec/functional/host_test.rb +22 -0
- data/spec/functional/images_list_test.rb +44 -0
- data/spec/functional/role_test.rb +16 -0
- data/spec/integration/role_lifecycle_test.rb +60 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/assets/create_deployment.xml +37 -0
- data/spec/unit/assets/create_deployment_in_progress.xml +1 -0
- data/spec/unit/assets/create_host.xml +7 -0
- data/spec/unit/assets/create_role.xml +54 -0
- data/spec/unit/assets/list_deployments_for_service000.xml +126 -0
- data/spec/unit/assets/list_deployments_for_service001.xml +166 -0
- data/spec/unit/assets/list_deployments_for_service002.xml +1 -0
- data/spec/unit/assets/list_deployments_for_service003.xml +1 -0
- data/spec/unit/assets/list_disks.xml +1 -0
- data/spec/unit/assets/list_hosts.xml +1 -0
- data/spec/unit/assets/list_images.xml +1 -0
- data/spec/unit/assets/post_success.xml +6 -0
- data/spec/unit/deploys_list_spec.rb +55 -0
- data/spec/unit/disks_spec.rb +44 -0
- data/spec/unit/hosts_spec.rb +55 -0
- data/spec/unit/images_spec.rb +35 -0
- data/spec/unit/query_azure_mock.rb +69 -0
- data/spec/unit/roles_create_spec.rb +82 -0
- data/spec/unit/roles_list_spec.rb +32 -0
- metadata +240 -0
@@ -0,0 +1,283 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
4
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require File.expand_path('../azure_base', __FILE__)
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Knife
|
25
|
+
class AzureServerCreate < Knife
|
26
|
+
|
27
|
+
include Knife::AzureBase
|
28
|
+
|
29
|
+
deps do
|
30
|
+
require 'readline'
|
31
|
+
require 'chef/json_compat'
|
32
|
+
require 'chef/knife/bootstrap'
|
33
|
+
Chef::Knife::Bootstrap.load_deps
|
34
|
+
end
|
35
|
+
|
36
|
+
banner "knife azure server create (options)"
|
37
|
+
|
38
|
+
attr_accessor :initial_sleep_delay
|
39
|
+
|
40
|
+
option :chef_node_name,
|
41
|
+
:short => "-N NAME",
|
42
|
+
:long => "--node-name NAME",
|
43
|
+
:description => "The Chef node name for your new node"
|
44
|
+
|
45
|
+
option :ssh_user,
|
46
|
+
:short => "-x USERNAME",
|
47
|
+
:long => "--ssh-user USERNAME",
|
48
|
+
:description => "The ssh username"
|
49
|
+
|
50
|
+
option :ssh_password,
|
51
|
+
:short => "-P PASSWORD",
|
52
|
+
:long => "--ssh-password PASSWORD",
|
53
|
+
:description => "The ssh password"
|
54
|
+
|
55
|
+
option :identity_file,
|
56
|
+
:short => "-i IDENTITY_FILE",
|
57
|
+
:long => "--identity-file IDENTITY_FILE",
|
58
|
+
:description => "The SSH identity file used for authentication"
|
59
|
+
|
60
|
+
option :prerelease,
|
61
|
+
:long => "--prerelease",
|
62
|
+
:description => "Install the pre-release chef gems"
|
63
|
+
|
64
|
+
option :bootstrap_version,
|
65
|
+
:long => "--bootstrap-version VERSION",
|
66
|
+
:description => "The version of Chef to install",
|
67
|
+
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
68
|
+
|
69
|
+
option :distro,
|
70
|
+
:short => "-d DISTRO",
|
71
|
+
:long => "--distro DISTRO",
|
72
|
+
:description => "Bootstrap a distro using a template",
|
73
|
+
:proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
|
74
|
+
:default => "chef-full"
|
75
|
+
|
76
|
+
option :template_file,
|
77
|
+
:long => "--template-file TEMPLATE",
|
78
|
+
:description => "Full path to location of template to use",
|
79
|
+
:proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
|
80
|
+
:default => false
|
81
|
+
|
82
|
+
option :run_list,
|
83
|
+
:short => "-r RUN_LIST",
|
84
|
+
:long => "--run-list RUN_LIST",
|
85
|
+
:description => "Comma separated list of roles/recipes to apply",
|
86
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
87
|
+
:default => []
|
88
|
+
|
89
|
+
option :no_host_key_verify,
|
90
|
+
:long => "--no-host-key-verify",
|
91
|
+
:description => "Disable host key verification",
|
92
|
+
:boolean => true,
|
93
|
+
:default => false
|
94
|
+
|
95
|
+
option :hosted_service_name,
|
96
|
+
:short => "-s NAME",
|
97
|
+
:long => "--hosted-service-name NAME",
|
98
|
+
:description => "specifies the name for the hosted service"
|
99
|
+
|
100
|
+
option :role_name,
|
101
|
+
:short => "-R name",
|
102
|
+
:long => "--role-name NAME",
|
103
|
+
:description => "specifies the name for the virtual machine"
|
104
|
+
|
105
|
+
option :host_name,
|
106
|
+
:short => "-H NAME",
|
107
|
+
:long => "--host-name NAME",
|
108
|
+
:description => "specifies the host name for the virtual machine"
|
109
|
+
|
110
|
+
option :media_location_prefix,
|
111
|
+
:short => "-m PREFIX",
|
112
|
+
:long => "--media-location-prefix PREFIX",
|
113
|
+
:description => "user account name (used for constructing os disk media link)"
|
114
|
+
|
115
|
+
option :os_disk_name,
|
116
|
+
:short => "-o DISKNAME",
|
117
|
+
:long => "--os-disk-name DISKNAME",
|
118
|
+
:description => "unique name for specifying os disk (optional)"
|
119
|
+
|
120
|
+
option :source_image,
|
121
|
+
:short => "-I IMAGE",
|
122
|
+
:long => "--source-image IMAGE",
|
123
|
+
:description => "disk image name to use to create virtual machine"
|
124
|
+
|
125
|
+
option :role_size,
|
126
|
+
:short => "-z SIZE",
|
127
|
+
:long => "--role-size SIZE",
|
128
|
+
:description => "size of virtual machine (ExtraSmall, Small, Medium, Large, ExtraLarge)"
|
129
|
+
|
130
|
+
option :tcp_endpoints,
|
131
|
+
:short => "-t PORT_LIST",
|
132
|
+
:long => "--tcp-endpoints PORT_LIST",
|
133
|
+
:description => "Comma separated list of TCP local and public ports to open i.e. '80:80,433:5000'"
|
134
|
+
|
135
|
+
option :udp_endpoints,
|
136
|
+
:short => "-u PORT_LIST",
|
137
|
+
:long => "--udp-endpoints PORT_LIST",
|
138
|
+
:description => "Comma separated list of UDP local and public ports to open i.e. '80:80,433:5000'"
|
139
|
+
|
140
|
+
|
141
|
+
def tcp_test_ssh(fqdn, sshport)
|
142
|
+
tcp_socket = TCPSocket.new(fqdn, sshport)
|
143
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
144
|
+
if readable
|
145
|
+
Chef::Log.debug("sshd accepting connections on #{fqdn}, banner is #{tcp_socket.gets}")
|
146
|
+
yield
|
147
|
+
true
|
148
|
+
else
|
149
|
+
false
|
150
|
+
end
|
151
|
+
rescue SocketError
|
152
|
+
sleep 2
|
153
|
+
false
|
154
|
+
rescue Errno::ETIMEDOUT
|
155
|
+
false
|
156
|
+
rescue Errno::EPERM
|
157
|
+
false
|
158
|
+
rescue Errno::ECONNREFUSED
|
159
|
+
sleep 2
|
160
|
+
false
|
161
|
+
# This happens on EC2 quite often
|
162
|
+
rescue Errno::EHOSTUNREACH
|
163
|
+
sleep 2
|
164
|
+
false
|
165
|
+
ensure
|
166
|
+
tcp_socket && tcp_socket.close
|
167
|
+
end
|
168
|
+
|
169
|
+
def parameter_test
|
170
|
+
details = Array.new
|
171
|
+
details << ui.color('name', :bold, :blue)
|
172
|
+
details << ui.color('Chef::Config', :bold, :blue)
|
173
|
+
details << ui.color('config', :bold, :blue)
|
174
|
+
details << ui.color('winner is', :bold, :blue)
|
175
|
+
[
|
176
|
+
:azure_subscription_id,
|
177
|
+
:azure_pem_file,
|
178
|
+
:azure_host_name,
|
179
|
+
:hosted_service_name,
|
180
|
+
:role_name,
|
181
|
+
:host_name,
|
182
|
+
:ssh_user,
|
183
|
+
:ssh_password,
|
184
|
+
:media_location_prefix,
|
185
|
+
:source_image,
|
186
|
+
:role_size
|
187
|
+
].each do |key|
|
188
|
+
key = key.to_sym
|
189
|
+
details << key.to_s
|
190
|
+
details << Chef::Config[:knife][key].to_s
|
191
|
+
details << config[key].to_s
|
192
|
+
details << locate_config_value(key)
|
193
|
+
end
|
194
|
+
puts ui.list(details, :columns_across, 4)
|
195
|
+
end
|
196
|
+
def run
|
197
|
+
$stdout.sync = true
|
198
|
+
|
199
|
+
Chef::Log.info("validating...")
|
200
|
+
validate!
|
201
|
+
|
202
|
+
Chef::Log.info("creating...")
|
203
|
+
server = connection.deploys.create(create_server_def)
|
204
|
+
|
205
|
+
puts("\n")
|
206
|
+
|
207
|
+
unless server && server.sshipaddress && server.sshport
|
208
|
+
Chef::Log.fatal("server not created")
|
209
|
+
exit 1
|
210
|
+
end
|
211
|
+
|
212
|
+
fqdn = server.sshipaddress
|
213
|
+
port = server.sshport
|
214
|
+
|
215
|
+
print "\n#{ui.color("Waiting for sshd on #{fqdn}:#{port}", :magenta)}"
|
216
|
+
|
217
|
+
print(".") until tcp_test_ssh(fqdn,port) {
|
218
|
+
sleep @initial_sleep_delay ||= 10
|
219
|
+
puts("done")
|
220
|
+
}
|
221
|
+
|
222
|
+
sleep 15
|
223
|
+
|
224
|
+
bootstrap_for_node(server,fqdn,port).run
|
225
|
+
|
226
|
+
puts "\n"
|
227
|
+
end
|
228
|
+
|
229
|
+
def bootstrap_for_node(server,fqdn,port)
|
230
|
+
bootstrap = Chef::Knife::Bootstrap.new
|
231
|
+
bootstrap.name_args = [fqdn]
|
232
|
+
bootstrap.config[:run_list] = config[:run_list]
|
233
|
+
bootstrap.config[:ssh_user] = locate_config_value(:ssh_user)
|
234
|
+
bootstrap.config[:ssh_password] = locate_config_value(:ssh_password)
|
235
|
+
bootstrap.config[:ssh_port] = port
|
236
|
+
bootstrap.config[:identity_file] = locate_config_value(:identity_file)
|
237
|
+
bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name) || server.name
|
238
|
+
bootstrap.config[:prerelease] = locate_config_value(:prerelease)
|
239
|
+
bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
|
240
|
+
bootstrap.config[:distro] = locate_config_value(:distro)
|
241
|
+
bootstrap.config[:use_sudo] = true unless locate_config_value(:ssh_user) == 'root'
|
242
|
+
bootstrap.config[:template_file] = config[:template_file]
|
243
|
+
bootstrap.config[:environment] = locate_config_value(:environment)
|
244
|
+
# may be needed for vpc_mode
|
245
|
+
bootstrap.config[:no_host_key_verify] = config[:no_host_key_verify]
|
246
|
+
bootstrap
|
247
|
+
end
|
248
|
+
|
249
|
+
def validate!
|
250
|
+
super([
|
251
|
+
:azure_subscription_id,
|
252
|
+
:azure_pem_file,
|
253
|
+
:azure_host_name,
|
254
|
+
:hosted_service_name,
|
255
|
+
:role_name,
|
256
|
+
:host_name,
|
257
|
+
:ssh_user,
|
258
|
+
:ssh_password,
|
259
|
+
:media_location_prefix,
|
260
|
+
:source_image,
|
261
|
+
:role_size
|
262
|
+
])
|
263
|
+
end
|
264
|
+
|
265
|
+
def create_server_def
|
266
|
+
server_def = {
|
267
|
+
:hosted_service_name => locate_config_value(:hosted_service_name),
|
268
|
+
:role_name => locate_config_value(:role_name),
|
269
|
+
:host_name => locate_config_value(:host_name),
|
270
|
+
:ssh_user => locate_config_value(:ssh_user),
|
271
|
+
:ssh_password => locate_config_value(:ssh_password),
|
272
|
+
:media_location_prefix => locate_config_value(:media_location_prefix),
|
273
|
+
:os_disk_name => locate_config_value(:os_disk_name),
|
274
|
+
:source_image => locate_config_value(:source_image),
|
275
|
+
:role_size => locate_config_value(:role_size),
|
276
|
+
:tcp_endpoints => locate_config_value(:tcp_endpoints),
|
277
|
+
:udp_endpoints => locate_config_value(:udp_endpoints)
|
278
|
+
}
|
279
|
+
server_def
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
4
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2009-2011 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require File.expand_path('../azure_base', __FILE__)
|
22
|
+
|
23
|
+
# These two are needed for the '--purge' deletion case
|
24
|
+
require 'chef/node'
|
25
|
+
require 'chef/api_client'
|
26
|
+
|
27
|
+
class Chef
|
28
|
+
class Knife
|
29
|
+
class AzureServerDelete < Knife
|
30
|
+
|
31
|
+
include Knife::AzureBase
|
32
|
+
|
33
|
+
banner "knife azure server delete SERVER [SERVER] (options)"
|
34
|
+
|
35
|
+
option :purge,
|
36
|
+
:short => "-P",
|
37
|
+
:long => "--purge",
|
38
|
+
:boolean => true,
|
39
|
+
:default => false,
|
40
|
+
:description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the EC2 node itself. Assumes node and client have the same name as the server (if not, add the '--node-name' option)."
|
41
|
+
|
42
|
+
option :chef_node_name,
|
43
|
+
:short => "-N NAME",
|
44
|
+
:long => "--node-name NAME",
|
45
|
+
:description => "The name of the node and client to delete, if it differs from the server name. Only has meaning when used with the '--purge' option."
|
46
|
+
|
47
|
+
# Extracted from Chef::Knife.delete_object, because it has a
|
48
|
+
# confirmation step built in... By specifying the '--purge'
|
49
|
+
# flag (and also explicitly confirming the server destruction!)
|
50
|
+
# the user is already making their intent known. It is not
|
51
|
+
# necessary to make them confirm two more times.
|
52
|
+
def destroy_item(klass, name, type_name)
|
53
|
+
begin
|
54
|
+
object = klass.load(name)
|
55
|
+
object.destroy
|
56
|
+
ui.warn("Deleted #{type_name} #{name}")
|
57
|
+
rescue Net::HTTPServerException
|
58
|
+
ui.warn("Could not find a #{type_name} named #{name} to delete!")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def run
|
63
|
+
|
64
|
+
validate!
|
65
|
+
|
66
|
+
@name_args.each do |name|
|
67
|
+
|
68
|
+
begin
|
69
|
+
server = connection.roles.find(name)
|
70
|
+
|
71
|
+
puts "\n"
|
72
|
+
msg_pair('Service', server.hostedservicename)
|
73
|
+
msg_pair('Deployment', server.deployname)
|
74
|
+
msg_pair('Role', server.name)
|
75
|
+
msg_pair('Size', server.size)
|
76
|
+
msg_pair('SSH Ip Address', server.sshipaddress)
|
77
|
+
msg_pair('SSH Port', server.sshport)
|
78
|
+
|
79
|
+
puts "\n"
|
80
|
+
confirm("Do you really want to delete this server")
|
81
|
+
|
82
|
+
connection.roles.delete(name)
|
83
|
+
|
84
|
+
puts "\n"
|
85
|
+
ui.warn("Deleted server #{server.name}")
|
86
|
+
|
87
|
+
if config[:purge]
|
88
|
+
thing_to_delete = config[:chef_node_name] || name
|
89
|
+
destroy_item(Chef::Node, thing_to_delete, "node")
|
90
|
+
destroy_item(Chef::ApiClient, thing_to_delete, "client")
|
91
|
+
else
|
92
|
+
ui.warn("Corresponding node and client for the #{name} server were not deleted and remain registered with the Chef Server")
|
93
|
+
end
|
94
|
+
|
95
|
+
rescue NoMethodError
|
96
|
+
ui.error("Could not locate server '#{name}'. Please verify it was provisioned.")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
4
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require File.expand_path('../azure_base', __FILE__)
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Knife
|
25
|
+
class AzureServerDescribe < Knife
|
26
|
+
|
27
|
+
include Knife::AzureBase
|
28
|
+
|
29
|
+
banner "knife azure server describe ROLE [ROLE]"
|
30
|
+
|
31
|
+
def run
|
32
|
+
$stdout.sync = true
|
33
|
+
|
34
|
+
validate!
|
35
|
+
|
36
|
+
@name_args.each do |name|
|
37
|
+
role = connection.roles.find name
|
38
|
+
puts ''
|
39
|
+
if (role)
|
40
|
+
details = Array.new
|
41
|
+
details << ui.color('Role name', :bold, :blue)
|
42
|
+
details << role.name
|
43
|
+
details << ui.color('Status', :bold, :blue)
|
44
|
+
details << role.status
|
45
|
+
details << ui.color('Size', :bold, :blue)
|
46
|
+
details << role.size
|
47
|
+
details << ui.color('Hosted service name', :bold, :blue)
|
48
|
+
details << role.hostedservicename
|
49
|
+
details << ui.color('Deployment name', :bold, :blue)
|
50
|
+
details << role.deployname
|
51
|
+
details << ui.color('Host name', :bold, :blue)
|
52
|
+
details << role.hostname
|
53
|
+
details << ui.color('SSH', :bold, :blue)
|
54
|
+
details << role.sshipaddress + ':' + role.sshport
|
55
|
+
puts ui.list(details, :columns_across, 2)
|
56
|
+
if role.tcpports.length > 0 || role.udpports.length > 0
|
57
|
+
details.clear
|
58
|
+
details << ui.color('Ports open', :bold, :blue)
|
59
|
+
details << ui.color('Local port', :bold, :blue)
|
60
|
+
details << ui.color('IP', :bold, :blue)
|
61
|
+
details << ui.color('Public port', :bold, :blue)
|
62
|
+
if role.tcpports.length > 0
|
63
|
+
role.tcpports.each do |port|
|
64
|
+
details << 'tcp'
|
65
|
+
details << port['LocalPort']
|
66
|
+
details << port['Vip']
|
67
|
+
details << port['PublicPort']
|
68
|
+
end
|
69
|
+
end
|
70
|
+
if role.udpports.length > 0
|
71
|
+
role.udpports.each do |port|
|
72
|
+
details << 'udp'
|
73
|
+
details << port['LocalPort']
|
74
|
+
details << port['Vip']
|
75
|
+
details << port['PublicPort']
|
76
|
+
end
|
77
|
+
end
|
78
|
+
puts ui.list(details, :columns_across, 4)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
4
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require File.expand_path('../azure_base', __FILE__)
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Knife
|
25
|
+
class AzureServerList < Knife
|
26
|
+
|
27
|
+
include Knife::AzureBase
|
28
|
+
|
29
|
+
banner "knife azure server list (options)"
|
30
|
+
|
31
|
+
def run
|
32
|
+
$stdout.sync = true
|
33
|
+
|
34
|
+
validate!
|
35
|
+
|
36
|
+
server_list = [
|
37
|
+
ui.color('Status', :bold),
|
38
|
+
ui.color('Service', :bold),
|
39
|
+
ui.color('Deployment', :bold),
|
40
|
+
ui.color('Role', :bold),
|
41
|
+
ui.color('Host', :bold),
|
42
|
+
ui.color('SSH IP', :bold),
|
43
|
+
ui.color('SSH Port', :bold)
|
44
|
+
]
|
45
|
+
items = connection.roles.all
|
46
|
+
items.each do |server|
|
47
|
+
server_list << begin
|
48
|
+
state = server.status.to_s.downcase
|
49
|
+
case state
|
50
|
+
when 'shutting-down','terminated','stopping','stopped'
|
51
|
+
ui.color(state, :red)
|
52
|
+
when 'pending'
|
53
|
+
ui.color(state, :yellow)
|
54
|
+
else
|
55
|
+
ui.color('ready', :green)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
server_list << server.hostedservicename.to_s
|
59
|
+
server_list << server.deployname.to_s
|
60
|
+
server_list << server.name.to_s
|
61
|
+
server_list << server.hostname.to_s
|
62
|
+
server_list << server.sshipaddress.to_s
|
63
|
+
server_list << server.sshport.to_s
|
64
|
+
end
|
65
|
+
puts ''
|
66
|
+
puts ui.list(server_list, :columns_across, 7)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|