knife-rackspace 0.5.14 → 0.5.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,11 @@
1
+ ## v0.5.16
2
+ * KNIFE_RACKSPACE-36 Changed to code to use IP address for bootstrapping
3
+ * KNIFE_RACKSPACE-38 Support the -P --purge option
4
+ * Refactored to use msg_pair method like other knife plugins with eye on eventual base class.
5
+ * KNIFE_RACKSPACE-29 Support private network to connect to for bootstrap
6
+ * KNIFE_RACKSPACE-40 Support for disabling host key checking
7
+ * Added the 'unknown' state to `rackspace server list`, appeared transitory
8
+
1
9
  ## v0.5.14
2
10
  * KNIFE_RACKSPACE-25 version bump to match knife-ec2's dependencies
3
11
  * KNIFE_RACKSPACE-33 chef-full is new default
@@ -54,7 +54,7 @@ Provisions a new server in the Rackspace Cloud and then perform a Chef bootstrap
54
54
 
55
55
  == knife rackspace server delete
56
56
 
57
- Deletes an existing server in the currently configured Rackspace Cloud account by the server/instance id. You can find the instance id by entering 'knife rackspace server list'. Please note - this does not delete the associated node and client objects from the Chef server.
57
+ Deletes an existing server in the currently configured Rackspace Cloud account by the server/instance id. You can find the instance id by entering 'knife rackspace server list'. Please note - this does not delete the associated node and client objects from the Chef server unless you pass the <tt>-P</tt> or <tt>--purge</tt> command option.
58
58
 
59
59
  == knife rackspace server list
60
60
 
@@ -73,6 +73,7 @@ Outputs a list of all available images available to the currently configured Rac
73
73
 
74
74
  Author:: Adam Jacob (<adam@opscode.com>)
75
75
  Author:: Seth Chisamore (<schisamo@opscode.com>)
76
+ Author:: Matt Ray (<matt@opscode.com>)
76
77
  Copyright:: Copyright (c) 2009-2012 Opscode, Inc.
77
78
  License:: Apache License, Version 2.0
78
79
 
@@ -71,6 +71,12 @@ class Chef
71
71
  Chef::Config[:knife][key] || config[key]
72
72
  end
73
73
 
74
+ def msg_pair(label, value, color=:cyan)
75
+ if value && !value.to_s.empty?
76
+ puts "#{ui.color(label, color)}: #{value}"
77
+ end
78
+ end
79
+
74
80
  def public_dns_name(server)
75
81
  @public_dns_name ||= begin
76
82
  Resolv.getname(server.addresses["public"][0])
@@ -57,6 +57,12 @@ class Chef
57
57
  :long => "--node-name NAME",
58
58
  :description => "The Chef node name for your new node"
59
59
 
60
+ option :private_network,
61
+ :long => "--private-network",
62
+ :description => "Use the private IP for bootstrapping rather than the public IP",
63
+ :boolean => true,
64
+ :default => false
65
+
60
66
  option :ssh_user,
61
67
  :short => "-x USERNAME",
62
68
  :long => "--ssh-user USERNAME",
@@ -101,7 +107,7 @@ class Chef
101
107
  :description => "Comma separated list of roles/recipes to apply",
102
108
  :proc => lambda { |o| o.split(/[\s,]+/) },
103
109
  :default => []
104
-
110
+
105
111
  option :first_boot_attributes,
106
112
  :short => "-j JSON_ATTRIBS",
107
113
  :long => "--json-attributes",
@@ -116,6 +122,12 @@ class Chef
116
122
  :proc => Proc.new { |m| Chef::Config[:knife][:rackspace_metadata] = JSON.parse(m) },
117
123
  :default => ""
118
124
 
125
+ option :host_key_verify,
126
+ :long => "--[no-]host-key-verify",
127
+ :description => "Verify host key, enabled by default",
128
+ :boolean => true,
129
+ :default => true
130
+
119
131
  def tcp_test_ssh(hostname)
120
132
  tcp_socket = TCPSocket.new(hostname, 22)
