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 +8 -2
- data/knife-joyent.gemspec +1 -1
- data/lib/chef/knife/joyent_base.rb +2 -2
- data/lib/chef/knife/joyent_server_create.rb +106 -58
- data/lib/chef/knife/joyent_server_delete.rb +1 -1
- data/lib/knife-joyent/version.rb +1 -1
- metadata +6 -5
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.
|
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
|
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
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
-
|
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
|
-
|
158
|
-
|
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 #{
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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
|
-
|
188
|
-
|
189
|
-
|
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,
|
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,
|
203
|
+
def bootstrap_for_node(server, bootstrap_ip)
|
206
204
|
bootstrap = Chef::Knife::Bootstrap.new
|
207
|
-
Chef::Log.debug("Bootstrap name_args = [ #{
|
208
|
-
bootstrap.name_args = [
|
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
|
data/lib/knife-joyent/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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.
|
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
|