vanagon 0.5.2 → 0.5.3

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: 8a3414d151dd4f8f7162a06b6dfe3a5dc8c9b066
4
- data.tar.gz: 944acf2e2cfa169c60f3072d05a5add5c03ac25c
3
+ metadata.gz: fd0b8d155b61fe71dc4b21216f3cd8674734c790
4
+ data.tar.gz: b3b1554b32d14049b08eb56c89206f9b71e120ff
5
5
  SHA512:
6
- metadata.gz: d88e78e71ccdd7f878141dc0b26d741bbef71b9f9c21e8cc8f766bf241bc8c317c6090e9781508f812d17dddc46e8af42f39d38274618934d4871de498eecf45
7
- data.tar.gz: 0152bcaa044f2c8f939a7c8bb4434801d023397d7d156692f6648a55bceca6958a3182577fd6b4492999712cb07ce7eaef017e7c7150cf2205153ddd318750e7
6
+ metadata.gz: f9646e8ab2503dfe9433e91f25af53c2a7debcadb276d9d4338a4f8ff11749a3125f7ec04a007c855bf7e6a5b9878e5bba9227fb42e2aa73d14e9d8e9bcf5462
7
+ data.tar.gz: 945246b7da4cc69b58a919c6f91df69db236e9be28039c7b1c0e78acf90e2b285c268b3730204a03050026901a4f890245fec9e89918098026fa6067eaf8ff47
@@ -184,7 +184,11 @@ class Vanagon
184
184
  # Return here because there is no file to install, just a string read in
185
185
  return
186
186
  when "windows"
187
- @component.service = OpenStruct.new(:id => "#{service_name.gsub(/[^A-Za-z0-9]/, '').upcase}", :service_file => service_file)
187
+ @component.service = OpenStruct.new(\
188
+ :bindir_id => "#{service_name.gsub(/[^A-Za-z0-9]/, '').upcase}BINDIR", \
189
+ :service_file => service_file, \
190
+ :component_group_id => "#{service_name.gsub(/[^A-Za-z0-9]/, '')}Component"\
191
+ )
188
192
  # return here as we are just collecting the name of the service file to put into the harvest filter list.
189
193
  return
190
194
  else
@@ -11,6 +11,7 @@ class Vanagon
11
11
  class Driver
12
12
  include Vanagon::Utilities
13
13
  attr_accessor :platform, :project, :target, :workdir, :verbose, :preserve
14
+ attr_accessor :timeout, :retry_count
14
15
 
15
16
  def initialize(platform, project, options = { :configdir => nil, :target => nil, :engine => nil, :components => nil, :skipcheck => false })
16
17
  @verbose = false
@@ -24,8 +25,7 @@ class Vanagon
24
25
  @platform = Vanagon::Platform.load_platform(platform, File.join(@@configdir, "platforms"))
25
26
  @project = Vanagon::Project.load_project(project, File.join(@@configdir, "projects"), @platform, components)
26
27
  @project.settings[:skipcheck] = options[:skipcheck]
27
- @@logger = Logger.new('vanagon_hosts.log')
28
- @@logger.progname = 'vanagon'
28
+ loginit('vanagon_hosts.log')
29
29
 
30
30
  # If a target has been given, we don't want to make any assumptions about how to tear it down.
31
31
  engine = 'base' if target
@@ -76,14 +76,13 @@ class Vanagon
76
76
  @engine.startup(@workdir)
77
77
 
78
78
  puts "Target is #{@engine.target}"
79
-
80
- install_build_dependencies
79
+ retry_task { install_build_dependencies }
81
80
  @project.fetch_sources(@workdir)
82
81
  @project.make_makefile(@workdir)
83
82
  @project.make_bill_of_materials(@workdir)
84
83
  @project.generate_packaging_artifacts(@workdir)
85
84
  @engine.ship_workdir(@workdir)
86
- @engine.dispatch("(cd #{@engine.remote_workdir}; #{@platform.make})")
85
+ retry_task { @engine.dispatch("(cd #{@engine.remote_workdir}; #{@platform.make})") }
87
86
  @engine.retrieve_built_artifact
88
87
  @engine.teardown unless @preserve
