knife-joyent 0.1.3 → 0.1.4

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.
data/README.md CHANGED
@@ -66,10 +66,10 @@ or, your ssh key
66
66
 
67
67
  **joyent_api_url**
68
68
 
69
- Specify a custom API endpoint, this is required if you want to specify
69
+ Specify a custom API endpoint, this is required if you want to specify
70
70
  where you want to provision your machines, or if you are using knife with a
71
71
  provider powered by [SmartDataCenter](http://www.joyent.com/products/smartdatacenter/).
72
-
72
+
73
73
  # Defaults to https://us-west-1.api.joyentcloud.com/
74
74
  knife[:joyent_api_url] = "https://us-sw-1.api.joyentcloud.com/"
75
75
 
@@ -83,6 +83,12 @@ the form of a hash with a single level of nesting. See the
83
83
  "some_data" => "value"
84
84
  }
85
85
 
86
+ **provisioner**
87
+
88
+ Machines provisioned will be tagged with key ``provisioner`` containing the value specified.
89
+ This is useful for tracking source of provisions for accounts where machines are provisioned
90
+ by/from different sources / users.
91
+
86
92
  ## Contributors
87
93
 
88
94
  - [Sean Omera](https://github.com/someara) - Opscode
data/knife-joyent.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.add_dependency "fog", "~> 1.6"
19
+ s.add_dependency "fog", "~> 1.11"
20
20
  s.add_dependency "chef", ">= 0.10.10"
21
21
  s.require_paths = ["lib"]
22
22
 
@@ -21,7 +21,7 @@ class Chef
21
21
 
22
22
  option :joyent_password,
23
23
  :short => '-P PASSWORD',
24
- :long => '--joyent-password PASSOWRD',
24
+ :long => '--joyent-password PASSWORD',
25
25
  :description => 'Your Joyent password',
26
26
  :proc => Proc.new {|key| Chef::Config[:knife][:joyent_password] = key }
27
27
 
@@ -45,7 +45,7 @@ class Chef
45
45
 
46
46
  def connection
47
47
  @connection ||= begin
48
- connection = Fog::Compute.new(
48
+ Fog::Compute.new(
49
49
  :provider => 'Joyent',
50
50
  :joyent_username => Chef::Config[:knife][:joyent_username],
51
51
  :joyent_password => Chef::Config[:knife][:joyent_password],
@@ -108,31 +108,26 @@ class Chef
108
108
  return (block_a.include?(ip) or block_b.include?(ip) or block_c.include?(ip))
109
109
  end
110
110
 
111
- # wait for ssh to come up
112
111
  def tcp_test_ssh(hostname)
113
- tcp_socket = TCPSocket.new(hostname, 22)
114
- readable = IO.select([tcp_socket], nil, nil, 5)
115
- if readable
116
- Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
117
- yield
118
- true
119
- else
120
- false
121
- end
122
- rescue Errno::ETIMEDOUT
123
- false
124
- rescue Errno::EPERM
125
- false
126
- rescue Errno::ECONNREFUSED
127
- sleep 2
128
- false
129
- rescue Errno::EHOSTUNREACH
130
- sleep 2
131
- false
132
- ensure
133
- tcp_socket && tcp_socket.close
112
+ ssh_test_max = 10*60
113
+ ssh_test = 0
114
+
115
+ begin
116
+ if ssh_test < ssh_test_max
117
+ print(".")
118
+ ssh_test += 1
119
+ sleep 1
120
+ else
121
+ ui.error("Unable to ssh to node (#{bootstrap_ip_address}), exiting")
122
+ exit 1
123
+ end
124
+ end until _tcp_test_ssh(bootstrap_id) {
125
+ sleep @initial_sleep_delay ||= 10
126
+ puts("done")
127
+ }
134
128
  end
135
129
 
130
+
136
131
  def run
137
132
  $stdout.sync = true
138
133
 
@@ -151,45 +146,35 @@ class Chef
151
146
  print "\n#{ui.color("Waiting for server", :magenta)}"
152
147
  server.wait_for { print "."; ready? }
153
148
 
154
- #which IP address to bootstrap
155
- bootstrap_ip_addresses = server.ips.select{ |ip| ip and not(is_loopback(ip) or is_linklocal(ip)) }
149
+ bootstrap_ip = self.determine_bootstrap_ip(server)
156
150
 
157
- if bootstrap_ip_addresses.count == 1
158
- bootstrap_ip_address = bootstrap_ip_addresses.first
159
- else
160
- if config[:private_network]
161
- bootstrap_ip_address = bootstrap_ip_addresses.find{|ip| is_private(ip)}
162
- else
163
- bootstrap_ip_address = bootstrap_ip_addresses.find{|ip| not is_private(ip)}
164
- end
165
- end
166
-
167
- Chef::Log.debug("Bootstrap IP Address #{bootstrap_ip_address}")
168
- if bootstrap_ip_address.nil?
151
+ Chef::Log.debug("Bootstrap IP Address #{bootstrap_ip}")
152
+ unless bootstrap_ip
169
153
  ui.error("No IP address available for bootstrapping.")
170
154
  exit 1
171
155
  end
172
156
 
173
- puts ui.color("attempting to bootstrap on #{bootstrap_ip_address}", :cyan)
174
-
175
- ssh_test_max = 10*60
176
- ssh_test = 0
177
-
178
- begin
179
- if ssh_test < ssh_test_max
180
- print(".")
181
- ssh_test += 1
182
- sleep 1
183
- else
184
- ui.error("Unable to ssh to node (#{bootstrap_ip_address}), exiting")
185
- exit 1
157
+ puts ui.color("attempting to bootstrap on #{bootstrap_ip}", :cyan)
158
+
159
+ if Chef::Config[:knife][:provisioner]
160
+ # tag the provision with 'provisioner'
161
+ tagkey = 'provisioner'
162
+ tagvalue = Chef::Config[:knife][:provisioner]
163
+ tags = [
164
+ ui.color('Name', :bold),
165
+ ui.color('Value', :bold),
166
+ ]
167
+ server.add_tags({tagkey => tagvalue}).each do |k, v|
168
+ tags << k
169
+ tags << v
186
170
  end
187
- end until tcp_test_ssh(bootstrap_ip_address) {
188
- sleep @initial_sleep_delay ||= 10
189
- puts("done")
190
- }
171
+ puts ui.color("Updated tags for #{node_name}", :cyan)
172
+ puts ui.list(tags, :uneven_columns_across, 2)
173
+ else
174
+ puts ui.color("No user defined in knife config for provision tagging", :magenta)
175
+ end
191
176
 
192
- bootstrap_for_node(server, bootstrap_ip_address).run
177
+ bootstrap_for_node(server, bootstrap_ip).run
193
178
 
194
179
  puts ui.color("Created machine:", :cyan)
195
180
  msg_pair("ID", server.id.to_s)
@@ -197,39 +182,77 @@ class Chef
197
182
  msg_pair("State", server.state)
198
183
  msg_pair("Type", server.type)
199
184
  msg_pair("Dataset", server.dataset)
200
- msg_pair("IP's", server.ips)
185
+ msg_pair("IP's", server.ips.join(" "))
201
186
  msg_pair("JSON Attributes",config[:json_attributes]) unless config[:json_attributes].empty?
187
+
188
+ rescue Excon::Errors::Conflict => e
189
+ if e.response && e.response.body.kind_of?(String)
190
+ error = ::Fog::JSON.decode(e.response.body)
191
+ puts ui.error(error['message'])
192
+ exit 1
193
+ else
194
+ puts ui.error(e.message)
195
+ exit 1
196
+ end
197
+ rescue => e
198
+ puts ui.error('Unexpected Error Occured:' + e.message)
199
+ exit 1
202
200
  end
203
201
 
204
202
  # Run Chef bootstrap script
205
- def bootstrap_for_node(server, bootstrap_ip_address)
203
+ def bootstrap_for_node(server, bootstrap_ip)
206
204
  bootstrap = Chef::Knife::Bootstrap.new
207
- Chef::Log.debug("Bootstrap name_args = [ #{bootstrap_ip_address} ]")
208
- bootstrap.name_args = [ bootstrap_ip_address ]
205
+ Chef::Log.debug("Bootstrap name_args = [ #{bootstrap_ip} ]")
206
+ bootstrap.name_args = [ bootstrap_ip ]
207
+
209
208
  Chef::Log.debug("Bootstrap run_list = #{config[:run_list]}")
210
209
  bootstrap.config[:run_list] = config[:run_list]
210
+
211
211
  Chef::Log.debug("Bootstrap ssh_user = #{config[:ssh_user]}")
212
212
  bootstrap.config[:ssh_user] = config[:ssh_user]
213
+
213
214
  Chef::Log.debug("Bootstrap identity_file = #{config[:identity_file]}")
214
215
  bootstrap.config[:identity_file] = config[:identity_file]
216
+
215
217
  Chef::Log.debug("Bootstrap chef_node_name = #{config[:chef_node_name]}")
216
218
  bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.id
219
+
217
220
  Chef::Log.debug("Bootstrap prerelease = #{config[:prerelease]}")
218
221
  bootstrap.config[:prerelease] = config[:prerelease]
222
+
219
223
  Chef::Log.debug("Bootstrap distro = #{config[:distro]}")
220
224
  bootstrap.config[:distro] = config[:distro]
225
+
221
226
  #Chef::Log.debug("Bootstrap use_sudo = #{config[:use_sudo]}")
222
227
  #bootstrap.config[:use_sudo] = true
228
+
223
229
  Chef::Log.debug("Bootstrap environment = #{config[:environment]}")
224
230
  bootstrap.config[:environment] = config[:environment]
231
+
225
232
  Chef::Log.debug("Bootstrap no_host_key_verify = #{config[:no_host_key_verify]}")
226
233
  bootstrap.config[:no_host_key_verify] = config[:no_host_key_verify]
234
+
227
235
  Chef::Log.debug("Bootstrap json_attributes = #{config[:json_attributes]}")
228
236
  bootstrap.config[:first_boot_attributes] = config[:json_attributes]
229
237
 
230
238
  bootstrap
231
239
  end
232
240
 
241
+ def determine_bootstrap_ip(server)
242
+ server_ips = server.ips.select{ |ip|
243
+ ip and not(is_loopback(ip) or is_linklocal(ip))
244
+ }
245
+ if server_ips.count === 1
246
+ server_ips.first
247
+ else
248
+ if config[:private_network]
249
+ server_ips.find{|ip| is_private(ip)}
250
+ else
251
+ server_ips.find{|ip| not is_private(ip)}
252
+ end
253
+ end
254
+ end
255
+
233
256
  private
234
257
 
235
258
  def validate_server_name
@@ -248,6 +271,31 @@ class Chef
248
271
  return {} if metadata.empty?
249
272
  Hash[metadata.map { |k, v| ["metadata.#{k}", v] }]
250
273
  end
274
+
275
+ def _tcp_test_ssh(hostname)
276
+ tcp_socket = TCPSocket.new(hostname, 22)
277
+ readable = IO.select([tcp_socket], nil, nil, 5)
278
+ if readable
279
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
280
+ yield
281
+ true
282
+ else
283
+ false
284
+ end
285
+ rescue Errno::ETIMEDOUT
286
+ false
287
+ rescue Errno::EPERM
288
+ false
289
+ rescue Errno::ECONNREFUSED
290
+ sleep 2
291
+ false
292
+ rescue Errno::EHOSTUNREACH
293
+ sleep 2
294
+ false
295
+ ensure
296
+ tcp_socket && tcp_socket.close
297
+ end
298
+
251
299
  end
252
300
  end
253
301
  end
@@ -25,7 +25,7 @@ class Chef
25
25
  msg("State", server.state)
26
26
  msg("Type", server.type)
27
27
  msg("Dataset", server.dataset)
28
- msg("IP's", server.ips)
28
+ msg("IP's", server.ips.join(" "))
29
29
 
30
30
  unless server
31
31
  puts ui.error("Unable to locate server: #{id}")
@@ -1,3 +1,3 @@
1
1
  module KnifeJoyent
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-joyent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-15 00:00:00.000000000 Z
12
+ date: 2013-05-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.6'
21
+ version: '1.11'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '1.6'
29
+ version: '1.11'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: chef
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -101,8 +101,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
101
  version: '0'
102
102
  requirements: []
103
103
  rubyforge_project:
104
- rubygems_version: 1.8.21
104
+ rubygems_version: 1.8.25
105
105
  signing_key:
106
106
  specification_version: 3
107
107
  summary: Joyent CloudAPI Support for Chef's Knife Command
108
108
  test_files: []
109
+ has_rdoc: true