121
133
  readable = IO.select([tcp_socket], nil, nil, 5)
@@ -155,12 +167,12 @@ class Chef
155
167
  :metadata => Chef::Config[:knife][:rackspace_metadata]
156
168
  )
157
169
 
158
- puts "#{ui.color("Instance ID", :cyan)}: #{server.id}"
159
- puts "#{ui.color("Host ID", :cyan)}: #{server.host_id}"
160
- puts "#{ui.color("Name", :cyan)}: #{server.name}"
161
- puts "#{ui.color("Flavor", :cyan)}: #{server.flavor.name}"
162
- puts "#{ui.color("Image", :cyan)}: #{server.image.name}"
163
- puts "#{ui.color("Metadata", :cyan)}: #{server.metadata}"
170
+ msg_pair("Instance ID", server.id)
171
+ msg_pair("Host ID", server.host_id)
172
+ msg_pair("Name", server.name)
173
+ msg_pair("Flavor", server.flavor.name)
174
+ msg_pair("Image", server.image.name)
175
+ msg_pair("Metadata", server.metadata)
164
176
 
165
177
  print "\n#{ui.color("Waiting server", :magenta)}"
166
178
 
@@ -169,40 +181,55 @@ class Chef
169
181
 
170
182
  puts("\n")
171
183
 
172
- puts "#{ui.color("Public DNS Name", :cyan)}: #{public_dns_name(server)}"
173
- puts "#{ui.color("Public IP Address", :cyan)}: #{server.addresses["public"][0]}"
174
- puts "#{ui.color("Private IP Address", :cyan)}: #{server.addresses["private"][0]}"
175
- puts "#{ui.color("Password", :cyan)}: #{server.password}"
184
+ msg_pair("Public DNS Name", public_dns_name(server))
185
+ msg_pair("Public IP Address", server.addresses['public'][0])
186
+ msg_pair("Private IP Address", server.addresses['private'][0])
187
+ msg_pair("Password", server.password)
176
188
 
177
189
  print "\n#{ui.color("Waiting for sshd", :magenta)}"
178
190
 
179
- print(".") until tcp_test_ssh(server.addresses["public"][0]) { sleep @initial_sleep_delay ||= 10; puts("done") }
191
+ #which IP address to bootstrap
192
+ bootstrap_ip_address = server.addresses['public'][0] if server.public_ip_address
193
+ if config[:private_network]
194
+ bootstrap_ip_address = server.addresses['private'][0]
195
+ end
196
+ Chef::Log.debug("Bootstrap IP Address #{bootstrap_ip_address}")
197
+ if bootstrap_ip_address.nil?
198
+ ui.error("No IP address available for bootstrapping.")
199
+ exit 1
200
+ end
201
+
202
+ print(".") until tcp_test_ssh(bootstrap_ip_address) {
203
+ sleep @initial_sleep_delay ||= 10
204
+ puts("done")
205
+ }
180
206
 
181
- bootstrap_for_node(server).run
207
+ bootstrap_for_node(server, bootstrap_ip_address).run
182
208
 
183
209
  puts "\n"
