omnibus 3.1.1 → 3.2.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +71 -0
  3. data/Gemfile +0 -7
  4. data/README.md +108 -36
  5. data/Rakefile +1 -5
  6. data/docs/omnibus-build-cache.md +5 -5
  7. data/features/commands/_deprecated.feature +21 -3
  8. data/features/step_definitions/generator_steps.rb +7 -7
  9. data/lib/omnibus.rb +232 -171
  10. data/lib/omnibus/build_version.rb +2 -2
  11. data/lib/omnibus/builder.rb +38 -19
  12. data/lib/omnibus/cleaner.rb +5 -5
  13. data/lib/omnibus/cleanroom.rb +141 -0
  14. data/lib/omnibus/cli.rb +6 -9
  15. data/lib/omnibus/cli/base.rb +2 -1
  16. data/lib/omnibus/cli/cache.rb +15 -21
  17. data/lib/omnibus/cli/deprecated.rb +40 -4
  18. data/lib/omnibus/cli/publish.rb +61 -0
  19. data/lib/omnibus/config.rb +350 -189
  20. data/lib/omnibus/digestable.rb +131 -0
  21. data/lib/omnibus/exceptions.rb +163 -83
  22. data/lib/omnibus/fetcher.rb +1 -1
  23. data/lib/omnibus/fetchers/net_fetcher.rb +19 -13
  24. data/lib/omnibus/fetchers/path_fetcher.rb +8 -1
  25. data/lib/omnibus/fetchers/s3_cache_fetcher.rb +16 -7
  26. data/lib/omnibus/generator.rb +2 -2
  27. data/lib/omnibus/generator_files/Gemfile.erb +4 -1
  28. data/lib/omnibus/generator_files/README.md.erb +10 -0
  29. data/lib/omnibus/generator_files/{omnibus.rb.example.erb → omnibus.rb.erb} +20 -11
  30. data/lib/omnibus/generator_files/package_scripts/makeselfinst.erb +1 -1
  31. data/lib/omnibus/generator_files/project.rb.erb +2 -2
  32. data/lib/omnibus/generator_files/windows_msi/localization-en-us.wxl.erb +3 -3
  33. data/lib/omnibus/git_cache.rb +192 -0
  34. data/lib/omnibus/health_check.rb +171 -116
  35. data/lib/omnibus/library.rb +4 -2
  36. data/lib/omnibus/logger.rb +60 -1
  37. data/lib/omnibus/null_argumentable.rb +51 -0
  38. data/lib/omnibus/ohai.rb +29 -8
  39. data/lib/omnibus/package.rb +240 -0
  40. data/lib/omnibus/packagers/base.rb +21 -42
  41. data/lib/omnibus/packagers/mac_dmg.rb +5 -5
  42. data/lib/omnibus/packagers/mac_pkg.rb +20 -19
  43. data/lib/omnibus/packagers/windows_msi.rb +7 -7
  44. data/lib/omnibus/project.rb +969 -486
  45. data/lib/omnibus/publisher.rb +76 -0
  46. data/lib/omnibus/publishers/artifactory_publisher.rb +168 -0
  47. data/lib/omnibus/publishers/null_publisher.rb +23 -0
  48. data/lib/omnibus/publishers/s3_publisher.rb +99 -0
  49. data/lib/omnibus/s3_cache.rb +150 -63
  50. data/lib/omnibus/software.rb +749 -321
  51. data/lib/omnibus/{sugar.rb → sugarable.rb} +11 -6
  52. data/lib/omnibus/version.rb +1 -1
  53. data/omnibus.gemspec +8 -8
  54. data/spec/data/complicated/config/projects/angrychef.rb +1 -1
  55. data/spec/data/complicated/config/projects/chef-windows.rb +1 -1
  56. data/spec/data/complicated/config/projects/chef.rb +1 -1
  57. data/spec/data/complicated/config/projects/chefdk-windows.rb +1 -1
  58. data/spec/data/complicated/config/projects/chefdk.rb +1 -1
  59. data/spec/data/complicated/config/software/cacerts.rb +1 -1
  60. data/spec/data/complicated/config/software/chef-client-msi.rb +1 -1
  61. data/spec/data/complicated/config/software/libgcc.rb +1 -1
  62. data/spec/data/complicated/config/software/libiconv.rb +0 -11
  63. data/spec/data/complicated/config/software/libpng.rb +2 -2
  64. data/spec/data/complicated/config/software/openssl.rb +1 -1
  65. data/spec/data/complicated/config/software/ruby.rb +1 -1
  66. data/spec/data/complicated/config/software/runit.rb +4 -4
  67. data/spec/data/projects/chefdk.rb +1 -1
  68. data/spec/data/projects/sample.rb +1 -1
  69. data/spec/data/software/erchef.rb +3 -1
  70. data/spec/functional/packagers/mac_spec.rb +25 -24
  71. data/spec/functional/packagers/windows_spec.rb +21 -20
  72. data/spec/spec_helper.rb +43 -4
  73. data/spec/unit/build_version_spec.rb +14 -16
  74. data/spec/unit/cleanroom_spec.rb +63 -0
  75. data/spec/unit/config_spec.rb +36 -30
  76. data/spec/unit/digestable_spec.rb +38 -0
  77. data/spec/unit/fetchers/net_fetcher_spec.rb +98 -87
  78. data/spec/unit/{install_path_cache_spec.rb → git_cache_spec.rb} +67 -56
  79. data/spec/unit/health_check_spec.rb +73 -0
  80. data/spec/unit/library_spec.rb +166 -159
  81. data/spec/unit/ohai_spec.rb +19 -0
  82. data/spec/unit/omnibus_spec.rb +43 -41
  83. data/spec/unit/package_spec.rb +178 -0
  84. data/spec/unit/packagers/base_spec.rb +17 -47
  85. data/spec/unit/packagers/mac_pkg_spec.rb +104 -126
  86. data/spec/unit/project_spec.rb +176 -25
  87. data/spec/unit/publisher_spec.rb +49 -0
  88. data/spec/unit/publishers/artifactory_publisher_spec.rb +80 -0
  89. data/spec/unit/publishers/s3_publisher_spec.rb +120 -0
  90. data/spec/unit/s3_cacher_spec.rb +84 -19
  91. data/spec/unit/software_spec.rb +397 -170
  92. data/spec/unit/sugarable_spec.rb +43 -0
  93. metadata +62 -50
  94. data/Guardfile +0 -10
  95. data/lib/omnibus/artifact.rb +0 -165
  96. data/lib/omnibus/cli/release.rb +0 -40
  97. data/lib/omnibus/generator_files/Vagrantfile.erb +0 -75
  98. data/lib/omnibus/install_path_cache.rb +0 -105
  99. data/lib/omnibus/overrides.rb +0 -88
  100. data/lib/omnibus/package_release.rb +0 -154
  101. data/lib/omnibus/software_s3_urls.rb +0 -50
  102. data/spec/unit/artifact_spec.rb +0 -91
  103. data/spec/unit/overrides_spec.rb +0 -102
  104. data/spec/unit/package_release_spec.rb +0 -180
  105. data/spec/unit/sugar_spec.rb +0 -17
