chef-provisioning-ssh 0.0.6 → 0.0.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0160449d53c76b17219f4ef4fe5dc8e55654e5d3
4
- data.tar.gz: bd6731b3071044c7208ba30180b420dca411e331
3
+ metadata.gz: f8be4eea284f7d7404c6fb4465f3b0abf8906b4f
4
+ data.tar.gz: 64b5600e5aeb58326cdfc8622d00f5c696f12863
5
5
  SHA512:
6
- metadata.gz: b7a9c1006367c1d1286687070656b949e964efae71ca7f4f24b8d8dee3b333306ad9bfac4a8bebc98b6b5505aedd223069f09e1371800bbed2c352b1f6c2e484
7
- data.tar.gz: deae4dfb868c0cbd77c2013475b6f75ada26fc9ab6001c21ea36806f16b8bf7503bd9d7af9ac30f70b5b2bcd2f7f521921ffb5b36defee4ce5bba911b58ff5c4
6
+ metadata.gz: 2604aabe0c9063ae30f99a712913bbe99415baa73d71f5f3f005506bb71e8c89176f6e9a4f55ae5b059e09402fab0089834229cd918fef5e7fb05abdea68eff5
7
+ data.tar.gz: cebce0acee1c06106a10fe291345d48766d86533e1e33ee8ff75ac118fae2071971784cbc8b81e73ac206006527ba878dddeb7cd0df61895f5757be7ea0c851a
@@ -6,7 +6,7 @@ require 'chef/provisioning/machine/basic_machine'
6
6
  require 'chef/provisioning/machine/unix_machine'
7
7
  require 'chef/provisioning/machine/windows_machine'
8
8
  require 'chef/provisioning/convergence_strategy/install_msi'
9
- require 'chef/provisioning/convergence_strategy/install_cached'
9
+ require 'chef/provisioning/convergence_strategy/install_sh'
10
10
  require 'chef/provisioning/transport/winrm'
11
11
  require 'chef/provisioning/transport/ssh'
12
12
  require 'chef/provisioning/ssh_driver/version'
@@ -19,21 +19,8 @@ class Chef
19
19
  module SshDriver
20
20
  # Provisions Machines Using SSH.
21
21
  class Driver < Chef::Provisioning::Driver
22
+
22
23
  include Chef::Provisioning::SshDriver::Helpers
23
- # ## Parameters
24
- # cluster_path - path to the directory containing the vagrant files, which
25
- # should have been created with the vagrant_cluster resource.
26
-
27
- # Create a new ssh driver.
28
- #
29
- # ## Parameters
30
- # cluster_path - path to the directory containing the vagrant files, which
31
- # should have been created with the vagrant_cluster resource.
32
- def initialize(driver_url, config)
33
- super
34
- scheme, cluster_path = driver_url.split(':', 2)
35
- @cluster_path = cluster_path
36
- end
37
24
 
38
25
  attr_reader :cluster_path
39
26
 
@@ -41,6 +28,12 @@ class Chef
41
28
  Driver.new(driver_url, config)
42
29
  end
43
30
 
31
+ def initialize(driver_url, config)
32
+ super(driver_url, config)
33
+ scheme, cluster_path = driver_url.split(':', 2)
34
+ @cluster_path = cluster_path
35
+ end
36
+
44
37
  def self.canonicalize_url(driver_url, config)
45
38
  scheme, cluster_path = driver_url.split(':', 2)
46
39
  cluster_path = File.expand_path(cluster_path || File.join(Chef::Config.config_dir, 'provisioning/ssh'))
@@ -48,479 +41,294 @@ class Chef
48
41
  end
49
42
 
50
43
  def allocate_machine(action_handler, machine_spec, machine_options)
51
- ensure_ssh_cluster(action_handler) unless ::File.exists?(cluster_path)
52
-
53
- log_info("SSH Driver - allocate_machine - machine_spec = #{machine_spec.inspect}")
54
- log_info("SSH Driver - allocate_machine - machine_options = #{machine_options['transport_options']}")
55
- log_info("SSH Driver - allocate_machine - machine_options = #{machine_options.configs}")
56
-
57
- new_machine = false
58
- new_machine_options = {}
59
- current_machine_options = false
60
-
61
- if machine_options[:transport_options] && machine_options[:transport_options]['is_windows']
62
-
44
+ existing_machine = existing_ssh_machine(machine_spec)
45
+ if !existing_machine
46
+ validate_machine_options(action_handler, machine_spec, machine_options)
47
+ ensure_ssh_cluster(action_handler)
48
+ ssh_machine = create_ssh_machine(action_handler, machine_spec, machine_options)
63
49
  machine_spec.location = {
64
50
  'driver_url' => driver_url,
65
51
  'driver_version' => Chef::Provisioning::SshDriver::VERSION,
66
52
  'target_name' => machine_spec.name,
67
- 'ssh_file_path' => "#{cluster_path}/#{machine_spec.name}.json",
53
+ 'ssh_machine_file' => ssh_machine,
68
54
  'allocated_at' => Time.now.utc.to_s
69
55
  }