184
- puts "#{ui.color("Instance ID", :cyan)}: #{server.id}"
185
- puts "#{ui.color("Host ID", :cyan)}: #{server.host_id}"
186
- puts "#{ui.color("Name", :cyan)}: #{server.name}"
187
- puts "#{ui.color("Flavor", :cyan)}: #{server.flavor.name}"
188
- puts "#{ui.color("Image", :cyan)}: #{server.image.name}"
189
- puts "#{ui.color("Metadata", :cyan)}: #{server.metadata}"
190
- puts "#{ui.color("Public DNS Name", :cyan)}: #{public_dns_name(server)}"
191
- puts "#{ui.color("Public IP Address", :cyan)}: #{server.addresses["public"][0]}"
192
- puts "#{ui.color("Private IP Address", :cyan)}: #{server.addresses["private"][0]}"
193
- puts "#{ui.color("Password", :cyan)}: #{server.password}"
194
- puts "#{ui.color("Environment", :cyan)}: #{config[:environment] || '_default'}"
195
- puts "#{ui.color("Run List", :cyan)}: #{config[:run_list].join(', ')}"
210
+ msg_pair("Instance ID", server.id)
211
+ msg_pair("Host ID", server.host_id)
212
+ msg_pair("Name", server.name)
213
+ msg_pair("Flavor", server.flavor.name)
214
+ msg_pair("Image", server.image.name)
215
+ msg_pair("Metadata", server.metadata)
216
+ msg_pair("Public DNS Name", public_dns_name(server))
217
+ msg_pair("Public IP Address", server.addresses["public"][0])
218
+ msg_pair("Private IP Address", server.addresses["private"][0])
219
+ msg_pair("Password", server.password)
220
+ msg_pair("Environment", config[:environment] || '_default')
221
+ msg_pair("Run List", config[:run_list].join(', '))
196
222
  end
197
223
 
198
- def bootstrap_for_node(server)
224
+ def bootstrap_for_node(server, bootstrap_ip_address)
199
225
  bootstrap = Chef::Knife::Bootstrap.new
200
- bootstrap.name_args = [public_dns_name(server)]
226
+ bootstrap.name_args = [bootstrap_ip_address]
201
227
  bootstrap.config[:run_list] = config[:run_list]
202
228
  bootstrap.config[:first_boot_attributes] = config[:first_boot_attributes]
203
229
  bootstrap.config[:ssh_user] = config[:ssh_user] || "root"
204
230
  bootstrap.config[:ssh_password] = server.password
205
231
  bootstrap.config[:identity_file] = config[:identity_file]
232
+ bootstrap.config[:host_key_verify] = config[:host_key_verify]
206
233
  bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.id
207
234
  bootstrap.config[:prerelease] = config[:prerelease]
208
235
  bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
@@ -1,6 +1,7 @@
1
1
  #
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
- # Copyright:: Copyright (c) 2009 Opscode, Inc.
3
+ # Author:: Matt Ray (<matt@opscode.com>)
4
+ # Copyright:: Copyright (c) 2009-2012 Opscode, Inc.
4
5
  # License:: Apache License, Version 2.0
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +19,10 @@
18
19
 
19
20
  require 'chef/knife/rackspace_base'
20
21
 
22
+ # These two are needed for the '--purge' deletion case
23
+ require 'chef/node'
24
+ require 'chef/api_client'
25
+
21
26
  class Chef
22
27
  class Knife
23
28
  class RackspaceServerDelete < Knife
@@ -26,31 +31,63 @@ class Chef
26
31
 
27
32
  banner "knife rackspace server delete SERVER_ID [SERVER_ID] (options)"
28
33
 
34
+ option :purge,
35
+ :short => "-P",
36
+ :long => "--purge",
37
+ :boolean => true,
38
+ :default => false,
39
+ :description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the Rackspace node itself. Assumes node and client have the same name as the server (if not, add the '--node-name' option)."
40
+
41
+ option :chef_node_name,
42
+ :short => "-N NAME",
43
+ :long => "--node-name NAME",
44
+ :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."
45
+
46
+ # Extracted from Chef::Knife.delete_object, because it has a
47
+ # confirmation step built in... By specifying the '--purge'
48
+ # flag (and also explicitly confirming the server destruction!)
49
+ # the user is already making their intent known. It is not
50
+ # necessary to make them confirm two more times.
51
+ def destroy_item(klass, name, type_name)
52
+ begin
53
+ object = klass.load(name)
54
+ object.destroy
55
+ ui.warn("Deleted #{type_name} #{name}")
56
+ rescue Net::HTTPServerException
57
+ ui.warn("Could not find a #{type_name} named #{name} to delete!")
58
+ end
59
+ end
60
+
29
61
  def run
30
62
  @name_args.each do |instance_id|
