chef-provisioning-vagrant 0.9.0 → 0.10.0

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/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require 'bundler'
2
- require 'bundler/gem_tasks'
3
-
4
- task :spec do
5
- require File.expand_path('spec/run')
6
- end
1
+ require 'bundler'
2
+ require 'bundler/gem_tasks'
3
+
4
+ task :spec do
5
+ require File.expand_path('spec/run')
6
+ end
@@ -1,58 +1,58 @@
1
- require 'chef/provider/lwrp_base'
2
- require 'chef/mixin/shell_out'
3
-
4
- class Chef::Provider::VagrantBox < Chef::Provider::LWRPBase
5
-
6
- use_inline_resources
7
-
8
- include Chef::Mixin::ShellOut
9
-
10
- def whyrun_supported?
11
- true
12
- end
13
-
14
- action :create do
15
- if !box_exists?(new_resource)
16
- if new_resource.url
17
- converge_by "run 'vagrant box add #{new_resource.name} #{new_resource.url} --provider #{new_resource.vagrant_provider}'" do
18
- shell_out("vagrant box add #{new_resource.name} #{new_resource.url} --provider #{new_resource.vagrant_provider}").error!
19
- end
20
- else
21
- raise "Box #{new_resource.name} does not exist"
22
- end
23
- end
24
- end
25
-
26
- action :delete do
27
- if box_exists?(new_resource.name)
28
- converge_by "run 'vagrant box remove #{new_resource.name} #{list_boxes[new_resource.name]} --provider #{new_resource.vagrant_provider}'" do
29
- shell_out("vagrant box remove #{new_resource.name} #{list_boxes[new_resource.name]} --provider #{new_resource.vagrant_provider}").error!
30
- end
31
- end
32
- end
33
-
34
- # Since all box names must be unique for a particular vagrant provider, this hash now
35
- # keys off the provider name, as opposed to the box name. The version is not currently
36
- # used, but is collected as metadata for future consumption
37
- def list_boxes
38
- @list_boxes ||= shell_out("vagrant box list").stdout.lines.inject({}) do |result, line|
39
- line =~ /^(\S+)\s+\((.+),(.+)\)\s*$/
40
- if result.has_key?($2)
41
- result[$2][$1] = $3
42
- else
43
- result[$2] = { $1 => $3 }
44
- end
45
- result
46
- end
47
- end
48
-
49
- # In some rather strained logic, we hook into the vagrant provider, then
50
- # the box name to make sure we have the correct box already installed.
51
- def box_exists?(new_resource)
52
- boxes = list_boxes
53
- boxes[new_resource.vagrant_provider].has_key?(new_resource.name)
54
- end
55
-
56
- def load_current_resource
57
- end
58
- end
1
+ require 'chef/provider/lwrp_base'
2
+ require 'chef/mixin/shell_out'
3
+
4
+ class Chef::Provider::VagrantBox < Chef::Provider::LWRPBase
5
+
6
+ use_inline_resources
7
+
8
+ include Chef::Mixin::ShellOut
9
+
10
+ def whyrun_supported?
11
+ true
12
+ end
13
+
14
+ action :create do
15
+ if !box_exists?(new_resource)
16
+ if new_resource.url
17
+ converge_by "run 'vagrant box add #{new_resource.name} #{new_resource.url} --provider #{new_resource.vagrant_provider}'" do
18
+ shell_out("vagrant box add #{new_resource.name} #{new_resource.url} --provider #{new_resource.vagrant_provider}").error!
19
+ end
20
+ else
21
+ raise "Box #{new_resource.name} does not exist"
22
+ end
23
+ end
24
+ end
25
+
26
+ action :delete do
27
+ if box_exists?(new_resource.name)
28
+ converge_by "run 'vagrant box remove #{new_resource.name} #{list_boxes[new_resource.name]} --provider #{new_resource.vagrant_provider}'" do
29
+ shell_out("vagrant box remove #{new_resource.name} #{list_boxes[new_resource.name]} --provider #{new_resource.vagrant_provider}").error!
30
+ end
31
+ end
32
+ end
33
+
34
+ # Since all box names must be unique for a particular vagrant provider, this hash now
35
+ # keys off the provider name, as opposed to the box name. The version is not currently
36
+ # used, but is collected as metadata for future consumption
37
+ def list_boxes
38
+ @list_boxes ||= shell_out("vagrant box list").stdout.lines.inject({}) do |result, line|
39
+ line =~ /^(\S+)\s+\((.+),(.+)\)\s*$/
40
+ if result.has_key?($2)
41
+ result[$2][$1] = $3
42
+ else
43
+ result[$2] = { $1 => $3 }
44
+ end
45
+ result
46
+ end
47
+ end
48
+
49
+ # In some rather strained logic, we hook into the vagrant provider, then
50
+ # the box name to make sure we have the correct box already installed.
51
+ def box_exists?(new_resource)
52
+ boxes = list_boxes
53
+ boxes[new_resource.vagrant_provider].has_key?(new_resource.name)
54
+ end
55
+
56
+ def load_current_resource
57
+ end
58
+ end
@@ -1,40 +1,40 @@
1
- require 'chef/provider/lwrp_base'
2
- require 'cheffish'
3
-
4
- class Chef::Provider::VagrantCluster < Chef::Provider::LWRPBase
5
-
6
- use_inline_resources
7
-
8
- def whyrun_supported?
9
- true
10
- end
11
-
12
- action :create do
13
- the_base_path = new_resource.path
14
- Cheffish.inline_resource(self, :create) do
15
- directory the_base_path
16
- file ::File.join(the_base_path, 'Vagrantfile') do
17
- content <<EOM
18
- Dir.glob('#{::File.join(the_base_path, '*.vm')}') do |vm_file|
19
- eval(IO.read(vm_file), nil, vm_file)
20
- end
21
- EOM
22
- end
23
- end
24
- end
25
-
26
- action :delete do
27
- the_base_path = new_resource.path
28
- Cheffish.inline_resource(self, :delete) do
29
- file ::File.join(the_base_path, 'Vagrantfile') do
30
- action :delete
31
- end
32
- directory the_base_path do
33
- action :delete
34
- end
35
- end
36
- end
37
-
38
- def load_current_resource
39
- end
40
- end
1
+ require 'chef/provider/lwrp_base'
2
+ require 'cheffish'
3
+
4
+ class Chef::Provider::VagrantCluster < Chef::Provider::LWRPBase
5
+
6
+ use_inline_resources
7
+
8
+ def whyrun_supported?
9
+ true
10
+ end
11
+
12
+ action :create do
13
+ the_base_path = new_resource.path
14
+ Cheffish.inline_resource(self, :create) do
15
+ directory the_base_path
16
+ file ::File.join(the_base_path, 'Vagrantfile') do
17
+ content <<EOM
18
+ Dir.glob('#{::File.join(the_base_path, '*.vm')}') do |vm_file|
19
+ eval(IO.read(vm_file), nil, vm_file)
20
+ end
21
+ EOM
22
+ end
23
+ end
24
+ end
25
+
26
+ action :delete do
27
+ the_base_path = new_resource.path
28
+ Cheffish.inline_resource(self, :delete) do
29
+ file ::File.join(the_base_path, 'Vagrantfile') do
30
+ action :delete
31
+ end
32
+ directory the_base_path do
33
+ action :delete
34
+ end
35
+ end
36
+ end
37
+
38
+ def load_current_resource
39
+ end
40
+ end
@@ -1,3 +1,3 @@
1
- require 'chef/provisioning/vagrant_driver/driver'
2
-
3
- Chef::Provisioning.register_driver_class("vagrant", Chef::Provisioning::VagrantDriver::Driver)
1
+ require 'chef/provisioning/vagrant_driver/driver'
2
+
3
+ Chef::Provisioning.register_driver_class("vagrant", Chef::Provisioning::VagrantDriver::Driver)
@@ -1,36 +1,36 @@
1
- require 'chef/provisioning'
2
- require 'chef/resource/vagrant_cluster'
3
- require 'chef/provider/vagrant_cluster'
4
- require 'chef/resource/vagrant_box'
5
- require 'chef/provider/vagrant_box'
6
- require 'chef/provisioning/vagrant_driver/driver'
7
-
8
- class Chef
9
- module Provisioning
10
- module VagrantDriver
11
- def self.with_vagrant_box(run_context, box_name, vagrant_options = {}, &block)
12
- if box_name.is_a?(Chef::Resource::VagrantBox)
13
- new_options = { :vagrant_options => { 'vm.box' => box_name.name } }
14
- new_options[:vagrant_options]['vm.box_url'] = box_name.url if box_name.url
15
- new_options[:vagrant_provider] = box_name.vagrant_provider
16
- else
17
- new_options = { :vagrant_options => { 'vm.box' => box_name } }
18
- end
19
-
20
- run_context.chef_provisioning.add_machine_options(new_options, &block)
21
- end
22
- end
23
- end
24
-
25
- module DSL
26
- module Recipe
27
- def with_vagrant_cluster(cluster_path, &block)
28
- with_driver("vagrant:#{cluster_path}", &block)
29
- end
30
-
31
- def with_vagrant_box(box_name, vagrant_options = {}, &block)
32
- Chef::Provisioning::VagrantDriver.with_vagrant_box(run_context, box_name, vagrant_options, &block)
33
- end
34
- end
35
- end
36
- end
1
+ require 'chef/provisioning'
2
+ require 'chef/resource/vagrant_cluster'
3
+ require 'chef/provider/vagrant_cluster'
4
+ require 'chef/resource/vagrant_box'
5
+ require 'chef/provider/vagrant_box'
6
+ require 'chef/provisioning/vagrant_driver/driver'
7
+
8
+ class Chef
9
+ module Provisioning
10
+ module VagrantDriver
11
+ def self.with_vagrant_box(run_context, box_name, vagrant_options = {}, &block)
12
+ if box_name.is_a?(Chef::Resource::VagrantBox)
13
+ new_options = { :vagrant_options => { 'vm.box' => box_name.name } }
14
+ new_options[:vagrant_options]['vm.box_url'] = box_name.url if box_name.url
15
+ new_options[:vagrant_provider] = box_name.vagrant_provider
16
+ else
17
+ new_options = { :vagrant_options => { 'vm.box' => box_name } }
18
+ end
19
+
20
+ run_context.chef_provisioning.add_machine_options(new_options, &block)
21
+ end
22
+ end
23
+ end
24
+
25
+ module DSL
26
+ module Recipe
27
+ def with_vagrant_cluster(cluster_path, &block)
28
+ with_driver("vagrant:#{cluster_path}", &block)
29
+ end
30
+
31
+ def with_vagrant_box(box_name, vagrant_options = {}, &block)
32
+ Chef::Provisioning::VagrantDriver.with_vagrant_box(run_context, box_name, vagrant_options, &block)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,470 +1,470 @@
1
- require 'chef/mixin/shell_out'
2
- require 'chef/provisioning/driver'
3
- require 'chef/provisioning/machine/windows_machine'
4
- require 'chef/provisioning/machine/unix_machine'
5
- require 'chef/provisioning/convergence_strategy/install_msi'
6
- require 'chef/provisioning/convergence_strategy/install_cached'
7
- require 'chef/provisioning/transport/winrm'
8
- require 'chef/provisioning/transport/ssh'
9
- require 'chef/provisioning/vagrant_driver/version'
10
- require 'chef/resource/vagrant_cluster'
11
- require 'chef/provider/vagrant_cluster'
12
-
13
- class Chef
14
- module Provisioning
15
- module VagrantDriver
16
- # Provisions machines in vagrant.
17
- class Driver < Chef::Provisioning::Driver
18
-
19
- include Chef::Mixin::ShellOut
20
-
21
- # Create a new vagrant driver.
22
- #
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
- def initialize(driver_url, config)
27
- super
28
- scheme, cluster_path = driver_url.split(':', 2)
29
- @cluster_path = cluster_path
30
- end
31
-
32
- attr_reader :cluster_path
33
-
34
- def self.from_url(driver_url, config)
35
- Driver.new(driver_url, config)
36
- end
37
-
38
- def self.canonicalize_url(driver_url, config)
39
- scheme, cluster_path = driver_url.split(':', 2)
40
- cluster_path = File.expand_path(cluster_path || File.join(Chef::Config.config_dir, 'vms'))
41
- "vagrant:#{cluster_path}"
42
- end
43
-
44
- # Acquire a machine, generally by provisioning it. Returns a Machine
45
- # object pointing at the machine, allowing useful actions like setup,
46
- # converge, execute, file and directory.
47
- def allocate_machine(action_handler, machine_spec, machine_options)
48
- ensure_vagrant_cluster(action_handler)
49
- vm_name = machine_spec.name
50
- vm_file_path = File.join(cluster_path, "#{machine_spec.name}.vm")
51
- vm_file_updated = create_vm_file(action_handler, vm_name, vm_file_path, machine_options)
52
- if vm_file_updated || !machine_spec.location
53
- old_location = machine_spec.location
54
- machine_spec.location = {
55
- 'driver_url' => driver_url,
56
- 'driver_version' => Chef::Provisioning::VagrantDriver::VERSION,
57
- 'vm_name' => vm_name,
58
- 'vm_file_path' => vm_file_path,
59
- 'allocated_at' => Time.now.utc.to_s,
60
- 'host_node' => action_handler.host_node
61
- }
62
- machine_spec.location['needs_reload'] = true if vm_file_updated
63
- if machine_options[:vagrant_options]
64
- %w(vm.guest winrm.host winrm.port winrm.username winrm.password).each do |key|
65
- machine_spec.location[key] = machine_options[:vagrant_options][key] if machine_options[:vagrant_options][key]
66
- end
67
- end
68
- machine_spec.location['chef_client_timeout'] = machine_options[:chef_client_timeout] if machine_options[:chef_client_timeout]
69
- end
70
- end
71
-
72
- def ready_machine(action_handler, machine_spec, machine_options)
73
- start_machine(action_handler, machine_spec, machine_options)
74
- machine_for(machine_spec, machine_options)
75
- end
76
-
77
- # Connect to machine without acquiring it
78
- def connect_to_machine(machine_spec, machine_options)
79
- machine_for(machine_spec, machine_options)
80
- end
81
-
82
- def destroy_machine(action_handler, machine_spec, machine_options)
83
- if machine_spec.location
84
- vm_name = machine_spec.location['vm_name']
85
- current_status = vagrant_status(vm_name)
86
- if current_status != 'not created'
87
- action_handler.perform_action "run vagrant destroy -f #{vm_name} (status was '#{current_status}')" do
88
- result = shell_out("vagrant destroy -f #{vm_name}", :cwd => cluster_path)
89
- if result.exitstatus != 0
90
- raise "vagrant destroy failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
91
- end
92
- end
93
- end
94
-
95
- convergence_strategy_for(machine_spec, machine_options).
96
- cleanup_convergence(action_handler, machine_spec)
97
-
98
- vm_file_path = machine_spec.location['vm_file_path']
99
- Chef::Provisioning.inline_resource(action_handler) do
100
- file vm_file_path do
101
- action :delete
102
- end
103
- end
104
- end
105
- end
106
-
107
- def stop_machine(action_handler, machine_spec, machine_options)
108
- if machine_spec.location
109
- vm_name = machine_spec.location['vm_name']
110
- current_status = vagrant_status(vm_name)
111
- if current_status == 'running'
112
- action_handler.perform_action "run vagrant halt #{vm_name} (status was '#{current_status}')" do
113
- result = shell_out("vagrant halt #{vm_name}", :cwd => cluster_path)
114
- if result.exitstatus != 0
115
- raise "vagrant halt failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
116
- end
117
- end
118
- end
119
- end
120
- end
121
-
122
- def ready_machines(action_handler, specs_and_options, parallelizer)
123
- start_machines(action_handler, specs_and_options)
124
- machines = []
125
- specs_and_options.each_pair do |spec, options|
126
- machine = machine_for(spec, options)
127
- machines << machine
128
- yield machine if block_given?
129
- end
130
- machines
131
- end
132
-
133
- def destroy_machines(action_handler, specs_and_options, parallelizer)
134
- all_names = []
135
- all_status = []
136
- all_outputs = {}
137
- specs_and_options.each_key do |spec|
138
- if spec.location
139
- vm_name = spec.location['vm_name']
140
- current_status = vagrant_status(vm_name)
141
- if current_status != 'not created'
142
- all_names.push(vm_name)
143
- all_status.push(current_status)
144
- end
145
- end
146
- end
147
- if all_names.length > 0
148
- names = all_names.join(" ")
149
- statuses = all_status.join(", ")
150
- action_handler.perform_action "run vagrant destroy -f #{names} (status was '#{statuses}')" do
151
- result = shell_out("vagrant destroy -f #{names}", :cwd => cluster_path)
152
- if result.exitstatus != 0
153
- raise "vagrant destroy failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
154
- end
155
- end
156
- end
157
- specs_and_options.each_pair do |spec, options|
158
- convergence_strategy_for(spec, options).cleanup_convergence(action_handler, spec)
159
-
160
- vm_file_path = spec.location['vm_file_path']
161
- Chef::Provisioning.inline_resource(action_handler) do
162
- file vm_file_path do
163
- action :delete
164
- end
165
- end
166
- yield spec if block_given?
167
- end
168
- end
169
-
170
- def stop_machines(action_handler, specs_and_options, parallelizer)
171
- all_names = []
172
- specs_and_options.each_key do |spec|
173
- if spec.location
174
- vm_name = spec.location['vm_name']
175
- current_status = vagrant_status(vm_name)
176
- if current_status == 'running'
177
- all_names.push(vm_name)
178
- end
179
- end
180
- end
181
- if all_names.length > 0
182
- names = all_names.join(" ")
183
- action_handler.perform_action "run vagrant halt #{names} (status was 'running')" do
184
- result = shell_out("vagrant halt #{names}", :cwd => cluster_path)
185
- if result.exitstatus != 0
186
- raise "vagrant halt failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
187
- end
188
- end
189
- end
190
- end
191
-
192
- # Used by vagrant_cluster and machine to get the string used to configure vagrant
193
- def self.vagrant_config_string(vagrant_config, variable, line_prefix)
194
- hostname = name.gsub(/[^A-Za-z0-9\-]/, '-')
195
- result = ''
196
- vagrant_config.each_pair do |key, value|
197
- result += "#{line_prefix}#{variable}.#{key} = #{value.inspect}\n"
198
- end
199
- result
200
- end
201
-
202
- def driver_url
203
- "vagrant:#{cluster_path}"
204
- end
205
-
206
- protected
207
-
208
- def ensure_vagrant_cluster(action_handler)
209
- _cluster_path = cluster_path
210
- Chef::Provisioning.inline_resource(action_handler) do
211
- vagrant_cluster _cluster_path
212
- end
213
- end
214
-
215
- def create_vm_file(action_handler, vm_name, vm_file_path, machine_options)
216
- # Determine contents of vm file
217
- vm_file_content = "Vagrant.configure('2') do |outer_config|\n"
218
- vm_file_content << " outer_config.vm.define #{vm_name.inspect} do |config|\n"
219
- merged_vagrant_options = { 'vm.hostname' => vm_name }
220
- if machine_options[:vagrant_options]
221
- merged_vagrant_options = Cheffish::MergedConfig.new(machine_options[:vagrant_options], merged_vagrant_options)
222
- end
223
- merged_vagrant_options.each_pair do |key, value|
224
- if key == 'vm.network'
225
- vm_file_content << " config.#{key}(#{value})\n"
226
- else
227
- vm_file_content << " config.#{key} = #{value.inspect}\n"
228
- end
229
- end
230
- vm_file_content << machine_options[:vagrant_config] if machine_options[:vagrant_config]
231
- vm_file_content << " end\nend\n"
232
-
233
- # Set up vagrant file
234
- Chef::Provisioning.inline_resource(action_handler) do
235
- file vm_file_path do
236
- content vm_file_content
237
- action :create
238
- end
239
- end
240
- end
241
-
242
- def start_machine(action_handler, machine_spec, machine_options)
243
- vm_name = machine_spec.location['vm_name']
244
- vm_provider = machine_options.has_key?(:vagrant_provider) ? machine_options[:vagrant_provider] : 'virtualbox'
245
- up_timeout = machine_options[:up_timeout] || 10*60
246
- current_status = vagrant_status(vm_name)
247
- vm_file_updated = machine_spec.location['needs_reload']
248
- machine_spec.location['needs_reload'] = false
249
- if current_status != 'running'
250
- # Run vagrant up if vm is not running
251
- action_handler.perform_action "run vagrant up #{vm_name} --provider #{vm_provider} (status was '#{current_status}')" do
252
- result = shell_out("vagrant up #{vm_name} --provider #{vm_provider}", :cwd => cluster_path,
253
- :timeout => up_timeout)
254
- if result.exitstatus != 0
255
- raise "vagrant up #{vm_name} --provider #{vm_provider} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
256
- end
257
- parse_vagrant_up(result.stdout, machine_spec)
258
- end
259
- elsif vm_file_updated
260
- # Run vagrant reload if vm is running and vm file changed
261
- action_handler.perform_action "run vagrant reload #{vm_name}" do
262
- result = shell_out("vagrant reload #{vm_name}", :cwd => cluster_path,
263
- :timeout => up_timeout)
264
- if result.exitstatus != 0
265
- raise "vagrant reload #{vm_name} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
266
- end
267
- parse_vagrant_up(result.stdout, machine_spec)
268
- end
269
- end
270
- end
271
-
272
- def start_machines(action_handler, specs_and_options)
273
- up_names = []
274
- up_status = []
275
- up_specs = {}
276
- update_names = []
277
- update_specs = {}
278
- timeouts = []
279
- specs_and_options.each_pair do |spec, options|
280
- vm_name = spec.location['vm_name']
281
-
282
- vm_file_updated = spec.location['needs_reload']
283
- spec.location['needs_reload'] = false
284
-
285
- current_status = vagrant_status(vm_name)
286
- if current_status != 'running'
287
- up_names.push(vm_name)
288
- up_status.push(current_status)
289
- up_specs[vm_name] = spec
290
- elsif vm_file_updated
291
- update_names.push(vm_name)
292
- update_specs[vm_name] = spec
293
- end
294
- timeouts.push(options[:up_timeout])
295
- end
296
- # Use the highest timeout, if any exist
297
- up_timeout = timeouts.compact.max
298
- up_timeout ||= 10*60
299
- if up_names.length > 0
300
- # Run vagrant up if vm is not running
301
- names = up_names.join(" ")
302
- statuses = up_status.join(", ")
303
- action_handler.perform_action "run vagrant up --parallel #{names} (status was '#{statuses}')" do
304
- result = shell_out("vagrant up --parallel #{names}", :cwd => cluster_path,
305
- :timeout => up_timeout)
306
- if result.exitstatus != 0
307
- raise "vagrant up #{names} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
308
- end
309
- parse_multi_vagrant_up(result.stdout, up_specs)
310
- end
311
- end
312
- if update_names.length > 0
313
- names = update_names.join(" ")
314
- # Run vagrant reload if vm is running and vm file changed
315
- action_handler.perform_action "run vagrant reload #{names}" do
316
- result = shell_out("vagrant reload #{names}", :cwd => cluster_path,
317
- :timeout => up_timeout)
318
- if result.exitstatus != 0
319
- raise "vagrant reload #{names} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
320
- end
321
- parse_multi_vagrant_up(result.stdout, update_specs)
322
- end
323
- end
324
- end
325
-
326
- def parse_vagrant_up(output, machine_spec)
327
- # Grab forwarded port info
328
- machine_spec.location['forwarded_ports'] = {}
329
- in_forwarding_ports = false
330
- output.lines.each do |line|
331
- if in_forwarding_ports
332
- if line =~ /-- (\d+) => (\d+)/
333
- machine_spec.location['forwarded_ports'][$1] = $2
334
- else
335
- in_forwarding_ports = false
336
- end
337
- elsif line =~ /Forwarding ports...$/
338
- in_forwarding_ports = true
339
- end
340
- end
341
- end
342
-
343
- def parse_multi_vagrant_up(output, all_machine_specs)
344
- # Grab forwarded port info
345
- in_forwarding_ports = {}
346
- all_machine_specs.each_pair do |key, spec|
347
- spec.location['forwarded_ports'] = {}
348
- in_forwarding_ports[key] = false
349
- end
350
- output.lines.each do |line|
351
- /^\[(.*?)\]/.match(line)
352
- node_name = $1
353
- if in_forwarding_ports[node_name]
354
- if line =~ /-- (\d+) => (\d+)/
355
- spec = all_machine_specs[node_name]
356
- spec.location['forwarded_ports'][$1] = $2
357
- else
358
- in_forwarding_ports[node_name] = false
359
- end
360
- elsif line =~ /Forwarding ports...$/
361
- in_forwarding_ports[node_name] = true
362
- end
363
- end
364
- end
365
-
366
- def machine_for(machine_spec, machine_options)
367
- if machine_spec.location['vm.guest'].to_s == 'windows'
368
- Chef::Provisioning::Machine::WindowsMachine.new(machine_spec, transport_for(machine_spec),
369
- convergence_strategy_for(machine_spec, machine_options))
370
- else
371
- Chef::Provisioning::Machine::UnixMachine.new(machine_spec, transport_for(machine_spec),
372
- convergence_strategy_for(machine_spec, machine_options))
373
- end
374
- end
375
-
376
- def convergence_strategy_for(machine_spec, machine_options)
377
- if machine_spec.location['vm.guest'].to_s == 'windows'
378
- Chef::Provisioning::ConvergenceStrategy::InstallMsi.
379
- new(machine_options[:convergence_options], config)
380
- else
381
- Chef::Provisioning::ConvergenceStrategy::InstallCached.
382
- new(machine_options[:convergence_options], config)
383
- end
384
- end
385
-
386
- def transport_for(machine_spec)
387
- if machine_spec.location['vm.guest'].to_s == 'windows'
388
- create_winrm_transport(machine_spec)
389
- else
390
- create_ssh_transport(machine_spec)
391
- end
392
- end
393
-
394
- def vagrant_status(name)
395
- status_output = shell_out("vagrant status #{name}", :cwd => cluster_path).stdout
396
- if status_output =~ /^#{name}\s+(.+)\s+\((.+)\)/
397
- $1
398
- else
399
- 'not created'
400
- end
401
- end
402
-
403
- def create_winrm_transport(machine_spec)
404
- forwarded_ports = machine_spec.location['forwarded_ports']
405
-
406
- # TODO IPv6 loopback? What do we do for that?
407
- hostname = machine_spec.location['winrm.host'] || '127.0.0.1'
408
- port = machine_spec.location['winrm.port'] || 5985
409
- port = forwarded_ports[port] if forwarded_ports[port]
410
- endpoint = "http://#{hostname}:#{port}/wsman"
411
- type = :plaintext
412
- options = {
413
- :user => machine_spec.location['winrm.username'] || 'vagrant',
414
- :pass => machine_spec.location['winrm.password'] || 'vagrant',
415
- :disable_sspi => true
416
- }
417
-
418
- Chef::Provisioning::Transport::WinRM.new(endpoint, type, options)
419
- end
420
-
421
- def create_ssh_transport(machine_spec)
422
- vagrant_ssh_config = vagrant_ssh_config_for(machine_spec)
423
- hostname = vagrant_ssh_config['HostName']
424
- username = vagrant_ssh_config['User']
425
- ssh_options = {
426
- :port => vagrant_ssh_config['Port'],
427
- :auth_methods => ['publickey'],
428
- :user_known_hosts_file => vagrant_ssh_config['UserKnownHostsFile'],
429
- :paranoid => yes_or_no(vagrant_ssh_config['StrictHostKeyChecking']),
430
- :keys => [ strip_quotes(vagrant_ssh_config['IdentityFile']) ],
431
- :keys_only => yes_or_no(vagrant_ssh_config['IdentitiesOnly'])
432
- }
433
- ssh_options[:auth_methods] = %w(password) if yes_or_no(vagrant_ssh_config['PasswordAuthentication'])
434
- options = {
435
- :prefix => 'sudo '
436
- }
437
- Chef::Provisioning::Transport::SSH.new(hostname, username, ssh_options, options, config)
438
- end
439
-
440
- def vagrant_ssh_config_for(machine_spec)
441
- vagrant_ssh_config = {}
442
- result = shell_out("vagrant ssh-config #{machine_spec.location['vm_name']}",
443
- :cwd => cluster_path)
444
- result.stdout.lines.inject({}) do |result, line|
445
- line =~ /^\s*(\S+)\s+(.+?)(\r\n|\r|\n|\z)/
446
- vagrant_ssh_config[$1] = $2
447
- end
448
- vagrant_ssh_config
449
- end
450
-
451
- def yes_or_no(str)
452
- case str
453
- when 'yes'
454
- true
455
- else
456
- false
457
- end
458
- end
459
-
460
- def strip_quotes(str)
461
- if str[0] == '"' && str[-1] == '"' && str.size >= 2
462
- str[1..-2]
463
- else
464
- str
465
- end
466
- end
467
- end
468
- end
469
- end
470
- end
1
+ require 'chef/mixin/shell_out'
2
+ require 'chef/provisioning/driver'
3
+ require 'chef/provisioning/machine/windows_machine'
4
+ require 'chef/provisioning/machine/unix_machine'
5
+ require 'chef/provisioning/convergence_strategy/install_msi'
6
+ require 'chef/provisioning/convergence_strategy/install_cached'
7
+ require 'chef/provisioning/transport/winrm'
8
+ require 'chef/provisioning/transport/ssh'
9
+ require 'chef/provisioning/vagrant_driver/version'
10
+ require 'chef/resource/vagrant_cluster'
11
+ require 'chef/provider/vagrant_cluster'
12
+
13
+ class Chef
14
+ module Provisioning
15
+ module VagrantDriver
16
+ # Provisions machines in vagrant.
17
+ class Driver < Chef::Provisioning::Driver
18
+
19
+ include Chef::Mixin::ShellOut
20
+
21
+ # Create a new vagrant driver.
22
+ #
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
+ def initialize(driver_url, config)
27
+ super
28
+ scheme, cluster_path = driver_url.split(':', 2)
29
+ @cluster_path = cluster_path
30
+ end
31
+
32
+ attr_reader :cluster_path
33
+
34
+ def self.from_url(driver_url, config)
35
+ Driver.new(driver_url, config)
36
+ end
37
+
38
+ def self.canonicalize_url(driver_url, config)
39
+ scheme, cluster_path = driver_url.split(':', 2)
40
+ cluster_path = File.expand_path(cluster_path || File.join(Chef::Config.config_dir, 'vms'))
41
+ "vagrant:#{cluster_path}"
42
+ end
43
+
44
+ # Acquire a machine, generally by provisioning it. Returns a Machine
45
+ # object pointing at the machine, allowing useful actions like setup,
46
+ # converge, execute, file and directory.
47
+ def allocate_machine(action_handler, machine_spec, machine_options)
48
+ ensure_vagrant_cluster(action_handler)
49
+ vm_name = machine_spec.name
50
+ vm_file_path = File.join(cluster_path, "#{machine_spec.name}.vm")
51
+ vm_file_updated = create_vm_file(action_handler, vm_name, vm_file_path, machine_options)
52
+ if vm_file_updated || !machine_spec.location
53
+ old_location = machine_spec.location
54
+ machine_spec.location = {
55
+ 'driver_url' => driver_url,
56
+ 'driver_version' => Chef::Provisioning::VagrantDriver::VERSION,
57
+ 'vm_name' => vm_name,
58
+ 'vm_file_path' => vm_file_path,
59
+ 'allocated_at' => Time.now.utc.to_s,
60
+ 'host_node' => action_handler.host_node
61
+ }
62
+ machine_spec.location['needs_reload'] = true if vm_file_updated
63
+ if machine_options[:vagrant_options]
64
+ %w(vm.guest winrm.host winrm.port winrm.username winrm.password).each do |key|
65
+ machine_spec.location[key] = machine_options[:vagrant_options][key] if machine_options[:vagrant_options][key]
66
+ end
67
+ end
68
+ machine_spec.location['chef_client_timeout'] = machine_options[:chef_client_timeout] if machine_options[:chef_client_timeout]
69
+ end
70
+ end
71
+
72
+ def ready_machine(action_handler, machine_spec, machine_options)
73
+ start_machine(action_handler, machine_spec, machine_options)
74
+ machine_for(machine_spec, machine_options)
75
+ end
76
+
77
+ # Connect to machine without acquiring it
78
+ def connect_to_machine(machine_spec, machine_options)
79
+ machine_for(machine_spec, machine_options)
80
+ end
81
+
82
+ def destroy_machine(action_handler, machine_spec, machine_options)
83
+ if machine_spec.location
84
+ vm_name = machine_spec.location['vm_name']
85
+ current_status = vagrant_status(vm_name)
86
+ if current_status != 'not created'
87
+ action_handler.perform_action "run vagrant destroy -f #{vm_name} (status was '#{current_status}')" do
88
+ result = shell_out("vagrant destroy -f #{vm_name}", :cwd => cluster_path)
89
+ if result.exitstatus != 0
90
+ raise "vagrant destroy failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
91
+ end
92
+ end
93
+ end
94
+
95
+ convergence_strategy_for(machine_spec, machine_options).
96
+ cleanup_convergence(action_handler, machine_spec)
97
+
98
+ vm_file_path = machine_spec.location['vm_file_path']
99
+ Chef::Provisioning.inline_resource(action_handler) do
100
+ file vm_file_path do
101
+ action :delete
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def stop_machine(action_handler, machine_spec, machine_options)
108
+ if machine_spec.location
109
+ vm_name = machine_spec.location['vm_name']
110
+ current_status = vagrant_status(vm_name)
111
+ if current_status == 'running'
112
+ action_handler.perform_action "run vagrant halt #{vm_name} (status was '#{current_status}')" do
113
+ result = shell_out("vagrant halt #{vm_name}", :cwd => cluster_path)
114
+ if result.exitstatus != 0
115
+ raise "vagrant halt failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ def ready_machines(action_handler, specs_and_options, parallelizer)
123
+ start_machines(action_handler, specs_and_options)
124
+ machines = []
125
+ specs_and_options.each_pair do |spec, options|
126
+ machine = machine_for(spec, options)
127
+ machines << machine
128
+ yield machine if block_given?
129
+ end
130
+ machines
131
+ end
132
+
133
+ def destroy_machines(action_handler, specs_and_options, parallelizer)
134
+ all_names = []
135
+ all_status = []
136
+ all_outputs = {}
137
+ specs_and_options.each_key do |spec|
138
+ if spec.location
139
+ vm_name = spec.location['vm_name']
140
+ current_status = vagrant_status(vm_name)
141
+ if current_status != 'not created'
142
+ all_names.push(vm_name)
143
+ all_status.push(current_status)
144
+ end
145
+ end
146
+ end
147
+ if all_names.length > 0
148
+ names = all_names.join(" ")
149
+ statuses = all_status.join(", ")
150
+ action_handler.perform_action "run vagrant destroy -f #{names} (status was '#{statuses}')" do
151
+ result = shell_out("vagrant destroy -f #{names}", :cwd => cluster_path)
152
+ if result.exitstatus != 0
153
+ raise "vagrant destroy failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
154
+ end
155
+ end
156
+ end
157
+ specs_and_options.each_pair do |spec, options|
158
+ convergence_strategy_for(spec, options).cleanup_convergence(action_handler, spec)
159
+
160
+ vm_file_path = spec.location['vm_file_path']
161
+ Chef::Provisioning.inline_resource(action_handler) do
162
+ file vm_file_path do
163
+ action :delete
164
+ end
165
+ end
166
+ yield spec if block_given?
167
+ end
168
+ end
169
+
170
+ def stop_machines(action_handler, specs_and_options, parallelizer)
171
+ all_names = []
172
+ specs_and_options.each_key do |spec|
173
+ if spec.location
174
+ vm_name = spec.location['vm_name']
175
+ current_status = vagrant_status(vm_name)
176
+ if current_status == 'running'
177
+ all_names.push(vm_name)
178
+ end
179
+ end
180
+ end
181
+ if all_names.length > 0
182
+ names = all_names.join(" ")
183
+ action_handler.perform_action "run vagrant halt #{names} (status was 'running')" do
184
+ result = shell_out("vagrant halt #{names}", :cwd => cluster_path)
185
+ if result.exitstatus != 0
186
+ raise "vagrant halt failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ # Used by vagrant_cluster and machine to get the string used to configure vagrant
193
+ def self.vagrant_config_string(vagrant_config, variable, line_prefix)
194
+ hostname = name.gsub(/[^A-Za-z0-9\-]/, '-')
195
+ result = ''
196
+ vagrant_config.each_pair do |key, value|
197
+ result += "#{line_prefix}#{variable}.#{key} = #{value.inspect}\n"
198
+ end
199
+ result
200
+ end
201
+
202
+ def driver_url
203
+ "vagrant:#{cluster_path}"
204
+ end
205
+
206
+ protected
207
+
208
+ def ensure_vagrant_cluster(action_handler)
209
+ _cluster_path = cluster_path
210
+ Chef::Provisioning.inline_resource(action_handler) do
211
+ vagrant_cluster _cluster_path
212
+ end
213
+ end
214
+
215
+ def create_vm_file(action_handler, vm_name, vm_file_path, machine_options)
216
+ # Determine contents of vm file
217
+ vm_file_content = "Vagrant.configure('2') do |outer_config|\n"
218
+ vm_file_content << " outer_config.vm.define #{vm_name.inspect} do |config|\n"
219
+ merged_vagrant_options = { 'vm.hostname' => vm_name }
220
+ if machine_options[:vagrant_options]
221
+ merged_vagrant_options = Cheffish::MergedConfig.new(machine_options[:vagrant_options], merged_vagrant_options)
222
+ end
223
+ merged_vagrant_options.each_pair do |key, value|
224
+ if key == 'vm.network'
225
+ vm_file_content << " config.#{key}(#{value})\n"
226
+ else
227
+ vm_file_content << " config.#{key} = #{value.inspect}\n"
228
+ end
229
+ end
230
+ vm_file_content << machine_options[:vagrant_config] if machine_options[:vagrant_config]
231
+ vm_file_content << " end\nend\n"
232
+
233
+ # Set up vagrant file
234
+ Chef::Provisioning.inline_resource(action_handler) do
235
+ file vm_file_path do
236
+ content vm_file_content
237
+ action :create
238
+ end
239
+ end
240
+ end
241
+
242
+ def start_machine(action_handler, machine_spec, machine_options)
243
+ vm_name = machine_spec.location['vm_name']
244
+ vm_provider = machine_options.has_key?(:vagrant_provider) ? machine_options[:vagrant_provider] : 'virtualbox'
245
+ up_timeout = machine_options[:up_timeout] || 10*60
246
+ current_status = vagrant_status(vm_name)
247
+ vm_file_updated = machine_spec.location['needs_reload']
248
+ machine_spec.location['needs_reload'] = false
249
+ if current_status != 'running'
250
+ # Run vagrant up if vm is not running
251
+ action_handler.perform_action "run vagrant up #{vm_name} --provider #{vm_provider} (status was '#{current_status}')" do
252
+ result = shell_out("vagrant up #{vm_name} --provider #{vm_provider}", :cwd => cluster_path,
253
+ :timeout => up_timeout)
254
+ if result.exitstatus != 0
255
+ raise "vagrant up #{vm_name} --provider #{vm_provider} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
256
+ end
257
+ parse_vagrant_up(result.stdout, machine_spec)
258
+ end
259
+ elsif vm_file_updated
260
+ # Run vagrant reload if vm is running and vm file changed
261
+ action_handler.perform_action "run vagrant reload #{vm_name}" do
262
+ result = shell_out("vagrant reload #{vm_name}", :cwd => cluster_path,
263
+ :timeout => up_timeout)
264
+ if result.exitstatus != 0
265
+ raise "vagrant reload #{vm_name} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
266
+ end
267
+ parse_vagrant_up(result.stdout, machine_spec)
268
+ end
269
+ end
270
+ end
271
+
272
+ def start_machines(action_handler, specs_and_options)
273
+ up_names = []
274
+ up_status = []
275
+ up_specs = {}
276
+ update_names = []
277
+ update_specs = {}
278
+ timeouts = []
279
+ specs_and_options.each_pair do |spec, options|
280
+ vm_name = spec.location['vm_name']
281
+
282
+ vm_file_updated = spec.location['needs_reload']
283
+ spec.location['needs_reload'] = false
284
+
285
+ current_status = vagrant_status(vm_name)
286
+ if current_status != 'running'
287
+ up_names.push(vm_name)
288
+ up_status.push(current_status)
289
+ up_specs[vm_name] = spec
290
+ elsif vm_file_updated
291
+ update_names.push(vm_name)
292
+ update_specs[vm_name] = spec
293
+ end
294
+ timeouts.push(options[:up_timeout])
295
+ end
296
+ # Use the highest timeout, if any exist
297
+ up_timeout = timeouts.compact.max
298
+ up_timeout ||= 10*60
299
+ if up_names.length > 0
300
+ # Run vagrant up if vm is not running
301
+ names = up_names.join(" ")
302
+ statuses = up_status.join(", ")
303
+ action_handler.perform_action "run vagrant up --parallel #{names} (status was '#{statuses}')" do
304
+ result = shell_out("vagrant up --parallel #{names}", :cwd => cluster_path,
305
+ :timeout => up_timeout)
306
+ if result.exitstatus != 0
307
+ raise "vagrant up #{names} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
308
+ end
309
+ parse_multi_vagrant_up(result.stdout, up_specs)
310
+ end
311
+ end
312
+ if update_names.length > 0
313
+ names = update_names.join(" ")
314
+ # Run vagrant reload if vm is running and vm file changed
315
+ action_handler.perform_action "run vagrant reload #{names}" do
316
+ result = shell_out("vagrant reload #{names}", :cwd => cluster_path,
317
+ :timeout => up_timeout)
318
+ if result.exitstatus != 0
319
+ raise "vagrant reload #{names} failed!\nSTDOUT:#{result.stdout}\nSTDERR:#{result.stderr}"
320
+ end
321
+ parse_multi_vagrant_up(result.stdout, update_specs)
322
+ end
323
+ end
324
+ end
325
+
326
+ def parse_vagrant_up(output, machine_spec)
327
+ # Grab forwarded port info
328
+ machine_spec.location['forwarded_ports'] = {}
329
+ in_forwarding_ports = false
330
+ output.lines.each do |line|
331
+ if in_forwarding_ports
332
+ if line =~ /-- (\d+) => (\d+)/
333
+ machine_spec.location['forwarded_ports'][$1] = $2
334
+ else
335
+ in_forwarding_ports = false
336
+ end
337
+ elsif line =~ /Forwarding ports...$/
338
+ in_forwarding_ports = true
339
+ end
340
+ end
341
+ end
342
+
343
+ def parse_multi_vagrant_up(output, all_machine_specs)
344
+ # Grab forwarded port info
345
+ in_forwarding_ports = {}
346
+ all_machine_specs.each_pair do |key, spec|
347
+ spec.location['forwarded_ports'] = {}
348
+ in_forwarding_ports[key] = false
349
+ end
350
+ output.lines.each do |line|
351
+ /^\[(.*?)\]/.match(line)
352
+ node_name = $1
353
+ if in_forwarding_ports[node_name]
354
+ if line =~ /-- (\d+) => (\d+)/
355
+ spec = all_machine_specs[node_name]
356
+ spec.location['forwarded_ports'][$1] = $2
357
+ else
358
+ in_forwarding_ports[node_name] = false
359
+ end
360
+ elsif line =~ /Forwarding ports...$/
361
+ in_forwarding_ports[node_name] = true
362
+ end
363
+ end
364
+ end
365
+
366
+ def machine_for(machine_spec, machine_options)
367
+ if machine_spec.location['vm.guest'].to_s == 'windows'
368
+ Chef::Provisioning::Machine::WindowsMachine.new(machine_spec, transport_for(machine_spec),
369
+ convergence_strategy_for(machine_spec, machine_options))
370
+ else
371
+ Chef::Provisioning::Machine::UnixMachine.new(machine_spec, transport_for(machine_spec),
372
+ convergence_strategy_for(machine_spec, machine_options))
373
+ end
374
+ end
375
+
376
+ def convergence_strategy_for(machine_spec, machine_options)
377
+ if machine_spec.location['vm.guest'].to_s == 'windows'
378
+ Chef::Provisioning::ConvergenceStrategy::InstallMsi.
379
+ new(machine_options[:convergence_options], config)
380
+ else
381
+ Chef::Provisioning::ConvergenceStrategy::InstallCached.
382
+ new(machine_options[:convergence_options], config)
383
+ end
384
+ end
385
+
386
+ def transport_for(machine_spec)
387
+ if machine_spec.location['vm.guest'].to_s == 'windows'
388
+ create_winrm_transport(machine_spec)
389
+ else
390
+ create_ssh_transport(machine_spec)
391
+ end
392
+ end
393
+
394
+ def vagrant_status(name)
395
+ status_output = shell_out("vagrant status #{name}", :cwd => cluster_path).stdout
396
+ if status_output =~ /^#{name}\s+(.+)\s+\((.+)\)/
397
+ $1
398
+ else
399
+ 'not created'
400
+ end
401
+ end
402
+
403
+ def create_winrm_transport(machine_spec)
404
+ forwarded_ports = machine_spec.location['forwarded_ports']
405
+
406
+ # TODO IPv6 loopback? What do we do for that?
407
+ hostname = machine_spec.location['winrm.host'] || '127.0.0.1'
408
+ port = machine_spec.location['winrm.port'] || 5985
409
+ port = forwarded_ports[port] if forwarded_ports[port]
410
+ endpoint = "http://#{hostname}:#{port}/wsman"
411
+ type = :plaintext
412
+ options = {
413
+ :user => machine_spec.location['winrm.username'] || 'vagrant',
414
+ :pass => machine_spec.location['winrm.password'] || 'vagrant',
415
+ :disable_sspi => true
416
+ }
417
+
418
+ Chef::Provisioning::Transport::WinRM.new(endpoint, type, options)
419
+ end
420
+
421
+ def create_ssh_transport(machine_spec)
422
+ vagrant_ssh_config = vagrant_ssh_config_for(machine_spec)
423
+ hostname = vagrant_ssh_config['HostName']
424
+ username = vagrant_ssh_config['User']
425
+ ssh_options = {
426
+ :port => vagrant_ssh_config['Port'],
427
+ :auth_methods => ['publickey'],
428
+ :user_known_hosts_file => vagrant_ssh_config['UserKnownHostsFile'],
429
+ :paranoid => yes_or_no(vagrant_ssh_config['StrictHostKeyChecking']),
430
+ :keys => [ strip_quotes(vagrant_ssh_config['IdentityFile']) ],
431
+ :keys_only => yes_or_no(vagrant_ssh_config['IdentitiesOnly'])
432
+ }
433
+ ssh_options[:auth_methods] = %w(password) if yes_or_no(vagrant_ssh_config['PasswordAuthentication'])
434
+ options = {
435
+ :prefix => 'sudo '
436
+ }
437
+ Chef::Provisioning::Transport::SSH.new(hostname, username, ssh_options, options, config)
438
+ end
439
+
440
+ def vagrant_ssh_config_for(machine_spec)
441
+ vagrant_ssh_config = {}
442
+ result = shell_out("vagrant ssh-config #{machine_spec.location['vm_name']}",
443
+ :cwd => cluster_path)
444
+ result.stdout.lines.inject({}) do |result, line|
445
+ line =~ /^\s*(\S+)\s+(.+?)(\r\n|\r|\n|\z)/
446
+ vagrant_ssh_config[$1] = $2
447
+ end
448
+ vagrant_ssh_config
449
+ end
450
+
451
+ def yes_or_no(str)
452
+ case str
453
+ when 'yes'
454
+ true
455
+ else
456
+ false
457
+ end
458
+ end
459
+
460
+ def strip_quotes(str)
461
+ if str[0] == '"' && str[-1] == '"' && str.size >= 2
462
+ str[1..-2]
463
+ else
464
+ str
465
+ end
466
+ end
467
+ end
468
+ end
469
+ end
470
+ end