omnibus 5.0.0 → 5.1.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +26 -0
  5. data/Gemfile +3 -0
  6. data/MAINTAINERS.md +1 -0
  7. data/appveyor.yml +1 -1
  8. data/bin/omnibus +5 -0
  9. data/lib/omnibus/builder.rb +165 -26
  10. data/lib/omnibus/digestable.rb +4 -2
  11. data/lib/omnibus/fetcher.rb +18 -5
  12. data/lib/omnibus/fetchers/git_fetcher.rb +38 -22
  13. data/lib/omnibus/fetchers/net_fetcher.rb +106 -37
  14. data/lib/omnibus/fetchers/path_fetcher.rb +13 -12
  15. data/lib/omnibus/file_syncer.rb +33 -14
  16. data/lib/omnibus/generator_files/README.md.erb +1 -1
  17. data/lib/omnibus/generator_files/package_scripts/postinst.erb +3 -3
  18. data/lib/omnibus/generator_files/package_scripts/postrm.erb +1 -1
  19. data/lib/omnibus/generator_files/package_scripts/preinst.erb +1 -1
  20. data/lib/omnibus/generator_files/package_scripts/prerm.erb +3 -3
  21. data/lib/omnibus/git_cache.rb +20 -7
  22. data/lib/omnibus/health_check.rb +144 -12
  23. data/lib/omnibus/packagers/bff.rb +57 -5
  24. data/lib/omnibus/packagers/deb.rb +2 -2
  25. data/lib/omnibus/packagers/pkg.rb +2 -2
  26. data/lib/omnibus/packagers/solaris.rb +18 -6
  27. data/lib/omnibus/project.rb +1 -1
  28. data/lib/omnibus/s3_cache.rb +8 -2
  29. data/lib/omnibus/software.rb +152 -18
  30. data/lib/omnibus/sugarable.rb +1 -5
  31. data/lib/omnibus/util.rb +1 -1
  32. data/lib/omnibus/version.rb +1 -1
  33. data/omnibus.gemspec +4 -1
  34. data/resources/bff/config.erb +7 -0
  35. data/resources/deb/md5sums.erb +1 -1
  36. data/spec/functional/builder_spec.rb +89 -2
  37. data/spec/functional/fetchers/git_fetcher_spec.rb +44 -37
  38. data/spec/functional/fetchers/net_fetcher_spec.rb +36 -5
  39. data/spec/functional/fetchers/path_fetcher_spec.rb +28 -28
  40. data/spec/unit/builder_spec.rb +143 -11
  41. data/spec/unit/fetchers/git_fetcher_spec.rb +23 -59
  42. data/spec/unit/fetchers/net_fetcher_spec.rb +151 -63
  43. data/spec/unit/fetchers/path_fetcher_spec.rb +4 -35
  44. data/spec/unit/git_cache_spec.rb +13 -14
  45. data/spec/unit/health_check_spec.rb +90 -0
  46. data/spec/unit/library_spec.rb +1 -1
  47. data/spec/unit/packagers/bff_spec.rb +126 -3
  48. data/spec/unit/packagers/deb_spec.rb +8 -3
  49. data/spec/unit/packagers/pkg_spec.rb +19 -19
  50. data/spec/unit/packagers/solaris_spec.rb +13 -1
  51. data/spec/unit/software_spec.rb +242 -38
  52. metadata +7 -6
  53. data/lib/omnibus/generator_files/package_scripts/makeselfinst.erb +0 -0
@@ -30,14 +30,14 @@ module Omnibus
30
30
  # @return [Software]
31
31
  #
32
32
  def load(project, name, manifest)
33
- loaded_softwares[name] ||= begin
33
+ loaded_softwares["#{project.name}:#{name}"] ||= begin
34
34
  filepath = Omnibus.software_path(name)
35
35
 
36
36
  if filepath.nil?
37
37
  raise MissingSoftware.new(name)
38
38
  else
39
39
  log.internal(log_key) do
40
- "Loading software `#{name}' from `#{filepath}'."
40
+ "Loading software `#{name}' from `#{filepath}' using overrides from #{project.name}."
41
41
  end
42
42
  end
43
43
 