@@ -17,6 +17,7 @@
17
17
  module Omnibus
18
18
  class HealthCheck
19
19
  include Logging
20
+ include Util
20
21
 
21
22
  WHITELIST_LIBS = [
22
23
  /ld-linux/,
@@ -34,7 +35,7 @@ module Omnibus
34
35
  /libutil\.so/,
35
36
  /linux-vdso.+/,
36
37
  /linux-gate\.so/,
37
- ]
38
+ ].freeze
38
39
 
39
40
  ARCH_WHITELIST_LIBS = [
40
41
  /libc\.so/,
@@ -48,7 +49,7 @@ module Omnibus
48
49
  /libpthread\.so/,
49
50
  /librt\.so/,
50
51
  /libutil\.so/,
51
- ]
52
+ ].freeze
52
53
 
53
54
  AIX_WHITELIST_LIBS = [
54
55
  /libpthread\.a/,
@@ -58,7 +59,7 @@ module Omnibus
58
59
  /libc\.a/,
59
60
  /libcrypt\.a/,
60
61
  /unix$/,
61
- ]
62
+ ].freeze
62
63
 
63
64
  SOLARIS_WHITELIST_LIBS = [
64
65
  /libaio\.so/,
@@ -90,7 +91,7 @@ module Omnibus
90
91
  /libm\.so\.1/,
91
92
  /libc_psr\.so\.1/,
92
93
  /s9_preload\.so\.1/,
93
- ]
94
+ ].freeze
94
95
 