31
-
32
- server = connection.servers.get(instance_id)
63
+ begin
64
+ server = connection.servers.get(instance_id)
65
+ msg_pair("Instance ID", server.id)
66
+ msg_pair("Host ID", server.host_id)
67
+ msg_pair("Name", server.name)
68
+ msg_pair("Flavor", server.flavor.name)
69
+ msg_pair("Image", server.image.name)
70
+ msg_pair("Public IP Address", server.addresses["public"][0])
71
+ msg_pair("Private IP Address", server.addresses["private"][0])
33
72
 
34
- msg("Instance ID", server.id.to_s)
35
- msg("Host ID", server.host_id)
36
- msg("Name", server.name)
37
- msg("Flavor", server.flavor.name)
38
- msg("Image", server.image.name)
39
- msg("Public DNS Name", server.addresses["public"][0])
40
- msg("Private IP Address", server.addresses["private"][0])
73
+ puts "\n"
74
+ confirm("Do you really want to delete this server")
41
75
 
42
- puts "\n"
43
- confirm("Do you really want to delete this server")
76
+ server.destroy
44
77
 
45
- server.destroy
78
+ ui.warn("Deleted server #{server.id}")
46
79
 
47
- ui.warn("Deleted server #{server.id} named #{server.name}")
48
- end
49
- end
80
+ if config[:purge]
81
+ thing_to_delete = config[:chef_node_name] || instance_id
82
+ destroy_item(Chef::Node, thing_to_delete, "node")
83
+ destroy_item(Chef::ApiClient, thing_to_delete, "client")
84
+ else
85
+ ui.warn("Corresponding node and client for the #{instance_id} server were not deleted and remain registered with the Chef Server")
86
+ end
50
87
 
51
- def msg(label, value)
52
- if value && !value.empty?
53
- puts "#{ui.color(label, :cyan)}: #{value}"
88
+ rescue NoMethodError
89
+ ui.error("Could not locate server '#{instance_id}'.")
90
+ end
54
91
  end
55
92
  end
56
93
  end
@@ -49,7 +49,7 @@ class Chef
49
49
  case server.state.downcase
50
50
  when 'deleted','suspended'
51
51
  ui.color(server.state.downcase, :red)
52
- when 'build'
52
+ when 'build','unknown'
53
53
  ui.color(server.state.downcase, :yellow)
54
54
  else
55
55
  ui.color(server.state.downcase, :green)
@@ -1,6 +1,6 @@
1
1
  module Knife
2
2
  module Rackspace
3
- VERSION = "0.5.14"
3
+ VERSION = "0.5.16"
4
4
  MAJOR, MINOR, TINY = VERSION.split('.')
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-rackspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.14
4
+ version: 0.5.16
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,11 +11,11 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-05-15 00:00:00.000000000Z
14
+ date: 2012-09-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: fog
18
- requirement: &70301854701640 !ruby/object:Gem::Requirement
18
+ requirement: !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
21
  - - ~>
@@ -23,10 +23,15 @@ dependencies:
23
23
  version: '1.3'
24
24
  type: :runtime
25
25
  prerelease: false
26
- version_requirements: *70301854701640
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ version: '1.3'
27
32
  - !ruby/object:Gem::Dependency
28
33
  name: chef
29
- requirement: &70301854701140 !ruby/object:Gem::Requirement
34
+ requirement: !ruby/object:Gem::Requirement
30
35
  none: false
31
36
  requirements:
32
37
  - - ! '>='
@@ -34,7 +39,12 @@ dependencies:
34
39
  version: 0.10.10
35
40
  type: :runtime
36
41
  prerelease: false
37
- version_requirements: *70301854701140
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.10.10
38
48
  description: Rackspace Support for Chef's Knife Command
39
49
  email:
40
50
  - adam@opscode.com
@@ -80,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
90
  version: '0'
81
91
  requirements: []
82
92
  rubyforge_project:
83
- rubygems_version: 1.8.17
93
+ rubygems_version: 1.8.24
84
94
  signing_key:
85
95
  specification_version: 3
86
96
  summary: Rackspace Support for Chef's Knife Command