@@ -176,6 +176,28 @@ module Omnibus
176
176
  end
177
177
  expose :description
178
178
 
179
+
180
+ #
181
+ # Sets the maintainer of the software. Currently this is for
182
+ # human consumption only and the tool doesn't do anything with it.
183
+ #
184
+ # @example
185
+ # maintainer "Joe Bob <joeb@chef.io>"
186
+ #
187
+ # @param [String] val
188
+ # the maintainer of this sofware def
189
+ #
190
+ # @return [String]
191
+ #
192
+ def maintainer(val = NULL)
193
+ if null?(val)
194
+ @maintainer
195
+ else
196
+ @description = val
197
+ end
198
+ end
199
+ expose :maintainer
200
+
179
201
  #
180
202
  # Add a software dependency to this software.
181
203
  #
@@ -227,10 +249,23 @@ module Omnibus
227
249
  # the SHA256 checksum of the downloaded artifact
228
250
  # @option val [String] :sha512 (nil)
229
251
  # the SHA512 checksum of the downloaded artifact
252
+ #
253
+ # Only used in net_fetcher:
254
+ #
230
255
  # @option val [String] :cookie (nil)
231
256
  # a cookie to set
232
257
  # @option val [String] :warning (nil)
233
258
  # a warning message to print when downloading
259
+ # @option val [Symbol] :extract (nil)
260
+ # either :tar, :lax_tar :seven_zip
261
+ #
262
+ # Only used in path_fetcher:
263
+ #
264
+ # @option val [Hash] :options (nil)
265
+ # flags/options that are passed through to file_syncer in path_fetcher
266
+ #
267
+ # Only used in git_fetcher:
268
+ #
234
269
  # @option val [Boolean] :submodules (false)
235
270
  # clone git submodules
236
271
  #
@@ -245,8 +280,13 @@ module Omnibus
245
280
  "be a kind of `Hash', but was `#{val.class.inspect}'")
246
281
  end
247
282
 
248
- extra_keys = val.keys - [:git, :path, :url, :md5, :sha1, :sha256, :sha512,
249
- :cookie, :warning, :unsafe, :options, :submodules]
283
+ extra_keys = val.keys - [
284
+ :git, :path, :url, # fetcher types
285
+ :md5, :sha1, :sha256, :sha512, # hash type - common to all fetchers
286
+ :cookie, :warning, :unsafe, :extract, # used by net_fetcher
287
+ :options, # used by path_fetcher
288
+ :submodules # used by git_fetcher
289
+ ]
250
290
  unless extra_keys.empty?
251
291
  raise InvalidValue.new(:source,
252
292
  "only include valid keys. Invalid keys: #{extra_keys.inspect}")
@@ -303,18 +343,30 @@ module Omnibus
303
343
  # @return [String, Proc]
304
344
  #
305
345
  def version(val = NULL, &block)
346
+ final_version = apply_overrides(:version)
347
+
306
348
  if block_given?
307
349
  if val.equal?(NULL)
308
350
  raise InvalidValue.new(:version,
309
351
  'pass a block when given a version argument')
310
352
  else
311
- if val == apply_overrides(:version)
353
+ if val == final_version
312
354
  block.call
313
355
  end
314
356
  end
315
357
  end
316
358
 
317
- apply_overrides(:version)
359
+ return if final_version.nil?
360
+
361
+ begin
362
+ Chef::Sugar::Constraints::Version.new(final_version)
363
+ rescue ArgumentError
364
+ log.warn(log_key) do
365
+ "Version #{final_version} for software #{name} was not parseable. " \
366
+ 'Comparison methods such as #satisfies? will not be available for this version.'
367
+ end
368
+ final_version
369
+ end
318
370
  end
319
371
  expose :version
320
372
 
@@ -338,19 +390,30 @@ module Omnibus
338
390
  expose :whitelist_file
339
391
 
340
392
  #
341
- # The relative path inside the extracted tarball.
393
+ # The path relative to fetch_dir where relevant project files are
394
+ # stored. This applies to all sources.
395
+ #
396
+ # Any command executed in the build step are run after cwd-ing into
397
+ # this path. The default is to stay at the top level of fetch_dir
398
+ # where the source tar-ball/git repo/file/directory has been staged.
342
399
  #