70
-
71
- else
72
-
73
- if machine_options[:transport_options]
74
- new_machine_options['transport_options'] = machine_options[:transport_options]
75
- elsif machine_options['transport_options']
76
- new_machine_options['transport_options'] = machine_options['transport_options']
77
- end
78
-
79
- if machine_options[:convergence_options]
80
- new_machine_options['convergence_options'] = machine_options[:convergence_options]
81
- elsif machine_options['convergence_options']
82
- new_machine_options['convergence_options'] = machine_options['convergence_options']
83
- end
84
-
85
- if machine_spec.location && ssh_machine_exists?(machine_spec.name)
86
- _current_machine_options = existing_machine_hash(machine_spec)
87
- current_machine_options = stringify_keys(_current_machine_options.dup)
88
- end
89
-
90
- log_info "machine_spec.name #{machine_spec.name}"
91
-
92
- log_info "new_machine_options #{new_machine_options} \n\n current_machine_options #{current_machine_options}"
93
-
94
-
95
- machine_file_hash = updated_ssh_machine_file_hash(stringify_keys(new_machine_options),
96
- stringify_keys(current_machine_options))
97
-
98
- raise 'machine File Hash Is Empty' unless machine_file_hash
99
- log_info("machine HASH = #{machine_file_hash}")
100
-
101
- if machine_file_hash && machine_file_hash['transport_options']
102
- host_for(machine_file_hash['transport_options'])
103
- initialize_ssh(machine_file_hash['transport_options'])
104
- end
105
-
106
- machine_updated = create_ssh_machine_file(action_handler,
107
- machine_spec.name,
108
- machine_file_hash)
109
- machine_options_for(machine_file_hash)
110
-
111
- log_info("STRIPPED machine HASH = #{machine_file_hash}")
112
- log_info("UNSTRIPPED machine HASH = #{machine_file_hash}")
113
- log_info "machine_options_for #{machine_options_for}"
114
-
115
- if machine_updated || !machine_spec.location
116
- machine_spec.location = {
117
- 'driver_url' => driver_url,
118
- 'driver_version' => Chef::Provisioning::SshDriver::VERSION,
119
- 'target_name' => machine_spec.name,
120
- 'ssh_file_path' => "#{cluster_path}/#{machine_spec.name}.json",
121
- 'allocated_at' => Time.now.utc.to_s
122
- }
123
-
124
- # if machine_options[:transport_options]
125
- # %w(winrm.host winrm.port winrm.username winrm.password).each do |key|
126
- # machine_spec.location[key] = machine_options[:transport_options][key] if machine_options[:vagrant_options][key]
127
- # end
128
- # end
129
-
130
- log_info("machine_spec.location= #{machine_spec.location}")
131
- end
132
56
  end
133
57
  end
134
58
 
135
59
  def ready_machine(action_handler, machine_spec, machine_options)
136
- allocate_machine(action_handler, machine_spec, machine_options)
137
- if machine_options[:transport_options] && machine_options[:transport_options]['is_windows']
138
- machine_for(machine_spec, machine_options)
139
- else
140
- machine_for(machine_spec, machine_options_for)
60
+ ssh_machine = existing_ssh_machine(machine_spec)
61
+
62
+ if !ssh_machine
63
+ raise "SSH Machine #{machine_spec.name} does not have a machine file associated with it!"
141
64
  end
65
+
66
+ wait_for_transport(action_handler, ssh_machine, machine_spec, machine_options)
67
+ machine_for(machine_spec, machine_options)
142
68
  end
143
69
 
144
70
  def connect_to_machine(machine_spec, machine_options)
145
- if machine_options[:transport_options] && machine_options[:transport_options]['is_windows']
146
- machine_for(machine_spec, machine_options)
147
- else
148
- if machine_spec.location && ssh_machine_exists?(machine_spec.name)
149
- _current_machine_options = existing_machine_hash(machine_spec)
150
- current_machine_options = stringify_keys(_current_machine_options.dup)
151
- end
152
- host_for(current_machine_options['transport_options'])
153
- initialize_ssh(current_machine_options['transport_options'])
154
- machine_for(machine_spec, machine_options_for(current_machine_options))
155
- end
71
+ machine_for(machine_spec, machine_options)
156
72
  end