95
96
  SMARTOS_WHITELIST_LIBS = [
96
97
  /libm.so/,
@@ -106,7 +107,7 @@ module Omnibus
106
107
  /libgcc_s.so/,
107
108
  /libstdc\+\+\.so/,
108
109
  /libcrypt.so/,
109
- ]
110
+ ].freeze
110
111
 
111
112
  MAC_WHITELIST_LIBS = [
112
113
  /libobjc\.A\.dylib/,
@@ -124,7 +125,7 @@ module Omnibus
124
125
  /libiconv/,
125
126
  /libstdc\+\+\.6\.dylib/,
126
127
  /libc\+\+\.1\.dylib/,
127
- ]
128
+ ].freeze
128
129
 
129
130
  FREEBSD_WHITELIST_LIBS = [
130
131
  /libc\.so/,
@@ -133,18 +134,57 @@ module Omnibus
133
134
  /librt\.so/,
134
135
  /libthr\.so/,
135
136
  /libutil\.so/,
136
- ]
137
-
138
- def self.run(install_dir, whitelist_files = [])
139
- case Ohai.platform
140
- when 'mac_os_x'
141
- bad_libs = health_check_otool(install_dir, whitelist_files)
142
- when 'aix'
143
- bad_libs = health_check_aix(install_dir, whitelist_files)
144
- else
145
- bad_libs = health_check_ldd(install_dir, whitelist_files)
137
+ ].freeze
138
+
139
+ class << self
140
+ # @see (HealthCheck#new)
141
+ def run!(project)
142
+ new(project).run!
143
+ end
144
+ end
145
+
146
+ #
147
+ # The project to healthcheck.
148
+ #
149
+ # @return [Project]
150
+ #
151
+ attr_reader :project
152
+
153
+ #
154
+ # Run the healthchecks against the given project. It is assumed that the
155
+ # project has already been built.
156
+ #
157
+ # @param [Project] project
158
+ # the project to health check
159
+ #
160
+ def initialize(project)
161
+ @project = project
162
+ end
163
+
164
+ #
165
+ # Run the given health check. Healthcheks are skipped on Windows.
166
+ #
167
+ # @raise [HealthCheckFailed]
168
+ # if the health check fails
169
+ #
170
+ # @return [true]
171
+ # if the healthchecks pass
172
+ #
173
+ def run!
174
+ if Ohai['platform'] == 'windows'
175
+ log.warn(log_key) { 'Skipping health check on Windows' }
176
+ return true
146
177
  end
147
178
 
179
+ bad_libs = case Ohai['platform']
180
+ when 'mac_os_x'
181
+ health_check_otool
182
+ when 'aix'
183
+ health_check_aix
184
+ else
185
+ health_check_ldd
186
+ end
187
+
148
188
  unresolved = []
149
189
  unreliable = []
150
190
  detail = []
@@ -163,10 +203,10 @@ module Omnibus
163
203
  end
164
204
  end
165
205
 
166
- log.warn(log_key) { 'Failed!' }
206
+ log.error(log_key) { 'Failed!' }
167
207
  bad_omnibus_libs, bad_omnibus_bins = bad_libs.keys.partition { |k| k.include? 'embedded/lib' }
168
208
 
169
- log.warn(log_key) do
209
+ log.error(log_key) do
170
210
  out = "The following libraries have unsafe or unmet dependencies:\n"
171
211
 
172
212
  bad_omnibus_libs.each do |lib|
@@ -176,7 +216,7 @@ module Omnibus
176
216
  out
177
217
  end
178
218
 