343
400
  # @example
344
401
  # relative_path 'example-1.2.3'
345
402
  #
346
403
  # @param [String] val
347
- # the relative path inside the tarball
404
+ # the relative path inside the source directory. default: '.'
405
+ #
406
+ # Due to back-compat reasons, relative_path works completely
407
+ # differently for anything other than tar-balls/archives. In those
408
+ # situations, the source is checked out rooted at relative_path
409
+ # instead 'cause reasons.
410
+ # TODO: Fix this in omnibus 6.
348
411
  #
349
412
  # @return [String]
350
413
  #
351
414
  def relative_path(val = NULL)
352
415
  if null?(val)
353
- @relative_path || name
416
+ @relative_path || '.'
354
417
  else
355
418
  @relative_path = val
356
419
  end
@@ -358,12 +421,22 @@ module Omnibus
358
421
  expose :relative_path
359
422
 
360
423
  #
361
- # The path where the extracted software lives.
424
+ # The path where the extracted software lives. All build commands
425
+ # associated with this software definition are run for under this path.
426
+ #
427
+ # Why is it called project_dir when this is a software definition, I hear
428
+ # you cry. Because history and reasons. This really is a location
429
+ # underneath the global omnibus source directory that you have focused
430
+ # into using relative_path above.
431
+ #
432
+ # These are not the only files your project fetches. They are merely the
433
+ # files that your project cares about. A source tarball may contain more
434
+ # directories that are not under your project_dir.
362
435
  #
363
436
  # @return [String]
364
437
  #
365
438
  def project_dir
366
- File.expand_path("#{Config.source_dir}/#{relative_path}")
439
+ File.expand_path("#{fetch_dir}/#{relative_path}")
367
440
  end
368
441
  expose :project_dir
369
442
 
@@ -447,6 +520,8 @@ module Omnibus
447
520
  #
448
521
  # Supported options:
449
522
  # :aix => :use_gcc force using gcc/g++ compilers on aix
523
+ # :bfd_flags => true the default build targets for windows based on
524
+ # the current platform architecture are added ARFLAGS and RCFLAGS.
450
525
  #
451
526
  # @param [Hash] env
452
527
  # @param [Hash] opts
@@ -471,7 +546,7 @@ module Omnibus
471
546
  when "mac_os_x"
472
547
  {
473
548
  "LDFLAGS" => "-L#{install_dir}/embedded/lib",
474
- "CFLAGS" => "-I#{install_dir}/embedded/include",
549
+ "CFLAGS" => "-I#{install_dir}/embedded/include -O2",
475
550
  }
476
551
  when "solaris2"
477
552
  {
@@ -484,7 +559,7 @@ module Omnibus
484
559
  when "freebsd"
485
560
  freebsd_flags = {
486
561
  "LDFLAGS" => "-L#{install_dir}/embedded/lib",
487
- "CFLAGS" => "-I#{install_dir}/embedded/include",
562
+ "CFLAGS" => "-I#{install_dir}/embedded/include -O2",
488
563
  }
489
564
  # Clang became the default compiler in FreeBSD 10+
490
565
  if Ohai['os_version'].to_i >= 1000024
@@ -494,13 +569,33 @@ module Omnibus
494
569
  )
495
570
  end
496
571
  freebsd_flags
572
+ when "windows"
573
+ arch_flag = windows_arch_i386? ? "-m32" : "-m64"
574
+ opt_flag = windows_arch_i386? ? "-march=i686" : "-march=x86-64"
575
+ {
576
+ "LDFLAGS" => "-L#{install_dir}/embedded/lib #{arch_flag}",
577
+ # If we're happy with these flags, enable SSE for other platforms running x86 too.
578
+ "CFLAGS" => "-I#{install_dir}/embedded/include #{arch_flag} -O3 -mfpmath=sse -msse2 #{opt_flag}"
579
+ }
497
580
  else
498
581
  {
499
582
  "LDFLAGS" => "-Wl,-rpath,#{install_dir}/embedded/lib -L#{install_dir}/embedded/lib",
500
- "CFLAGS" => "-I#{install_dir}/embedded/include",
583
+ "CFLAGS" => "-I#{install_dir}/embedded/include -O2",
501
584
  }
