omnibus-sonian 1.2.0.1

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 (70) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +5 -0
  5. data/.yardopts +6 -0
  6. data/CHANGELOG.md +96 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE +201 -0
  9. data/NOTICE +9 -0
  10. data/README.md +195 -0
  11. data/Rakefile +7 -0
  12. data/bin/makeself-header.sh +401 -0
  13. data/bin/makeself.sh +407 -0
  14. data/bin/omnibus +11 -0
  15. data/lib/omnibus.rb +304 -0
  16. data/lib/omnibus/artifact.rb +151 -0
  17. data/lib/omnibus/build_version.rb +285 -0
  18. data/lib/omnibus/builder.rb +328 -0
  19. data/lib/omnibus/clean_tasks.rb +30 -0
  20. data/lib/omnibus/cli.rb +35 -0
  21. data/lib/omnibus/cli/application.rb +140 -0
  22. data/lib/omnibus/cli/base.rb +118 -0
  23. data/lib/omnibus/cli/build.rb +62 -0
  24. data/lib/omnibus/cli/cache.rb +60 -0
  25. data/lib/omnibus/cli/release.rb +49 -0
  26. data/lib/omnibus/config.rb +224 -0
  27. data/lib/omnibus/exceptions.rb +143 -0
  28. data/lib/omnibus/fetcher.rb +184 -0
  29. data/lib/omnibus/fetchers.rb +22 -0
  30. data/lib/omnibus/fetchers/git_fetcher.rb +212 -0
  31. data/lib/omnibus/fetchers/net_fetcher.rb +193 -0
  32. data/lib/omnibus/fetchers/path_fetcher.rb +65 -0
  33. data/lib/omnibus/fetchers/s3_cache_fetcher.rb +42 -0
  34. data/lib/omnibus/health_check.rb +356 -0
  35. data/lib/omnibus/library.rb +62 -0
  36. data/lib/omnibus/overrides.rb +69 -0
  37. data/lib/omnibus/package_release.rb +163 -0
  38. data/lib/omnibus/project.rb +715 -0
  39. data/lib/omnibus/reports.rb +99 -0
  40. data/lib/omnibus/s3_cacher.rb +138 -0
  41. data/lib/omnibus/software.rb +441 -0
  42. data/lib/omnibus/templates/Berksfile.erb +3 -0
  43. data/lib/omnibus/templates/Gemfile.erb +4 -0
  44. data/lib/omnibus/templates/README.md.erb +102 -0
  45. data/lib/omnibus/templates/Vagrantfile.erb +95 -0
  46. data/lib/omnibus/templates/gitignore.erb +8 -0
  47. data/lib/omnibus/templates/omnibus.rb.example.erb +5 -0
  48. data/lib/omnibus/templates/package_scripts/makeselfinst.erb +27 -0
  49. data/lib/omnibus/templates/package_scripts/postinst.erb +17 -0
  50. data/lib/omnibus/templates/package_scripts/postrm.erb +9 -0
  51. data/lib/omnibus/templates/project.rb.erb +21 -0
  52. data/lib/omnibus/templates/software/c-example.rb.erb +42 -0
  53. data/lib/omnibus/templates/software/erlang-example.rb.erb +38 -0
  54. data/lib/omnibus/templates/software/ruby-example.rb.erb +24 -0
  55. data/lib/omnibus/util.rb +61 -0
  56. data/lib/omnibus/version.rb +20 -0
  57. data/omnibus.gemspec +34 -0
  58. data/spec/artifact_spec.rb +106 -0
  59. data/spec/build_version_spec.rb +266 -0
  60. data/spec/data/overrides/bad_line.overrides +3 -0
  61. data/spec/data/overrides/good.overrides +5 -0
  62. data/spec/data/overrides/with_dupes.overrides +4 -0
  63. data/spec/data/software/erchef.rb +40 -0
  64. data/spec/fetchers/net_fetcher_spec.rb +16 -0
  65. data/spec/overrides_spec.rb +114 -0
  66. data/spec/package_release_spec.rb +197 -0
  67. data/spec/s3_cacher_spec.rb +47 -0
  68. data/spec/software_spec.rb +85 -0
  69. data/spec/spec_helper.rb +28 -0
  70. metadata +252 -0
