chef-provisioning-ssh 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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