502
585
  end
503
586
 
587
+ # There are some weird, misbehaving makefiles on windows that hate ARFLAGS because it
588
+ # replaces the "rcs" flags in some build steps. So we provide this flag behind an
589
+ # optional flag.
590
+ if opts[:bfd_flags] && windows?
591
+ bfd_target = windows_arch_i386? ? "pe-i386" : "pe-x86-64"
592
+ compiler_flags.merge!(
593
+ {
594
+ "RCFLAGS" => "--target=#{bfd_target}",
595
+ "ARFLAGS" => "--target=#{bfd_target}",
596
+ }
597
+ )
598
+ end
504
599
  # merge LD_RUN_PATH into the environment. most unix distros will fall
505
600
  # back to this if there is no LDFLAGS passed to the linker that sets
506
601
  # the rpath. the LDFLAGS -R or -Wl,-rpath will override this, but in
@@ -550,11 +645,15 @@ module Omnibus
550
645
  # for the platform is used to join the paths.
551
646
  #
552
647
  # @param [Hash] env
648
+ # @param [Hash] opts
649
+ # :msys => true add the embedded msys path if building on windows.
553
650
  #
554
651
  # @return [Hash]
555
652
  #
556
- def with_embedded_path(env = {})
557
- path_value = prepend_path("#{install_dir}/bin", "#{install_dir}/embedded/bin")
653
+ def with_embedded_path(env = {}, opts = {})
654
+ paths = ["#{install_dir}/bin", "#{install_dir}/embedded/bin"]
655
+ paths << "#{install_dir}/embedded/msys/1.0/bin" if opts[:msys] && windows?
656
+ path_value = prepend_path(paths)
558
657
  env.merge(path_key => path_value)
559
658
  end
560
659
  expose :with_embedded_path
@@ -711,6 +810,24 @@ module Omnibus
711
810
  # @!endgroup
712
811
  # --------------------------------------------------
713
812
 
813
+ #
814
+ # Path to where any source is extracted to.
815
+ #
816
+ # Files in a source directory are staged underneath here. Files from
817
+ # a url are fetched and extracted here. Look outside this directory
818
+ # at your own peril.
819
+ #
820
+ # @return [String] the full absolute path to the software root fetch
821
+ # directory.
822
+ #
823
+ def fetch_dir(val = NULL)
824
+ if null?(val)
825
+ @fetch_dir || File.expand_path("#{Config.source_dir}/#{name}")
826
+ else
827
+ @fetch_dir = val
828
+ end
829
+ end
830
+
714
831
  # @todo see comments on {Omnibus::Fetcher#without_caching_for}
715
832
  def version_guid
716
833
  fetcher.version_guid
@@ -736,16 +853,33 @@ module Omnibus
736
853
  #
737
854
  # The fetcher for this software
738
855
  #
856
+ # This is where we handle all the crazy back-compat on relative_path.
857
+ # All fetchers in omnibus 4 use relative_path incorrectly. net_fetcher was
858
+ # the only one to use to sensibly, and even then only if fetch_dir was
859
+ # Config.source_dir and the source was an archive. Therefore, to not break
860
+ # everyone ever, we will still pass project_dir for all other fetchers.
861
+ # There is still one issue where other omnibus software (such as the
862
+ # appbundler dsl) currently assume that fetch_dir the same as source_dir.
863
+ # Therefore, we make one extra concession - when relative_path is set in a
864
+ # software definition to be the same as name (a very common scenario), we
865
+ # land the source into the fetch directory instead of project_dir. This
866
+ # is to avoid fiddling with the appbundler dsl until it gets sorted out.
867
+ #
739
868
  # @return [Fetcher]
740
869
  #
741
870
  def fetcher
742
- @fetcher ||= Fetcher.fetcher_class_for_source(self.source).new(manifest_entry, project_dir, build_dir)
871
+ @fetcher ||=
872
+ if source_type == :url && File.basename(source[:url], '?*').end_with?(*NetFetcher::ALL_EXTENSIONS)
873
+ Fetcher.fetcher_class_for_source(self.source).new(manifest_entry, fetch_dir, build_dir)
874
+ else
875
+ Fetcher.fetcher_class_for_source(self.source).new(manifest_entry, project_dir, build_dir)
876
+ end
743
877
  end