data/bin/omnibus ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Trap interrupts to quit cleanly. See
4
+ # https://twitter.com/mitchellh/status/283014103189053442
5
+ Signal.trap("INT") { exit 1 }
6
+
7
+ $:.unshift File.expand_path("../../lib", __FILE__)
8
+
9
+ require 'omnibus/cli'
10
+
11
+ Omnibus::CLI::Application.start
data/lib/omnibus.rb ADDED
@@ -0,0 +1,304 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2012 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'ohai'
19
+ o = Ohai::System.new
20
+ o.require_plugin('os')
21
+ o.require_plugin('platform')
22
+ o.require_plugin('linux/cpu') if o.os == 'linux'
23
+ o.require_plugin('kernel')
24
+ OHAI = o
25
+
26
+ require 'omnibus/library'
27
+ require 'omnibus/reports'
28
+ require 'omnibus/config'
29
+ require 'omnibus/exceptions'
30
+ require 'omnibus/software'
31
+ require 'omnibus/project'
32
+ require 'omnibus/fetchers'
33
+ require 'omnibus/health_check'
34
+ require 'omnibus/build_version'
35
+ require 'omnibus/overrides'
36
+ require 'omnibus/version'
37
+
38
+ require 'pathname'
39
+
40
+ module Omnibus
41
+
42
+ DEFAULT_CONFIG_FILENAME = 'omnibus.rb'.freeze
43
+
44
+ # Configure Omnibus.
45
+ #
46
+ # After this has been called, the {Omnibus::Config} object is
47
+ # available as `Omnibus.config`.
48
+ #
49
+ # @return [void]
50
+ #
51
+ # @deprecated Use {#load_configuration} if you need to process a
52
+ # config file, followed by {#process_configuration} to act upon it.
53
+ def self.configure
54
+ load_configuration
55
+ process_configuration
56
+ end
57
+
58
+ # Convenience method for access to the Omnibus::Config object.
59
+ # Provided for backward compatibility.
60
+ #
61
+ # @ return [Omnibus::Config]
62
+ #
63
+ # @deprecated Just refer to {Omnibus::Config} directly.
64
+ def self.config
65
+ Config
66
+ end
67
+
68
+ # Load in an Omnibus configuration file. Values will be merged with
69
+ # and override the defaults defined in {Omnibus::Config}.
70
+ #
71
+ # @param file [String] path to a configuration file to load
72
+ #
73
+ # @return [void]
74
+ def self.load_configuration(file=nil)
75
+ if file
76
+ Config.from_file(file)
77
+ end
78
+ end
79
+
80
+ # Processes the configuration to construct the dependency tree of
81
+ # projects and software.
82
+ #
83
+ # @return [void]
84
+ def self.process_configuration
85
+ Config.validate
86
+ process_dsl_files
87
+ generate_extra_rake_tasks
88
+ end
89
+
90
+ # All {Omnibus::Project} instances that have been created.
91
+ #
92
+ # @return [Array<Omnibus::Project>]
93
+ def self.projects
94
+ @projects ||= []
95
+ end
96
+
97
+ # Names of all the {Omnibus::Project} instances that have been created.
98
+ #
99
+ # @return [Array<String>]
100
+ def self.project_names
101
+ projects.map{|p| p.name}
102
+ end
103
+
104
+ # Load the {Omnibus::Project} instance with the given name.
105
+ #
106
+ # @param name [String]
107
+ # @return {Omnibus::Project}
108
+ def self.project(name)
109
+ projects.find{ |p| p.name == name}
110
+ end
111
+
112
+ # The absolute path to the Omnibus project/repository directory.
113
+ #
114
+ # @return [String]
115
+ #
116
+ # @deprecated Call {Omnibus::Config.project_root} instead. We need
117
+ # to be able to easily tweak this at runtime via the CLI tool.
118
+ def self.project_root
119
+ Config.project_root
120
+ end
121
+
122
+ # The source root is the path to the root directory of the `omnibus` gem.
123
+ #
124
+ # @return [Pathname]
125
+ def self.source_root
126
+ @source_root ||= Pathname.new(File.expand_path("../..", __FILE__))
127
+ end
128
+
129
+ # The source root is the path to the root directory of the `omnibus-software`
130
+ # gem.
131
+ #
132
+ # @return [Pathname]
133
+ def self.omnibus_software_root
134
+ @omnibus_software_root ||= begin
135
+ if spec = Gem::Specification.find_all_by_name('omnibus-software').first
136
+ Pathname.new(spec.gem_dir)
137
+ else
138
+ nil
139
+ end
140
+ end
141
+ end
142
+
143
+ # Return paths to all configured {Omnibus::Project} DSL files.
144
+ #
145
+ # @return [Array<String>]
146
+ def self.project_files
147
+ ruby_files(File.join(project_root, Config.project_dir))
148
+ end
149
+
150
+ # Return paths to all configured {Omnibus::Software} DSL files.
151
+ #
152
+ # @return [Array<String>]
153
+ def self.software_files
154
+ ruby_files(File.join(project_root, Config.software_dir))
155
+ end
156
+
157
+ # Backward compat alias
158
+ #
159
+ # @todo print a deprecation message
160
+ class << self
161
+ alias :root :project_root
162
+ end
163
+
164
+ private
165
+
166
+ # Generates {Omnibus::Project}s for each project DSL file in
167
+ # `project_specs`. All projects are then accessible at
168
+ # {Omnibus#projects}
169
+ #
170
+ # @return [void]
171
+ #
172
+ # @see Omnibus::Project
173
+ def self.expand_projects
174
+ project_files.each do |spec|
175
+ Omnibus.projects << Omnibus::Project.load(spec)
176
+ end
177
+ end
178
+
179
+ # Generate {Omnibus::Software} objects for all software DSL files in
180
+ # `software_specs`.
181
+ #
182
+ # @param overrides [Hash] a hash of version override information.
183
+ # @param software_files [Array<String>]
184
+ # @return [void]
185
+ #
186
+ # @see Omnibus::Overrides#overrides
187
+ def self.expand_software(overrides, software_map)
188
+ unless overrides.is_a? Hash
189
+ raise ArgumentError, "Overrides argument must be a hash! You passed #{overrides.inspect}."
190
+ end
191
+
192
+ Omnibus.projects.each do |project|
193
+ project.dependencies.each do |dependency|
194
+ recursively_load_dependency(dependency, project, overrides, software_map)
195
+ end
196
+ end
197
+ end
198
+
199
+ # Processes all configured {Omnibus::Project} and
200
+ # {Omnibus::Software} DSL files.
201
+ #
202
+ # @return [void]
203
+ def self.process_dsl_files
204
+ # Do projects first
205
+ expand_projects
206
+
207
+ # Then do software
208
+ final_software_map = prefer_local_software(omnibus_software_files,
209
+ software_files)
210
+
211
+ overrides = Config.override_file ? Omnibus::Overrides.overrides : {}
212
+
213
+ expand_software(overrides, final_software_map)
214
+ end
215
+
216
+ # Creates some additional Rake tasks beyond those generated in the
217
+ # process of reading in the DSL files.
218
+ #
219
+ # @return [void]
220
+ #
221
+ # @todo Not so sure I like how this is being done, but at least it
222
+ # isolates the Rake stuff.
223
+ def self.generate_extra_rake_tasks
224
+ require 'omnibus/clean_tasks'
225
+ end
226
+
227
+ # Return a list of all the Ruby files (i.e., those with an "rb"
228
+ # extension) in the given directory
229
+ #
230
+ # @param dir [String]
231
+ # @return [Array<String>]
232
+ def self.ruby_files(dir)
233
+ Dir.glob("#{dir}/*.rb")
234
+ end
235
+
236
+ # Retrieve the fully-qualified paths to every software definition
237
+ # file bundled in the {https://github.com/opscode/omnibus-software omnibus-software} gem.
238
+ #
239
+ # @return [Array<String>] the list of paths. Will be empty if the
240
+ # `omnibus-software` gem is not in the gem path.
241
+ def self.omnibus_software_files
242
+ if omnibus_software_root
243
+ Dir.glob(File.join(omnibus_software_root, 'config', 'software', '*.rb'))
244
+ else
245
+ []
246
+ end
247
+ end
248
+
249
+ # Given a list of software definitions from `omnibus-software` itself, and a
250
+ # list of software files local to the current project, create a
251
+ # single list of software definitions. If the software was defined
252
+ # in both sets, the locally-defined one ends up in the final list.
253
+ #
254
+ # The base name of the software file determines what software it
255
+ # defines.
256
+ #
257
+ # @param omnibus_files [Array<String>]
258
+ # @param local_files [Array<String>]
259
+ # @return [Array<String>]
260
+ def self.prefer_local_software(omnibus_files, local_files)
261
+ base = software_map(omnibus_files)
262
+ local = software_map(local_files)
263
+ base.merge(local)
264
+ end
265
+
266
+ # Given a list of file paths, create a map of the basename (without
267
+ # extension) to the complete path.
268
+ #
269
+ # @param files [Array<String>]
270
+ # @return [Hash<String, String>]
271
+ def self.software_map(files)
272
+ files.each_with_object({}) do |file, collection|
273
+ software_name = File.basename(file, ".*")
274
+ collection[software_name] = file
275
+ end
276
+ end
277
+
278
+ # Loads a project's dependency recursively, ensuring all transitive dependencies
279
+ # are also loaded.
280
+ #
281
+ # @param dependency_name [String]
282
+ # @param project [Omnibus::Project]
283
+ # @param overrides [Hash] a hash of version override information.
284
+ # @param software_map [Hash<String, String>]
285
+ #
286
+ # @return [void]
287
+ def self.recursively_load_dependency(dependency_name, project, overrides, software_map)
288
+ dep_file = software_map[dependency_name]
289
+
290
+ unless dep_file
291
+ raise MissingProjectDependency.new(dependency_name,
292
+ [File.join(project_root, Config.software_dir),
293
+ File.join(omnibus_software_root, 'config', 'software')])
294
+ end
295
+
296
+ dep_software = Omnibus::Software.load(dep_file, project, overrides)
297
+ project.library.component_added(dep_software)
298
+
299
+ # load any transitive deps for the component into the library also
300
+ dep_software.dependencies.each do |dep|
301
+ recursively_load_dependency(dep, project, overrides, software_map)
302
+ end
303
+ end
304
+ end
@@ -0,0 +1,151 @@
1
+ module Omnibus
2
+ class Artifact
3
+
4
+ attr_reader :path
5
+ attr_reader :platforms
6
+ attr_reader :config
7
+
8
+ # @param path [String] relative or absolute path to a package file.
9
+ # @param platforms [Array<Array<String, String, String>>] an Array of
10
+ # distro, distro version, architecture tuples. By convention, the first
11
+ # platform is the platform on which the artifact was built.
12
+ # @param config [#Hash<Symbol, Object>] configuration for the release.
13
+ # Artifact only uses `:build_version => String`.
14
+ def initialize(path, platforms, config)
15
+ @path = path
16
+ @platforms = platforms
17
+ @config = config
18
+ end
19
+
20
+ # Adds this artifact to the `release_manifest`, which is mutated. Intended
21
+ # to be used in a visitor-pattern fashion over a collection of Artifacts to
22
+ # generate a final release manifest.
23
+ #
24
+ # @param release_manifest [Hash{ String => Hash }] a version 1 style release
25
+ # manifest Hash (see example)
26
+ #
27
+ # @example Add the package to release_manifest:
28
+ # add_to_release_manifest!( {} )
29
+ # "el" => {
30
+ # "5" => { "x86_64" => { "11.4.0-1" => "/el/5/x86_64/demoproject-11.4.0-1.el5.x86_64.rpm" } }
31
+ # }
32
+ # @return [Hash{String=>Hash}] the updated release manifest.
33
+ def add_to_release_manifest!(release_manifest)
34
+ platforms.each do |distro, version, arch|
35
+ release_manifest[distro] ||= {}
36
+ release_manifest[distro][version] ||= {}
37
+ release_manifest[distro][version][arch] = { build_version => relpath }
38
+ # TODO: when adding checksums, the desired format is like this:
39
+ # build_support_json[platform][platform_version][machine_architecture][options[:version]]["relpath"] = build_location
40
+ end
41
+ release_manifest
42
+ end
43
+
44
+ # Adds this artifact to the `release_manifest`, which is mutated. Intended
45
+ # to be used in a visitor-pattern fashion over a collection of Artifacts to
46
+ # generate a final release manifest.
47
+ #
48
+ # @param release_manifest [Hash{ String => Hash }] a version 2 style release
49
+ # manifest Hash (see example)
50
+ #
51
+ # @example Add the package to release_manifest:
52
+ # add_to_release_manifest!( {} )
53
+ # "el" => {
54
+ # "5" => {
55
+ # "x86_64" => {
56
+ # "11.4.0-1" => {
57
+ # "relpath" => "/el/5/x86_64/demoproject-11.4.0-1.el5.x86_64.rpm",
58
+ # "md5" => "123f00d...",
59
+ # "sha256" => 456beef..."
60
+ # }
61
+ # }
62
+ # }
63
+ # }
64
+ # @return [Hash{String=>Hash}] the updated release manifest.
65
+ def add_to_v2_release_manifest!(release_manifest)
66
+ platforms.each do |distro, version, arch|
67
+ pkg_info = {
68
+ "relpath" => relpath,
69
+ "md5" => md5,
70
+ "sha256" => sha256
71
+ }
72
+
73
+ release_manifest[distro] ||= {}
74
+ release_manifest[distro][version] ||= {}
75
+ release_manifest[distro][version][arch] = { build_version => pkg_info }
76
+ end
77
+ release_manifest
78
+ end
79
+
80
+ # Metadata about the artifact as a flat Hash.
81
+ #
82
+ # @example For a RHEL/CentOS 6, 64-bit package of project version 11.4.0-1
83
+ # flat_metadata
84
+ # { "platform" => "el",
85
+ # "platform_version" => "6",
86
+ # "arch" => "x86_64",
87
+ # "version" => "11.4.0-1",
88
+ # "md5" => "d41d8cd98f00b204e9800998ecf8427e",
89
+ # "sha256" => "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }
90
+ #
91
+ # @return [Hash{String=>String}] the artifact metadata
92
+ def flat_metadata
93
+ distro, version, arch = build_platform
94
+ {
95
+ "platform" => distro,
96
+ "platform_version" => version,
97
+ "arch" => arch,
98
+ "version" => build_version,
99
+ "basename" => File.basename(path),
100
+ "md5" => md5,
101
+ "sha256" => sha256
102
+ }
103
+ end
104
+
105
+ # Platform on which the artifact was built. By convention, this is the
106
+ # first in the list of platforms passed to {#initialize}.
107
+ # @return [Array<String, String, String>] an Array of distro, distro
108
+ # version, architecture.
109
+ def build_platform
110
+ platforms.first
111
+ end
112
+
113
+ # @return [String] build version of the project.
114
+ def build_version
115
+ config[:version]
116
+ end
117
+
118
+ # @return [String] relative path at which the artifact should be located
119
+ # when uploaded to artifact repo.
120
+ # @example Chef 11.4.0-1 on 64 bit RHEL 6:
121
+ # relpath
122
+ # "/el/6/x86_64/chef-11.4.0-1.el5.x86_64.rpm"
123
+ def relpath
124
+ # upload build to build platform directory
125
+ "/#{build_platform.join('/')}/#{path.split('/').last}"
126
+ end
127
+
128
+ # @return [String] hex encoded MD5 of the package
129
+ def md5
130
+ @md5 ||= digest(Digest::MD5)
131
+ end
132
+
133
+ # @return [String] hex encoded SHA2-256 of the package
134
+ def sha256
135
+ @sha256 ||= digest(Digest::SHA256)
136
+ end
137
+
138
+ private
139
+
140
+ def digest(digest_class)
141
+ digest = digest_class.new
142
+ File.open(path) do |io|
143
+ while chunk = io.read(1024 * 8)
144
+ digest.update(chunk)
145
+ end
146
+ end
147
+ digest.hexdigest
148
+ end
149
+ end
150
+ end
151
+