89
88
  cleanup_workdir unless @preserve
@@ -95,7 +94,7 @@ class Vanagon
95
94
  if @engine.name == "hardware"
96
95
  @engine.teardown
97
96
  end
98
- end
97
+ end
99
98
 
100
99
  def prepare(workdir = nil)
101
100
  @workdir = workdir ? FileUtils.mkdir_p(workdir).first : Dir.mktmpdir
@@ -115,5 +114,22 @@ class Vanagon
115
114
  puts e.backtrace.join("\n")
116
115
  raise e
117
116
  end
117
+
118
+ # Retry the provided block, use the retry count and timeout
119
+ # values from the project, if available, otherwise use some
120
+ # sane defaults.
121
+ def retry_task(&block)
122
+ @timeout = @project.timeout || 3600
123
+ @retry_count = @project.retry_count || 3
124
+ Vanagon::Utilities.retry_with_timeout(@retry_count, @timeout) { yield }
125
+ end
126
+ private :retry_task
127
+
128
+ # Initialize the logging instance
129
+ def loginit(logfile)
130
+ @@logger = Logger.new(logfile)
131
+ @@logger.progname = 'vanagon'
132
+ end
133
+ private :loginit
118
134
  end
119
135
  end
@@ -289,6 +289,105 @@ class Vanagon
289
289
  File.join("windows", target_repo, @architecture)
290
290
  end
291
291
 
292
+ # Generate correctly formatted wix elements that match the
293
+ # structure of the directory input
294
+ #
295
+ # @param services, Array of components services
296
+ # and optionally:
297
+ # @return [string] correctly formatted wix element string
298
+ def generate_wix_dirs(services)
299
+ directories = []
300
+ services.map { |svc| directories.push({ :path => svc.service_file, :bindir_id => svc.bindir_id }) }
301
+ # root refers to the root of an n-ary tree (which we are about to make)
302
+ root = { :children => [] }
303
+ # iterate over all paths specified and break each one
304
+ # in to its specific directories. This will generate_wix_dirs
305
+ # an n-ary tree structure matching the specs from the input
306
+ directories.each do |dir|
307
+ # Always start at the beginning
308
+ curr = root
309
+ names = strip_path(dir[:path])
310
+ # The last entry in this list will be the actual file,
311
+ # which we do not want, we only want it's base path
312
+ names.pop
313
+ names.each do |name|
314
+ curr = insert_child(curr, name)
315
+ end
316
+ # at this point, curr will be the top dir, override the id if
317
+ # id exists
318
+ curr[:bindir_ids].push(dir[:bindir_id])
319
+ end
320
+ return generate_wix_from_graph(root)
321
+ end
322
+
323
+ # insert a new object with the name "name" if it doesn't already
324
+ # exist. Then assign curr to either the new child or the one that
325
+ # already exists here
326
+ #
327
+ # @param [HASH] curr, current object we are on
328
+ # @param [string] name, name of new object we are to search for and
329
+ # create if necessary
330
+ def insert_child(curr, name)
331
+ #The Id field will default to name, but be overridden later
332
+ new_obj = { :name => name, :id => name, :bindir_ids => [], :children => [] }
333
+ if (child_index = includes_child(new_obj, curr[:children]))
334
+ curr = curr[:children][child_index]
335
+ else
336
+ curr[:children].push(new_obj)
337
+ curr = new_obj
338
+ end
339
+ return curr
340
+ end
341
+
342
+ # strip and split the directory path into single names
343
+ # @param [string] path string of directory
344
+ def strip_path(path)
345
+ if path.include?("/") || path.include?("\\")
346
+ # The regex in the last part of this if warrants some
347
+ # explanation. Specifically it matches any combinations
348
+ # of any letters, then the : char, then finally either
349
+ # the char / or the char \. it's meant to parse out drive
350
+ # roots on windows
351
+ if path.start_with?("/") || path.start_with?("\\") || path.start_with?("SourceDir") || path =~ (/([A-Za-z])*\:(\/|\\)/)
352
+ path = path.sub(/\/|\\|([A-Za-z])*\:(\/|\\)|(\/|\\)?(SourceDir)(\/|\\)?/, '')
353
+ end
354
+ names = path.split(/\/|\\/)
355
+ end
356
+ return names
357
+ end
358
+
359
+ # Find if child element is the same as one of
360
+ # the old_children elements, return that child
361
+ def includes_child(new_child, old_children)
362
+ old_children.each_with_index do |curr_old_child, index|
363
+ return index if curr_old_child[:name] == new_child[:name]
364
+ end unless old_children.empty?
365
+ return nil
366
+ end
367
+
368
+
369
+ # Recursively generate wix element structure
370
+ #
371
+ # @param root, the (empty) root of an n-ary tree containing the
372
+ # structure of directories
373
+ def generate_wix_from_graph(root)
374
+ string = ''
375
+ unless root[:children].empty?
376
+ root[:children].each do |child|
377
+ string += ("<Directory Name=\"#{child[:name]}\" Id=\"#{child[:id]}\">\n")
378
+ unless child[:bindir_ids].empty?
379
+ child[:bindir_ids].each do |bindir_id|
380
+ string += ("<Directory Id=\"#{bindir_id}\" />\n")
381
+ end
382
+ end
383
+ string += generate_wix_from_graph(child)
384
+ string += ("</Directory>\n")
385
+ end
386
+ return string
387
+ end
388
+ return ''
389
+ end
390
+
292
391
  # Constructor. Sets up some defaults for the windows platform and calls the parent constructor