744
878
 
745
879
  #
746
880
  # The type of source specified for this software defintion.
747
881
  #
748
- # @return [String]
882
+ # @return [Symbol]
749
883
  #
750
884
  def source_type
751
885
  if source
@@ -16,11 +16,7 @@
16
16
 
17
17
  require 'chef/sugar/architecture'
18
18
  require 'chef/sugar/cloud'
19
- # NOTE: We cannot include the constraints library because of the conflicting
20
- # +version+ attribute would screw things up. You can still use the
21
- # +Chef::Sugar::Constraint.version('1.2.3') for comparing versions.
22
- #
23
- # require 'chef/sugar/constraints'
19
+ require 'chef/sugar/constraints'
24
20
  require 'chef/sugar/ip'
25
21
  require 'chef/sugar/platform'
26
22
  require 'chef/sugar/platform_family'
@@ -46,7 +46,7 @@ module Omnibus
46
46
  # @param options [Hash] the options passed to the initializer of the
47
47
  # +Mixlib::ShellOut+ instance.
48
48
  # @return [Mixlib::ShellOut] the underlying +Mixlib::ShellOut+ instance
49
- # which which has +stdout+, +stderr+, +status+, and +exitstatus+
49
+ # which has +stdout+, +stderr+, +status+, and +exitstatus+
50
50
  # populated with results of the command.
51
51
  #
52
52
  def shellout(*args)
@@ -15,5 +15,5 @@
15
15
  #
16
16
 
17
17
  module Omnibus
18
- VERSION = '5.0.0'
18
+ VERSION = '5.1.0'
19
19
  end