157
73
 
158
74
  def destroy_machine(action_handler, machine_spec, machine_options)
159
- delete_ssh_machine_file(action_handler, existing_ssh_machine_file(machine_spec.name))
160
- # allocate_machine(action_handler, machine_spec, machine_options)
161
- # convergence_strategy_for(node).delete_chef_objects(action_handler, node)
75
+ ssh_machine = existing_ssh_machine(machine_spec)
76
+
77
+ if !ssh_machine
78
+ raise "SSH Machine #{machine_spec.name} does not have a machine file associated with it!"
79
+ end
80
+
81
+
162
82
  end
163
83
 
164
84
  def stop_machine(action_handler, machine_spec, machine_options)
165
- #
166
- # What to do What to do.
167
- #
168
- # On one level there's really only one thing to do here,
169
- # shellout and halt, or shutdown -h now,
170
- # maybe provide abitily to pass some shutdown options
171
- #
172
- # But be vewwy vewwy careful:
173
- #
174
- # you better have console...
175
- # or be close to your datacenter
176
- #
177
- end
85
+ ssh_machine = existing_ssh_machine(machine_spec)
178
86
 
179
- def restart_machine(action_handler, machine_spec, machine_options)
180
- # allocate_machine(action_handler, machine_spec, machine_options)
181
- # Full Restart, POST BIOS and all
182
- end
87
+ if !ssh_machine
88
+ raise "SSH Machine #{machine_spec.name} does not have a machine file associated with it!"
89
+ end
183
90
 
184
- def reload_machine(action_handler, machine_spec, machine_options)
185
- # allocate_machine(action_handler, machine_spec, machine_options)
186
- # Use `kexec` here to skip POST and BIOS and all that noise.
91
+ action_handler.report_progress("SSH Machine #{machine_spec.name} is existing hardware login and power off.")
187
92
  end
188
93
 
189
- # protected
94
+ def machine_for(machine_spec, machine_options)
95
+ ssh_machine = existing_ssh_machine(machine_spec)
190
96
 
191
- def ensure_ssh_cluster(action_handler)
192
- _cluster_path = cluster_path
193
- Chef::Provisioning.inline_resource(action_handler) do
194
- ssh_cluster _cluster_path
97
+ if !ssh_machine
98
+ raise "SSH Machine #{machine_spec.name} does not have a machine file associated with it!"
99
+ end
100
+
101
+ if ssh_machine[:is_windows]
102
+ Chef::Provisioning::Machine::WindowsMachine.new(machine_spec,
103
+ transport_for(ssh_machine),
104
+ convergence_strategy_for(ssh_machine))
105
+ else
106
+ Chef::Provisioning::Machine::UnixMachine.new(machine_spec,
107
+ transport_for(ssh_machine),
108
+ convergence_strategy_for(ssh_machine))
195
109
  end
196
110
  end
197
111
 
198
- def existing_machine_hash(machine_spec)
199
- raise("You Must Pass machine_spec unless existing_machine_hash exists") unless machine_spec
200
- if ssh_machine_exists?(machine_spec.name)
201
- existing_machine_hash = JSON.parse(File.read(existing_ssh_machine_file(machine_spec.name)))
202
- existing_machine_hash
203
- # else
204
- # return false
205
- # # raise('We have machine_spec.location but have no machine_spec.location["ssh_file_path"]. WTF?')
206
- # end
112
+ def transport_for(ssh_machine)
113
+ if ssh_machine[:is_windows]
114
+ create_winrm_transport(ssh_machine)
207
115
  else
208
- return false
116
+ create_ssh_transport(ssh_machine)
209
117
  end
210
118
  end
211
119
 
212
- def delete_ssh_machine_file(action_handler, registry_file)
213
- log_info("registry_file = #{registry_file}")
214
- if ::File.exists?(registry_file)
215
- Chef::Provisioning.inline_resource(action_handler) do
216
- file registry_file do
217
- action :delete
218
- end
219
- end
120
+ def convergence_strategy_for(ssh_machine)
121
+ if ssh_machine[:is_windows]
122
+ Chef::Provisioning::ConvergenceStrategy::InstallMsi.
123
+ new(ssh_machine[:convergence_options], config)
124
+ else
125
+ Chef::Provisioning::ConvergenceStrategy::InstallSh.
126
+ new(ssh_machine[:convergence_options], config)
220
127
  end
221
128
  end
222
129
 