293
392
  #
294
393
  # Mingw varies on where it is installed based on architecture. We want to use which ever is on the system.
@@ -11,7 +11,7 @@ class Vanagon
11
11
  attr_accessor :version, :directories, :license, :description, :vendor
12
12
  attr_accessor :homepage, :requires, :user, :repo, :noarch, :identifier
13
13
  attr_accessor :cleanup, :version_file, :release, :replaces, :provides
14
- attr_accessor :bill_of_materials
14
+ attr_accessor :bill_of_materials, :retry_count, :timeout
15
15
 
16
16
  # Loads a given project from the configdir
17
17
  #
@@ -101,6 +101,22 @@ class Vanagon
101
101
  replaces.flatten.uniq
102
102
  end
103
103
 
104
+ # Grabs a specific service based on which name is passed in
105
+ # note that if the name is wrong or there was no
106
+ # @component.install_service call in the component, this
107
+ # will return nil
108
+ #
109
+ # @param [string] name of service to grab
110
+ # @return [@component.service obj] specific service
111
+ def get_service(name)
112
+ @components.each do |component|
113
+ if component.name == name
114
+ return component.service
115
+ end
116
+ end
117
+ return nil
118
+ end
119
+
104
120
  # Collects all of the provides for the project and its components
105
121
  #
106
122
  # @return [Array] array of package level provides for the project
@@ -35,3 +35,8 @@ fi
35
35
  fi
36
36
  <%- end -%>
37
37
  <%- end -%>
