omnibus-sonian 1.2.0.1

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