223
- def ssh_machine_exists?(target_name)
224
- ::File.exists?(existing_ssh_machine_file(target_name))
130
+ def create_ssh_transport(ssh_machine)
131
+ hostname = ssh_machine[:transport_options][:host] ||
132
+ ssh_machine[:transport_options][:ip_address]
133
+ username = ssh_machine[:transport_options][:username]
134
+ ssh_options = ssh_machine[:transport_options][:ssh_options] ?
135
+ ssh_machine[:transport_options][:ssh_options] : {}
136
+ options = ssh_machine[:transport_options][:options] ?
137
+ ssh_machine[:transport_options][:options] : {}
138
+ Chef::Provisioning::Transport::SSH.new(hostname, username,
139
+ ssh_options, {:prefix => 'sudo '}, config)
225
140
  end
226
141
 
227
- def existing_ssh_machine_file(target_name)
228
- existing_ssh_machine_file = ::File.join(@cluster_path, "#{target_name}.json")
229
- existing_ssh_machine_file
142
+ def create_winrm_transport(ssh_machine)
143
+ # TODO IPv6 loopback? What do we do for that?
144
+ hostname = ssh_machine[:transport_options][:host] ||
145
+ ssh_machine[:transport_options][:ip_address]
146
+ port = ssh_machine[:transport_options][:port] || 5985
147
+ # port = forwarded_ports[port] if forwarded_ports[port]
148
+ endpoint = "http://#{hostname}:#{port}/wsman"
149
+ type = :plaintext
150
+ options = {
151
+ :user => ssh_machine[:transport_options][:username],
152
+ :pass => ssh_machine[:transport_options][:password],
153
+ :disable_sspi => true
154
+ }
155
+
156
+ Chef::Provisioning::Transport::WinRM.new(endpoint, type, options, config)
230
157
  end
231
158
 