38
+
39
+ <%- get_services.each do |service| -%>
40
+ # Restarting service <%= service.name %>
41
+ /usr/sbin/svcadm restart <%= service.name %> || true
42
+ <%- end -%>
@@ -53,8 +53,11 @@ set name=org.opensolaris.smf.fmri <%= get_services.map {|service| "value=svc:/#{
53
53
  <%- end -%>
54
54
 
55
55
  <%- get_configfiles.each do |config| -%>
56
- # Preserve the old conf file on upgrade
56
+ # Preserve the old conf file on upgrade, restart services on config file change
57
57
  <transform file path=<%= strip_and_escape(config.path) %>$ -> add preserve renamenew>
58
+ <%- get_services.each do |service| -%>
59
+ <transform file path=<%= strip_and_escape(config.path) %>$ -> add restart_fmri <%= "svc:/#{service.name}:*" %> >
60
+ <%- end -%>
58
61
  <%- end -%>
59
62
 
60
63
  # Set any required owner, group or mode transformations
@@ -2,10 +2,8 @@
2
2
  <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi' xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
3
3
 
4
4
  <Fragment>
5
- <ComponentGroup Id="ServiceListGroup">
6
- <%- get_services.each do |service| -%>
7
- <ComponentGroupRef Id="Service_<%= service.id %>" />
8
- <%- end -%>
9
- </ComponentGroup>
5
+ <DirectoryRef Id='TARGETDIR'>
6
+ <%= @platform.generate_wix_dirs(self.get_services) %>
7
+ </DirectoryRef>
10
8
  </Fragment>
11
9
  </Wix>
@@ -15,8 +15,10 @@
15
15
  Description="<%= "#{settings[:product_id]}#{@platform.architecture == "x64" ? " (64-bit)" : ""}" %> Installer"
16
16
  Comments="<%= @homepage %>"
17
17
  Compressed="yes"
18
- Platform="<%= @platform.architecture %>"
19
- />
18
+ Platform="<%= @platform.architecture %>" />
19
+
20
+ <!-- We are discussing a MAINT PR to move the componentfilegroup to seperate file
21
+ This would allow project to specify additional fragments if needed -->
20
22
 
21
23
  <MajorUpgrade AllowDowngrades="yes" />
22
24
  <Media Id="1" Cabinet="<%= settings[:product_id] %>.cab" EmbedCab="yes" CompressionLevel="high" />
@@ -25,7 +27,13 @@
25
27
  <!-- We can add all components by referencing this one thing -->
26
28
  <ComponentGroupRef Id="ProductComponentGroup" />
27
29
  <ComponentGroupRef Id="RegistryComponentGroup" />
28
- <ComponentGroupRef Id="ServiceListGroup" />
30
+ <%- get_services.each do |service| -%>
31
+ <ComponentGroupRef Id="<%= service.component_group_id %>" />
32
+ <%- end -%>
33
+ <!-- All of these Include refs are expected to be present -->
34
+ <ComponentGroupRef Id="FragmentProperties" />
35
+ <ComponentGroupRef Id="FragmentSequences" />
36
+ <ComponentGroupRef Id="FragmentCustomActions" />
29
37
  </Feature>
30
38
  <!-- We will use DirectoryRef at the project level to hook in the project directory structure -->
31
39
  <Directory Id='TARGETDIR' Name='SourceDir' />
File without changes
@@ -1,4 +1,7 @@
1
1
  require 'vanagon/platform'
2
+ require 'vanagon/project'
3
+ require 'vanagon/common'
4
+
2
5
 
3
6
  # These constants are defined for the purpose of the project/generic file merge tests
4
7
  # to point these directories to test areas under the /tmp directory.
@@ -26,14 +29,17 @@ describe "Vanagon::Platform::Windows" do
26
29
  :output_dir_with_target => "windows/thing/x64",
27
30
  :target_user => "Administrator",
28
31
  :projname => "test-proj",
29
- :block => %Q[ platform "windows-2012r2-x64" do |plat| end ]
32
+ :block => %Q[ platform "windows-2012r2-x64" do |plat| plat.servicetype 'windows' end ]
30
33
  },
31
34
  ]
32
35
 
33
36
  platforms.each do |plat|
34
- context "on #{plat[:name]} we should behave ourselves" do
37
+ context "on #{plat[:name]}" do
35
38
  let(:platform) { plat }
36
39
  let(:cur_plat) { Vanagon::Platform::DSL.new(plat[:name]) }