179
- log.warn(log_key) do
219
+ log.error(log_key) do
180
220
  out = "The following binaries have unsafe or unmet dependencies:\n"
181
221
 
182
222
  bad_omnibus_bins.each do |bin|
@@ -187,7 +227,7 @@ module Omnibus
187
227
  end
188
228
 
189
229
  if unresolved.length > 0
190
- log.warn(log_key) do
230
+ log.error(log_key) do
191
231
  out = "The following requirements could not be resolved:\n"
192
232
 
193
233
  unresolved.each do |lib|
@@ -199,7 +239,7 @@ module Omnibus
199
239
  end
200
240
 
201
241
  if unreliable.length > 0
202
- log.warn(log_key) do
242
+ log.error(log_key) do
203
243
  out = "The following libraries cannot be guaranteed to be on "
204
244
  out << "target systems:\n"
205
245
 
@@ -211,7 +251,7 @@ module Omnibus
211
251
  end
212
252
  end
213
253
 
214
- log.warn(log_key) do
254
+ log.error(log_key) do
215
255
  out = "The precise failures were:\n"
216
256
 
217
257
  detail.each do |line|
@@ -228,101 +268,47 @@ module Omnibus
228
268
  out
229
269
  end
230
270
 
231
- raise 'Health Check Failed'
271
+ raise HealthCheckFailed
232
272
  end
233
- end
234
273
 
235
- def self.health_check_otool(install_dir, whitelist_files)
236
- otool_cmd = "find #{install_dir}/ -type f | egrep '\.(dylib|bundle)$' | xargs otool -L > otool.out 2>/dev/null"
237
- log.info(log_key) { "Executing: `#{otool_cmd}`" }
238
- shell = Mixlib::ShellOut.new(otool_cmd, timeout: 3600)
239
- shell.run_command
240
-
241
- otool_output = File.read('otool.out')
274
+ true
275
+ end
242
276
 
277
+ #
278
+ # Run healthchecks against otool.
279
+ #
280
+ # @return [Array<String>]
281
+ # the bad libraries
282
+ #
283
+ def health_check_otool
243
284
  current_library = nil
244
285
  bad_libs = {}
245
286
 
246
- otool_output.each_line do |line|
287
+ read_shared_libs("find #{project.install_dir}/ -type f | egrep '\.(dylib|bundle)$' | xargs otool -L") do |line|
247
288
  case line
248
289
  when /^(.+):$/
249
290
  current_library = Regexp.last_match[1]
250
291
  when /^\s+(.+) \(.+\)$/
251
292
  linked = Regexp.last_match[1]
252
293
  name = File.basename(linked)
253
- bad_libs = check_for_bad_library(install_dir, bad_libs, whitelist_files, current_library, name, linked)
254
- end
255
- end
256
-
257
- File.delete('otool.out')
258
-
259
- bad_libs
260
- end
261
-
262
- def self.check_for_bad_library(install_dir, bad_libs, whitelist_files, current_library, name, linked)
263
- safe = nil
264
-
265
- whitelist_libs = case Ohai.platform
266
- when 'arch'
267
- ARCH_WHITELIST_LIBS
268
- when 'mac_os_x'
269
- MAC_WHITELIST_LIBS
270
- when 'solaris2'
271
- SOLARIS_WHITELIST_LIBS
272
- when 'smartos'
273
- SMARTOS_WHITELIST_LIBS
274
- when 'freebsd'
275
- FREEBSD_WHITELIST_LIBS
276
- when 'aix'
277
- AIX_WHITELIST_LIBS
278
- else
279
- WHITELIST_LIBS
280
- end
281
- whitelist_libs.each do |reg|
282
- safe ||= true if reg.match(name)
283
- end
284
- whitelist_files.each do |reg|
285
- safe ||= true if reg.match(current_library)
286
- end
287
-
288
- log.debug(log_key) { " --> Dependency: #{name}" }
289
- log.debug(log_key) { " --> Provided by: #{linked}" }
290
-
291
- if !safe && linked !~ Regexp.new(install_dir)
292
- log.debug(log_key) { " -> FAILED: #{current_library} has unsafe dependencies" }
293
- bad_libs[current_library] ||= {}
294
- bad_libs[current_library][name] ||= {}
295
- if bad_libs[current_library][name].key?(linked)
296
- bad_libs[current_library][name][linked] += 1
297
- else
298
- bad_libs[current_library][name][linked] = 1
294
+ bad_libs = check_for_bad_library(bad_libs, current_library, name, linked)
299
295
  end