232
- def create_ssh_machine_file(action_handler, target_name, use_machine_options)
233
- log_info("File is = #{::File.join(@cluster_path, "#{target_name}.json")}")
234
- log_info("current_machine_options = #{use_machine_options.to_s}")
235
- stringify_keys(use_machine_options)
236
- file_path = existing_ssh_machine_file(target_name)
237
- options_parsed = ::JSON.parse(use_machine_options.to_json)
238
- json_machine_options = ::JSON.pretty_generate(options_parsed)
239
- Chef::Provisioning.inline_resource(action_handler) do
240
- file file_path do
241
- content json_machine_options
159
+ def wait_for_transport(action_handler, ssh_machine, machine_spec, machine_options)
160
+ time_elapsed = 0
161
+ sleep_time = 10
162
+ max_wait_time = 120
163
+ transport = transport_for(ssh_machine)
164
+ unless transport.available?
165
+ if action_handler.should_perform_actions
166
+ action_handler.report_progress "waiting for #{machine_spec.name} (#{ssh_machine[:transport_options][:ip_address]} on #{driver_url}) to be connectable (transport up and running) ..."
167
+ while time_elapsed < max_wait_time && !transport.available?
168
+ action_handler.report_progress "been waiting #{time_elapsed}/#{max_wait_time} -- sleeping #{sleep_time} seconds for #{machine_spec.name} (#{ssh_machine[:transport_options][:ip_address]} on #{driver_url}) to be connectable ..."
169
+ sleep(sleep_time)
170
+ time_elapsed += sleep_time
171
+ end
172
+ unless transport.available?
173
+ raise "Machine #{machine_spec.name} (#{ssh_machine[:transport_options][:ip_address]} on #{driver_url}) did not become ready within 120 seconds"
174
+ end
175
+ action_handler.report_progress "#{machine_spec.name} is now connectable"
242
176
  end
243
177
  end
244
178
  end
245
179
 
246
- def updated_ssh_machine_file_hash(new_machine_options, current_machine_options)
247
- log_info "updated_ssh_machine_file_hash --\nnew_machine_options = #{new_machine_options}\ncurrent_machine_options = #{current_machine_options}"
248
- if new_machine_options && new_machine_options['convergence_options']
249
- use_convergence_options = new_machine_options['convergence_options']
250
- else
251
- use_convergence_options = false
252
- end
180
+ def validate_machine_options(action_handler, machine_spec, machine_options)
181
+ error_msgs = []
182
+ valid = true
253
183
 
254
- if new_machine_options && new_machine_options['transport_options']
255
- new_transport_options = new_machine_options['transport_options']
184
+ if !machine_options[:transport_options]
185
+ error_msgs << ":transport_options required."
186
+ valid = false
256
187
  else
257
- false
258
- end
188
+ if machine_options[:transport_options][:is_windows]
189
+ # Validate Windows Options.
190
+ req_and_valid_fields = [:is_windows, [:host, :ip_address], :username, :password]
191
+ one_of_fields = req_and_valid_fields.select{ |i| i.kind_of?(Array)}
192
+
193
+ missing = req_and_valid_fields.flatten - machine_options[:transport_options].keys
194
+
195
+ for oof in one_of_fields
196
+ if oof == oof & missing
197
+ error_msgs << ":transport_options => :#{oof.join(" or :")} required."
198
+ end
199
+ missing -= oof
200
+ end
259
201
 
260
- if current_machine_options && current_machine_options['transport_options']
261
- current_transport_options = current_machine_options['transport_options']
262
- else
263
- current_transport_options = new_transport_options
264
- end
265
- transport_options_hash = updated_transport_options_hash(new_transport_options,
266
- current_transport_options)
267
- new_hash = {}
268
- new_hash['convergence_options'] = use_convergence_options if use_convergence_options
269
- new_hash['transport_options'] = transport_options_hash
270
- stringify_keys(new_hash)
271
- return new_hash
272
- end
202
+ for missed in missing do
203
+ error_msgs << ":transport_options => :#{missed} required."
204
+ valid = false
205
+ end
273
206
 
274
- def updated_transport_options_hash(new_transport_options, current_transport_options = false)
275
- log_info "updated_transport_options_hash - new_transport_options if #{new_transport_options}"
276
- current_transport_options = new_transport_options unless current_transport_options
207
+ extras = machine_options[:transport_options].keys - req_and_valid_fields.flatten
277
208
 
278
- new_ip = new_transport_options['ip_address'] rescue false
279
- current_ip = current_transport_options['ip_address'] rescue false
280
- if (new_ip && current_ip)
281
- raise 'IP Addr Does not match' unless (new_ip == current_ip)
282
- end
283
- ip_address = (current_ip || new_ip)
284
-
285
- new_hostname = new_transport_options['hostname'] rescue false
286
- current_hostname = current_transport_options['hostname'] rescue false
287
- hostname = (current_hostname || new_hostname)
288
-
289
- new_host = new_transport_options['host'] rescue false
290
- current_host = current_transport_options['host'] rescue false
291
- given_host = (current_host || new_host)
292
-
293
- raise 'We Gots No IP or Hostname. So, um, yeah.' unless (hostname ||
294
- ip_address ||
295
- given_host)
296
-
297
- new_username = new_transport_options['username'] rescue false
298
- new_ssh_options_user = new_transport_options['ssh_options']['user'] rescue false
299
- current_username = current_transport_options['username'] rescue false
300
- current_ssh_options_user = current_transport_options['ssh_options']['user'] rescue false
301
- username = (current_username || current_ssh_options_user || new_username ||new_ssh_options_user)
302
-
303
- opts = {}
304
- opts['host'] = given_host if given_host
305
- opts['hostname'] = hostname if hostname
306
- opts['ip_address'] = ip_address if ip_address
307
- host = host_for(opts)
308
-
309
- current_transport_options ||= {}
310
- current_transport_options['ssh_options'] ||= {}
311
- current_transport_options['ssh_options']['keys'] = [] unless current_transport_options['ssh_options']['keys']
312
- new_transport_options ||= {}
313
- new_transport_options['ssh_options'] ||= {}
314
- new_transport_options['ssh_options']['user'] = username
315
- new_transport_options['ssh_options']['keys'] = [] unless new_transport_options['ssh_options']['keys']
316
- new_keys = Array(current_transport_options['ssh_options']['keys']).concat( Array(new_transport_options['ssh_options']['keys']) ) || false
317
- log_info("new_keys = #{new_keys}")
318
-
319
- new_hash = {}
320
- new_hash['host'] = host
321
- new_hash['ip_address'] = ip_address if ip_address
322
- new_hash['hostname'] = hostname if hostname
323
- new_hash['ssh_options'] = {}
324
- new_hash['ssh_options']['keys'] = new_keys if new_keys
325
- if new_transport_options && new_transport_options['ssh_options']
326
- new_hash['ssh_options']['password'] = new_transport_options['password'] if new_transport_options['password']
327
- end
209
+ for extra in extras do
210
+ error_msgs << ":transport_options => :#{extra} not allowed."
211
+ valid = false
212
+ end
213
+ else
214
+ # Validate Unix Options
215
+ req_fields = [[:host, :ip_address], :username]
216
+ one_of_fields = req_fields.select{ |i| i.kind_of?(Array)}
217
+
218
+ missing = req_fields.flatten - machine_options[:transport_options].keys
219
+
220
+ for oof in one_of_fields
221
+ if oof == oof & missing
222
+ error_msgs << ":transport_options => :#{oof.join(" or :")} required."
223
+ end
224
+ missing -= oof
225
+ end
328
226
 
329
- merged_transport_options = Chef::Mixin::DeepMerge.merge(current_transport_options.to_hash, new_transport_options.to_hash)
330
- _merged_transport_options = merged_transport_options.dup
331
- updated_transport_options_hash = _merged_transport_options.dup
332
- updated_transport_options_hash = Chef::Mixin::DeepMerge.merge(merged_transport_options, new_hash) unless new_hash.empty?
333
- ensure_has_keys_or_password(updated_transport_options_hash)
334
- log_info "updated_transport_options_hash = #{updated_transport_options_hash}"
335
- updated_transport_options_hash
336
- end
227
+ for missed in missing do
228
+ error_msgs << ":transport_options => :#{missed} required."
229
+ valid = false
230
+ end
337
231
 
338
- def ensure_has_keys_or_password(transport_hash = false)
339
- if transport_hash && transport_hash['ssh_options']
340
- ssh_hash = transport_hash['ssh_options']
341
- keys = ssh_hash['keys'] || false
342
- password = ssh_hash['password'] || false
343
- has_either = (password || (keys && !keys.empty?))
344
- else
345
- has_either = false
346
- end
347
- raise 'No Keys OR Password, No Can Do Compadre' unless has_either
348
- return has_either ? true : false
349
- end
232
+ valid_fields = [:is_windows, :host, :ip_address, :username, :ssh_options, :options]
350
233
 
351
- def host_for(_transport_options)
352
- @target_host = false
353
- log_info "_transport_options #{_transport_options}"
354
- transport_options = stringify_keys(_transport_options)
355
-
356
- target_ip = transport_options['ip_address'] || false
357
- target_fqdn = transport_options['hostname'] || false
358
- target_host = transport_options['host'] || false
359
-
360
- raise "no target_ip or target_fqdn given" unless(target_ip ||
361
- target_host ||
362
- target_fqdn )
363
- if target_ip
364
- raise 'Invalid IP' unless ( target_ip =~ Resolv::IPv4::Regex ||
365
- target_ip =~ Resolv::IPv6::Regex )
366
- @target_host = target_ip
367
- elsif target_fqdn
368
- rh = Resolv::Hosts.new
369
- rd = Resolv.new
370
- begin
371
- rh.getaddress(target_fqdn)
372
- in_hosts_file = true
373
- rescue
374
- in_hosts_file = false
375
- end
376
- begin
377
- rd.getaddress(target_fqdn)
378
- in_dns = true
379
- rescue
380
- in_dns = false
234
+ extras = machine_options[:transport_options].keys - valid_fields
235
+
236
+ for extra in extras do
237
+ error_msgs << ":transport_options => :#{extra} not allowed."
238
+ valid = false
239
+ end
240
+
241
+ if machine_options[:transport_options][:ssh_options]
242
+ valid_fields = valid_ssh_options
243
+
244
+ extras = machine_options[:transport_options][:ssh_options].keys - valid_fields
245
+
246
+ for extra in extras do
247
+ error_msgs << ":transport_options => ssh_options => :#{extra} not allowed."
248
+ valid = false
249
+ end
250
+ end
251
+
252
+ if machine_options[:transport_options][:options]
253
+ valid_fields = [:prefix, :ssh_pty_enable, :ssh_gateway]
254
+
255
+ extras = machine_options[:transport_options][:options].keys - valid_fields
256
+
257
+ for extra in extras do
258
+ error_msgs << ":transport_options => :options => :#{extra} not allowed."
259
+ valid = false
260
+ end
261
+ end
381
262
  end
382
- raise 'Unresolvable Hostname' unless (in_hosts_file || in_dns)
383
- @target_host = target_fqdn
384
- elsif target_host
385
- @target_host = target_host
386
- else
387
- raise "aint got no target yo, that dog dont hunt"
388
263
  end
389
- log_debug("get_target_connection_method - @target_host: #{@target_host}")
390
- @target_host
391
- end
392
264
 
393
- def can_connect?(_ssh_options, host)
265
+ if !valid
266
+ exception_string = "Machine Options for #{machine_spec.name} are invalid cannot create machine."
267
+ for string in error_msgs do
268
+ exception_string = "#{exception_string}\n #{string}"
269
+ end
270
+ raise exception_string
271
+ end
394
272
  end
395
273
 
396
- def initialize_ssh(transport_options, options = {})
397
- _transport_options_s = transport_options.dup
398
- _transport_options = symbolize_keys(_transport_options_s.dup)
399
- log_info "_transport_options is #{_transport_options}"
400
- ssh_options = _transport_options[:ssh_options]
401
- @host = _transport_options[:host] || false
402
- @username = ssh_options[:user] rescue false
403
- @ssh_options_for_transport = ssh_options_for(ssh_options)
404
-
405
- new_options = options.empty? ? options : symbolize_keys(options)
406
- new_options.merge!({:ssh_pty_enable => true}) unless new_options.has_key?(:ssh_pty_enable)
407
- new_options.merge!({:prefix => 'sudo '}) unless @username == 'root'
408
- @options = new_options
409
- test = Chef::Provisioning::Transport::SSH.new(@host, @username, @ssh_options_for_transport, @options, config)
410
- test.available?
274
+ def ensure_ssh_cluster(action_handler)
275
+ _cluster_path = cluster_path
276
+ Chef::Provisioning.inline_resource(action_handler) do
277
+ ssh_cluster _cluster_path
278
+ end
411
279
  end
412
280
 
413
- def machine_options_for(given_machine_options = false)
414
- if @machine_options_for
415
- log_info "@machine_options_for #{@machine_options_for}"
416
- return @machine_options_for
417
- else
418
- @machine_options_for ||= begin
419
- _given_machine_options = given_machine_options.dup
420
- ret_val = false
421
- ret_val = symbolize_keys(_given_machine_options) if _given_machine_options
422
- ret_val
281
+ def create_ssh_machine(action_handler, machine_spec, machine_options)
282
+ log_info("File is = #{ssh_machine_file(machine_spec)}")
283
+ log_info("current_machine_options = #{machine_options.to_s}")
284
+ machine_options_hash = deep_hashify(machine_options)
285
+ stringy_machine_options = stringify_keys(machine_options_hash)
286
+ file_path = ssh_machine_file(machine_spec)
287
+ options_parsed = ::JSON.parse(stringy_machine_options.to_json)
288
+ json_machine_options = ::JSON.pretty_generate(options_parsed)
289
+ Chef::Provisioning.inline_resource(action_handler) do
290
+ file file_path do
291
+ content json_machine_options
423
292
  end
424
293
  end
294
+ file_path
425
295
  end
426
296
 
427
- def machine_for(machine_spec, machine_options)
428
- if machine_options[:transport_options]['is_windows']
429
- Chef::Provisioning::Machine::WindowsMachine.new(machine_spec, create_winrm_transport(machine_options),
430
- convergence_strategy_for(machine_spec, machine_options))
431
- else
432
- Chef::Provisioning::Machine::UnixMachine.new(machine_spec,
433
- transport_for(machine_options),
434
- convergence_strategy_for(machine_spec, machine_options))
297
+ def delete_ssh_machine(action_handler, machine_spec)
298
+ if ::File.exists?(ssh_machine_file(machine_spec))
299
+ Chef::Provisioning.inline_resource(action_handler) do
300
+ file registry_file do
301
+ action :delete
302
+ end
303
+ end
435
304
  end
436
305
  end
437
306
 
438
- def transport_for(machine_options)
439
- if machine_options[:transport_options]['is_windows']
440
- create_winrm_transport(machine_spec)
307
+ def existing_ssh_machine(machine_spec)
308
+ if ssh_machine_exists?(machine_spec)
309
+ existing_machine_hash = JSON.parse(File.read(ssh_machine_file(machine_spec)))
310
+ symbolize_keys(existing_machine_hash.to_hash)
441
311
  else
442
- Chef::Provisioning::Transport::SSH.new(@target_host, @username, @ssh_options_for_transport, @options, config)
312
+ return false
443
313
  end
444
314
  end
445
315
 
446
- def convergence_strategy_for(machine_spec, machine_options)
447
- if machine_options[:transport_options]['is_windows']
448
- @windows_convergence_strategy ||= begin
449
- Chef::Provisioning::ConvergenceStrategy::InstallMsi.
450
- new(machine_options[:convergence_options], config)
451
- end
316
+ def ssh_machine_exists?(machine_spec)
317
+ if machine_spec.location
318
+ ::File.exists?(ssh_machine_file(machine_spec))
452
319
  else
453
- @unix_convergence_strategy ||= begin
454
- Chef::Provisioning::ConvergenceStrategy::InstallCached.new(machine_options[:convergence_options],
455
- config)
456
- end
320
+ false
457
321
  end
458
322
  end
459
323
 
460
- def create_winrm_transport(machine_options)
461
- # forwarded_ports = machine_options[:transport_options]['forwarded_ports']
462
-
463
- # TODO IPv6 loopback? What do we do for that?
464
- hostname = machine_options[:transport_options]['host'] || '127.0.0.1'
465
- port = machine_options[:transport_options]['port'] || 5985
466
- # port = forwarded_ports[port] if forwarded_ports[port]
467
- endpoint = "http://#{hostname}:#{port}/wsman"
468
- type = :plaintext
469
- options = {
470
- :user => machine_options[:transport_options]['user'] || 'vagrant',
471
- :pass => machine_options[:transport_options]['password'] || 'vagrant',
472
- :disable_sspi => true
473
- }
474
-
475
- Chef::Provisioning::Transport::WinRM.new(endpoint, type, options, config)
476
- end
477
-
478
- # def create_ssh_transport(machine_options)
479
- def ssh_options_for(given_ssh_options)
480
- machine_ssh_options = stringify_keys(given_ssh_options)
481
- # username = (@username || machine_ssh_options['user'] || ENV['METAL_SSH_USER'] || 'root')
482
- log_info("machine_ssh_options: #{machine_ssh_options}")
483
-
484
- ssh_pass = machine_ssh_options['password'] || false
485
- ssh_pass_hash = { 'password' => ssh_pass } if ssh_pass
486
-
487
- ssh_keys = []
488
- if machine_ssh_options['keys']
489
- Array(machine_ssh_options['keys']).each do |key|
490
- ssh_keys << key
491
- end
324
+ def ssh_machine_file(machine_spec)
325
+ if machine_spec.location && machine_spec.location['ssh_machine_file']
326
+ machine_spec.location['ssh_machine_file']
492
327
  else
493
- ssh_keys = false
328
+ ssh_machine_file = ::File.join(@cluster_path, "#{machine_spec.name}.json")
329
+ ssh_machine_file
494
330
  end
495
-
496
- ssh_key_hash = { 'keys' => ssh_keys.flatten.uniq } if ssh_keys
497
-
498
- log_info("create_ssh_transport - ssh_pass: #{ssh_pass}") if ssh_pass
499
- log_info("create_ssh_transport - ssh_keys: #{ssh_keys.inspect}") if ssh_keys
500
- log_info("create_ssh_transport - no ssh_pass or ssh_key given") unless (ssh_keys || ssh_pass)
501
- raise "no ssh_pass or ssh_key given" unless ( ssh_pass || ssh_keys )
502
- machine_ssh_options.merge!(ssh_pass_hash) if ssh_pass_hash
503
- machine_ssh_options.merge!(ssh_key_hash) if ssh_key_hash
504
-
505
- # Validate Ssh Options
506
- use_ssh_options = symbolize_keys(machine_ssh_options)
507
- log_info "use_ssh_options #{use_ssh_options}"
508
- use_ssh_options.each { |k,v| raise "Invalid Shh Option #{k} \n Valid Options are #{valid_ssh_options}" unless valid_ssh_options.include?(k) }
509
-
510
- # Make Sure We Can Connect
511
- log_debug("create_ssh_transport - ssh_options: #{use_ssh_options.inspect}")
512
- begin
513
- ssh = Net::SSH.start(@target_host, @username, use_ssh_options)
514
- ssh.close
515
- log_info("ABLE to Connect to #{@target_host} using #{@username} and #{use_ssh_options.inspect}")
516
- rescue
517
- log_info("UNABLE to Connect to #{@target_host} using #{@username} and #{use_ssh_options.inspect}")
518
- raise "UNABLE to Connect to #{@target_host} using #{@username} and #{use_ssh_options.inspect}"
519
- end
520
-
521
- return use_ssh_options
522
331
  end
523
-
524
332
  end
525
333
  end
526
334
  end
@@ -99,6 +99,22 @@ class Chef
99
99
  end
100
100
  end
101
101
 
102
+ def deep_hashify(machine_options)
103
+ if machine_options.respond_to?(:to_hash)
104
+ hash = machine_options.to_hash
105
+
106
+ hash.inject({}){|result, (key, value)|
107
+ if value.respond_to?(:to_hash)
108
+ new_value = deep_hashify(value)
109
+ else
110
+ new_value = value
111
+ end
112
+ result[key] = new_value
113
+ result
114
+ }
115
+ end
116
+ end
117
+
102
118
  def false_or_value(v)
103
119
  case v
104
120
  when "false"
@@ -188,4 +204,3 @@ class Chef
188
204
  end
189
205
  end
190
206
  end
191
-
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module SshDriver
4
- VERSION = '0.0.6'
4
+ VERSION = '0.0.7'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-provisioning-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zack Zondlo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-25 00:00:00.000000000 Z
11
+ date: 2015-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-provisioning