@@ -21,7 +21,10 @@ Gem::Specification.new do |gem|
21
21
  gem.test_files = gem.files.grep(/^(test|spec|features)\//)
22
22
  gem.require_paths = ['lib']
23
23
 
24
- gem.add_dependency 'chef-sugar', '~> 3.0'
24
+ # https://github.com/ksubrama/pedump, branch 'patch-1'
25
+ # is declared in the Gemfile because of its outdated
26
+ # dependency on multipart-post (~> 1.1.4)
27
+ gem.add_dependency 'chef-sugar', '~> 3.3'
25
28
  gem.add_dependency 'cleanroom', '~> 1.0'
26
29
  gem.add_dependency 'mixlib-shellout', '~> 2.0'
27
30
  gem.add_dependency 'mixlib-versioning'
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ #
3
+ # Perform necessary <%= name %> post install steps
4
+ # after package is installed.
5
+ #
6
+
7
+ echo "<%= name %> has been configured!"
@@ -1,3 +1,3 @@
1
1
  <% md5sums.each do |path, checksum| -%>
2
- <%= checksum %> <%= path %>
2
+ <%= checksum %> <%= path %>
3
3
  <% end -%>
@@ -19,7 +19,7 @@ module Omnibus
19
19
  # corresponding to the system installation and hope it all works out.
20
20
  def fake_embedded_bin(name)
21
21
  if windows?
22
- ext = (name == 'ruby') ? '.exe' : '.bat'
22
+ ext = name == 'ruby' ? '.exe' : '.bat'
23
23
  source = Bundler.which(name + ext)
24
24
  raise "Could not find #{name} in bundler environment" unless source
25
25
  File.open(File.join(embedded_bin_dir, name + '.bat'), 'w') do |f|
@@ -116,7 +116,7 @@ module Omnibus
116
116
  end
117
117
  end
118
118
 
119
- describe '#patch', :not_supported_on_windows do
119
+ describe '#patch' do
120
120
  it 'applies the patch' do
121
121
  configure = File.join(project_dir, 'configure')
122
122
  File.open(configure, 'w') do |f|
@@ -138,6 +138,13 @@ module Omnibus
138
138
  EOH
139
139
  end
140
140
 
141
+ if windows?
142
+ bash_path = Bundler.which('bash.exe')
143
+ allow(subject).to receive(:embedded_msys_bin)
144
+ .with('bash.exe')
145
+ .and_return("#{bash_path}")
146
+ end
147
+
141
148
  subject.patch(source: 'apply.patch')
142
149
  subject.build
143
150
  end
@@ -195,6 +202,8 @@ module Omnibus
195
202
  end
196
203
 
197
204
  describe '#appbundle' do
205
+ let(:project) { double("Project") }
206
+ let(:project_softwares) { [ double("Software", name: project_name, project_dir: project_dir) ] }
198
207
  it 'executes the command as the embedded appbundler' do
199
208
  make_gemspec
200
209
  make_gemfile
@@ -206,6 +215,10 @@ module Omnibus
206
215
  subject.gem("build #{project_name}.gemspec", shellout_opts(subject))
207
216
  subject.gem("install #{project_name}-1.0.0.gem", shellout_opts(subject))
208
217
  subject.appbundle(project_name, shellout_opts(subject))
218
+
219
+ expect(subject).to receive(:project).and_return(project)
220
+ expect(project).to receive(:softwares).and_return(project_softwares)
221
+
209
222
  output = capture_logging { subject.build }
210
223
 
211
224
  appbundler_path = File.join(embedded_bin_dir, 'appbundler')
@@ -594,5 +607,79 @@ module Omnibus
594
607
  end
595
608
  end
596
609
  end
610
+
611
+ describe '#update_config_guess', :not_supported_on_windows, :focus => true do
612
+ let(:config_guess_dir) { "#{install_dir}/embedded/lib/config_guess" }
613
+
614
+ before do
615
+ FileUtils.mkdir_p(config_guess_dir)
616
+ end
617
+
618
+ context 'with no config.guess' do
619
+ before do
620
+ File.open("#{config_guess_dir}/config.sub", "w+") do |f|
621
+ f.write("This is config.sub")
622
+ end
623
+ end
624
+
625
+ it 'fails' do
626
+ subject.update_config_guess
627
+ expect{subject.build}.to raise_error(RuntimeError)
628
+ end
629
+ end
630
+
631
+ context 'with no config.sub' do
632
+ before do
633
+ File.open("#{config_guess_dir}/config.guess", "w+") do |f|
634
+ f.write("This is config.guess")
635
+ end
636
+ end
637
+
638
+ it 'fails' do
639
+ subject.update_config_guess
640
+ expect{subject.build}.to raise_error(RuntimeError)
641
+ end
642
+ end
643
+
644
+ context 'with config_guess dependency' do
645
+ before do
646
+ File.open("#{config_guess_dir}/config.guess", "w+") do |f|
647
+ f.write("This is config.guess")
648
+ end
649
+
650
+ File.open("#{config_guess_dir}/config.sub", "w+") do |f|
651
+ f.write("This is config.sub")
652
+ end
653
+ end
654
+
655
+ it 'update config_guess with defaults' do
656
+ subject.update_config_guess
657
+ subject.build
658
+ expect(File.read("#{project_dir}/config.guess")).to match /config.guess/
659
+ expect(File.read("#{project_dir}/config.sub")).to match /config.sub/
660
+ end
661
+
662
+ it 'honors :target option' do
663
+ subject.update_config_guess(target: "sub_dir")
664
+ subject.build
665
+ expect(File.read("#{project_dir}/sub_dir/config.guess")).to match /config.guess/
666
+ expect(File.read("#{project_dir}/sub_dir/config.sub")).to match /config.sub/
667
+ end
668
+
669
+ it 'honors :config_guess in :install option' do
670
+ subject.update_config_guess(install: [:config_guess])
671
+ subject.build
672
+ expect(File.read("#{project_dir}/config.guess")).to match /config.guess/
673
+ expect(File.exist?("#{project_dir}/config.sub")).to be false
674
+ end
675
+
676
+ it 'honors :config_sub in :install option' do
677
+ subject.update_config_guess(install: [:config_sub])
678
+ subject.build
679
+ expect(File.read("#{project_dir}/config.sub")).to match /config.sub/
680
+ expect(File.exist?("#{project_dir}/config.guess")).to be false
681
+ end
682
+ end
683
+ end
597
684
  end
598
685
  end