300
- else
301
- log.debug(log_key) { " -> PASSED: #{name} is either whitelisted or safely provided." }
302
296
  end
303
297
 
304
298
  bad_libs
305
299
  end
306
300
 
307
- def self.health_check_aix(install_dir, whitelist_files)
308
- #
309
- # ShellOut has GC turned off during execution, so when we're
310
- # executing extremely long commands with lots of output, we
311
- # should be mindful that the string concatentation for building
312
- # #stdout will hurt memory usage drastically
313
- #
314
- ldd_cmd = "find #{install_dir}/ -type f | xargs file | grep \"RISC System\" | awk -F: '{print $1}' | xargs -n 1 ldd > ldd.out 2>/dev/null"
315
-
316
- log.info(log_key) { "Executing `#{ldd_cmd}`" }
317
- shell = Mixlib::ShellOut.new(ldd_cmd, timeout: 3600)
318
- shell.run_command
319
-
320
- ldd_output = File.read('ldd.out')
321
-
301
+ #
302
+ # Run healthchecks against aix.
303
+ #
304
+ # @return [Array<String>]
305
+ # the bad libraries
306
+ #
307
+ def health_check_aix
322
308
  current_library = nil
323
309
  bad_libs = {}
324
310
 
325
- ldd_output.each_line do |line|
311
+ read_shared_libs("find #{project.install_dir}/ -type f | xargs file | grep \"RISC System\" | awk -F: '{print $1}' | xargs -n 1 ldd") do |line|
326
312
  case line
327
313
  when /^(.+) needs:$/
328
314
  current_library = Regexp.last_match[1]
@@ -330,36 +316,27 @@ module Omnibus
330
316
  when /^\s+(.+)$/
331
317
  name = Regexp.last_match[1]
332
318
  linked = Regexp.last_match[1]
333
- bad_libs = check_for_bad_library(install_dir, bad_libs, whitelist_files, current_library, name, linked)
319
+ bad_libs = check_for_bad_library(bad_libs, current_library, name, linked)
334
320
  when /File is not an executable XCOFF file/ # ignore non-executable files
335
321
  else
336
322
  log.warn(log_key) { "Line did not match for #{current_library}\n#{line}" }
337
323
  end
338
324
  end
339
325
 
340
- File.delete('ldd.out')
341
326
  bad_libs
342
327
  end
343
328
 
344
- def self.health_check_ldd(install_dir, whitelist_files)
345
- #
346
- # ShellOut has GC turned off during execution, so when we're
347
- # executing extremely long commands with lots of output, we
348
- # should be mindful that the string concatentation for building
349
- # #stdout will hurt memory usage drastically
350
- #
351
- ldd_cmd = "find #{install_dir}/ -type f | xargs ldd > ldd.out 2>/dev/null"
352
-
353
- log.info(log_key) { "Executing `#{ldd_cmd}`" }
354
- shell = Mixlib::ShellOut.new(ldd_cmd, timeout: 3600)
355
- shell.run_command
356
-
357
- ldd_output = File.read('ldd.out')
358
-
329
+ #
330
+ # Run healthchecks against ldd.
331
+ #
332
+ # @return [Array<String>]
333
+ # the bad libraries
334
+ #
335
+ def health_check_ldd
359
336
  current_library = nil
360
337
  bad_libs = {}
361
338
 
362
- ldd_output.each_line do |line|
339
+ read_shared_libs("find #{project.install_dir}/ -type f | xargs ldd") do |line|
363
340
  case line
364
341
  when /^(.+):$/
365
342
  current_library = Regexp.last_match[1]