40
+ let (:project_block) {
41
+ "project 'test-fixture' do |proj|
42
+ end" }
37
43
 
38
44
  before do
39
45
  cur_plat.instance_eval(plat[:block])
@@ -160,6 +166,123 @@ describe "Vanagon::Platform::Windows" do
160
166
  expect(File).not_to exist("#{WORKDIR}/wix/file-3.wxs.erb")
161
167
  expect(File).not_to exist("#{WORKDIR}/wix/file-4.wxs.erb")
162
168
  end
169
+
170
+
171
+ describe "generate_wix_dirs" do
172
+
173
+ it "returns one directory with install_service defaults" do
174
+ cur_plat.instance_eval(plat[:block])
175
+ comp = Vanagon::Component::DSL.new('service-test', {}, cur_plat._platform)
176
+ comp.install_service('/opt/bin.exe')
177
+ expect(cur_plat._platform.generate_wix_dirs([comp._component.service].flatten.compact)).to eq( \
178
+ <<-HERE
179
+ <Directory Name="opt" Id="opt">
180
+ <Directory Id="SERVICETESTBINDIR" />
181
+ </Directory>
182
+ HERE
183
+ )
184
+ end
185
+
186
+ it "returns one directory with non-default name" do
187
+ cur_plat.instance_eval(plat[:block])
188
+ comp = Vanagon::Component::DSL.new('service-test', {}, cur_plat._platform)
189
+ comp.install_service('/opt/bin.exe', nil, "service-test-2")
190
+ expect(cur_plat._platform.generate_wix_dirs([comp._component.service].flatten.compact)).to eq( \
191
+ <<-HERE
192
+ <Directory Name="opt" Id="opt">
193
+ <Directory Id="SERVICETEST2BINDIR" />
194
+ </Directory>
195
+ HERE
196
+ )
197
+ end
198
+
199
+ it "returns nested directory correctly with \\" do
200
+ cur_plat.instance_eval(plat[:block])
201
+ comp = Vanagon::Component::DSL.new('service-test', {}, cur_plat._platform)
202
+ comp.install_service('root\\programfiles\\bin.exe')
203
+ expect(cur_plat._platform.generate_wix_dirs([comp._component.service].flatten.compact)).to eq( \
204
+ <<-HERE
205
+ <Directory Name="root" Id="root">
206
+ <Directory Name="programfiles" Id="programfiles">
207
+ <Directory Id="SERVICETESTBINDIR" />
208
+ </Directory>
209
+ </Directory>
210
+ HERE
211
+ )
212
+ end
213
+
214
+ it "removes any drive roots" do
215
+ cur_plat.instance_eval(plat[:block])
216
+ comp = Vanagon::Component::DSL.new('service-test', {}, cur_plat._platform)
217
+ comp.install_service('C:\\programfiles\\bin.exe')
218
+ expect(cur_plat._platform.generate_wix_dirs([comp._component.service].flatten.compact)).to eq( \
219
+ <<-HERE
220
+ <Directory Name="programfiles" Id="programfiles">
221
+ <Directory Id="SERVICETESTBINDIR" />
222
+ </Directory>
223
+ HERE
224
+ )
225
+ end
226
+
227
+ it "removes SourceDir" do
228
+ cur_plat.instance_eval(plat[:block])
229
+ comp = Vanagon::Component::DSL.new('service-test', {}, cur_plat._platform)
230
+ comp.install_service('SourceDir\\programfiles\\bin.exe')
231
+ expect(cur_plat._platform.generate_wix_dirs([comp._component.service].flatten.compact)).to eq( \
232
+ <<-HERE
233
+ <Directory Name="programfiles" Id="programfiles">
234
+ <Directory Id="SERVICETESTBINDIR" />
235
+ </Directory>
236
+ HERE
237
+ )
238
+ end
239
+
240
+
241
+ it "adds a second directory for the same input but different components" do
242
+ cur_plat.instance_eval(plat[:block])
243
+ comp = Vanagon::Component::DSL.new('service-test', {}, cur_plat._platform)
244
+ comp.install_service('/programfiles/bin.exe')
245
+ comp2 = Vanagon::Component::DSL.new('service-test-2', {}, cur_plat._platform)
246
+ comp2.install_service('/programfiles/bin.exe')
247
+ expect(cur_plat._platform.generate_wix_dirs([comp._component.service, comp2._component.service].flatten.compact)).to eq( \
248
+ <<-HERE
249
+ <Directory Name="programfiles" Id="programfiles">
250
+ <Directory Id="SERVICETESTBINDIR" />
251
+ <Directory Id="SERVICETEST2BINDIR" />
252
+ </Directory>
253
+ HERE
254
+ )
255
+ end
256
+
257
+ it "returns correctly formatted multiple nested directories" do
258
+ cur_plat.instance_eval(plat[:block])
259
+ comp1 = Vanagon::Component::DSL.new('service-test1', {}, cur_plat._platform)
260
+ comp1.install_service('/opt/oneUp/twoUp/bin.exe')
261
+ comp2 = Vanagon::Component::DSL.new('service-test2', {}, cur_plat._platform)
262
+ comp2.install_service('/opt/oneUpAgain/twoUp/bin.exe')
263
+ comp3 = Vanagon::Component::DSL.new('service-test3', {}, cur_plat._platform)
264
+ comp3.install_service('/opt/oneUpAgain/twoUpAgain/bin.exe')
265
+ expect(cur_plat._platform.generate_wix_dirs([comp1._component.service, comp2._component.service, comp3._component.service].flatten.compact)).to eq( \
266
+ <<-HERE
267
+ <Directory Name="opt" Id="opt">
268
+ <Directory Name="oneUp" Id="oneUp">
269
+ <Directory Name="twoUp" Id="twoUp">
270
+ <Directory Id="SERVICETEST1BINDIR" />
271
+ </Directory>
272
+ </Directory>
273
+ <Directory Name="oneUpAgain" Id="oneUpAgain">
274
+ <Directory Name="twoUp" Id="twoUp">
275
+ <Directory Id="SERVICETEST2BINDIR" />
276
+ </Directory>
277
+ <Directory Name="twoUpAgain" Id="twoUpAgain">
278
+ <Directory Id="SERVICETEST3BINDIR" />
279
+ </Directory>
280
+ </Directory>
281
+ </Directory>
282
+ HERE
283
+ )
284
+ end
285
+ end
163
286
  end
164
287
  end
165
288
  end
@@ -154,5 +154,9 @@ describe "Vanagon::Utilities" do
154
154
  expect(Vanagon::Utilities).to receive(:remote_ssh_command).with(host, command, port).exactly(1).times.and_return(true)
155
155
  expect(Vanagon::Utilities.retry_with_timeout(tries, timeout) { Vanagon::Utilities.remote_ssh_command(host, command, port) }).to be(true)
156
156
  end
157
+
158
+ it 'raises a Vanagon::Error if the command times out' do
159
+ expect{ Vanagon::Utilities.retry_with_timeout(tries, timeout) { sleep 5 }.to raise_error(Vanagon::Error) }
160
+ end
157
161
  end
158
162
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vanagon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet Labs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-08 00:00:00.000000000 Z
11
+ date: 2016-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -132,7 +132,7 @@ files:
132
132
  - resources/windows/nuget/chocolateyInstall.ps1
133
133
  - resources/windows/nuget/chocolateyUninstall.ps1
134
134
  - resources/windows/nuget/project.nuspec.erb
135
- - resources/windows/wix/componentrefs.wxs.erb
135
+ - resources/windows/wix/directorylist.wxs.erb
136
136
  - resources/windows/wix/filter.xslt.erb
137
137
  - resources/windows/wix/project.wxs.erb
138
138
  - resources/windows/wix/registryEntries.wxs.erb
@@ -157,6 +157,7 @@ files:
157
157
  - spec/lib/vanagon/component/source/http_spec.rb
158
158
  - spec/lib/vanagon/component/source_spec.rb
159
159
  - spec/lib/vanagon/component_spec.rb
160
+ - spec/lib/vanagon/driver_spec.rb
160
161
  - spec/lib/vanagon/engine/base_spec.rb
161
162
  - spec/lib/vanagon/engine/docker_spec.rb
162
163
  - spec/lib/vanagon/engine/hardware_spec.rb
@@ -195,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
196
  version: '0'
196
197
  requirements: []
197
198
  rubyforge_project:
198
- rubygems_version: 2.4.6
199
+ rubygems_version: 2.5.1
199
200
  signing_key:
200
201
  specification_version: 3
201
202
  summary: All of your packages will fit into this van with this one simple trick.
@@ -209,6 +210,7 @@ test_files:
209
210
  - spec/lib/vanagon/component/source/http_spec.rb
210
211
  - spec/lib/vanagon/component/source_spec.rb
211
212
  - spec/lib/vanagon/component_spec.rb
213
+ - spec/lib/vanagon/driver_spec.rb
212
214
  - spec/lib/vanagon/engine/base_spec.rb
213
215
  - spec/lib/vanagon/engine/docker_spec.rb
214
216
  - spec/lib/vanagon/engine/hardware_spec.rb