omnibus 5.0.0 → 5.1.0

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