@@ -367,7 +344,7 @@ module Omnibus
367
344
  when /^\s+(.+) \=\>\s+(.+)( \(.+\))?$/
368
345
  name = Regexp.last_match[1]
369
346
  linked = Regexp.last_match[2]
370
- bad_libs = check_for_bad_library(install_dir, bad_libs, whitelist_files, current_library, name, linked)
347
+ bad_libs = check_for_bad_library(bad_libs, current_library, name, linked)
371
348
  when /^\s+(.+) \(.+\)$/
372
349
  next
373
350
  when /^\s+statically linked$/
@@ -386,7 +363,85 @@ module Omnibus
386
363
  end
387
364
  end
388
365
 
389
- File.delete('ldd.out')
366
+ bad_libs
367
+ end
368
+
369
+ private
370
+
371
+ #
372
+ # The list of whitelisted (ignored) files from the project and softwares.
373
+ #
374
+ # @return [Array<String, Regexp>]
375
+ #
376
+ def whitelist_files
377
+ project.library.components.inject([]) do |array, component|
378
+ array += component.whitelist_files
379
+ array
380
+ end
381
+ end
382
+
383
+ #
384
+ # Execute the given command, yielding each line.
385
+ #
386
+ # @param [String] command
387
+ # the command to execute
388
+ # @yield [String]
389
+ # each line
390
+ #
391
+ def read_shared_libs(command)
392
+ cmd = shellout(command)
393
+ cmd.stdout.each_line do |line|
394
+ yield line
395
+ end
396
+ end
397
+
398
+ #
399
+ # Check the given path and library for "bad" libraries.
400
+ #
401
+ def check_for_bad_library(bad_libs, current_library, name, linked)
402
+ safe = nil
403
+
404
+ whitelist_libs = case Ohai['platform']
405
+ when 'arch'
406
+ ARCH_WHITELIST_LIBS
407
+ when 'mac_os_x'
408
+ MAC_WHITELIST_LIBS
409
+ when 'solaris2'
410
+ SOLARIS_WHITELIST_LIBS
411
+ when 'smartos'
412
+ SMARTOS_WHITELIST_LIBS
413
+ when 'freebsd'
414
+ FREEBSD_WHITELIST_LIBS
415
+ when 'aix'
416
+ AIX_WHITELIST_LIBS
417
+ else
418
+ WHITELIST_LIBS
419
+ end
420
+
421
+ whitelist_libs.each do |reg|
422
+ safe ||= true if reg.match(name)
423
+ end
424
+
425
+ whitelist_files.each do |reg|
426
+ safe ||= true if reg.match(current_library)
427
+ end
428
+
429
+ log.debug(log_key) { " --> Dependency: #{name}" }
430
+ log.debug(log_key) { " --> Provided by: #{linked}" }
431
+
432
+ if !safe && linked !~ Regexp.new(project.install_dir)
433
+ log.debug(log_key) { " -> FAILED: #{current_library} has unsafe dependencies" }
434
+ bad_libs[current_library] ||= {}
435
+ bad_libs[current_library][name] ||= {}
436
+ if bad_libs[current_library][name].key?(linked)
437
+ bad_libs[current_library][name][linked] += 1
438
+ else
439
+ bad_libs[current_library][name][linked] = 1
440
+ end
441
+ else
442
+ log.debug(log_key) { " -> PASSED: #{name} is either whitelisted or safely provided." }
443
+ end
444
+
390
445
  bad_libs
391
446
  end
392
447
  end
@@ -18,6 +18,8 @@ module Omnibus
18
18
  #
19
19
  # Used to generate the manifest of all software components with versions
20
20
  class Library
21
+ include Enumerable
22
+
21
23
  # The list of Omnibus::Software definitions. This is populated by calling
22
24
  # #component_added during code loading. The list is expected to be sorted
23
25
  # in a valid order according to project and software dependencies, but this
@@ -98,8 +100,8 @@ module Omnibus
98
100
  end
99
101
  end
100
102
 
101
- def select(*args, &block)
102
- @components.select(*args, &block)
103
+ def each(&block)
104
+ @components.each(&block)
103
105
  end
104
106
  end
105
107
  end