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
@@ -0,0 +1,131 @@
1
+ #
2
+ # Copyright 2012-2014 Chef Software, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'digest'
18
+
19
+ module Omnibus
20
+ module Digestable
21
+ #
22
+ # Calculate the digest of the file at the given path. Files are read in
23
+ # binary chunks to prevent Ruby from exploding.
24
+ #
25
+ # @param [String] path
26
+ # the path of the file to digest
27
+ # @param [Symbol] type
28
+ # the type of digest to use
29
+ #
30
+ # @return [String]
31
+ # the hexdigest of the file at the path
32
+ #
33
+ def digest(path, type = :md5)
34
+ digest = digest_from_type(type)
35
+
36
+ update_with_file_contents(digest, path)
37
+ digest.hexdigest
38
+ end
39
+
40
+ #
41
+ # Calculate the digest of a directory at the given path. Each file in the
42
+ # directory is read in binary chunks to prevent excess memory usage.
43
+ # Filesystem entries of all types are included in the digest, including
44
+ # directories, links, and sockets. The contents of non-file entries are
45
+ # represented as:
46
+ #
47
+ # $type $path
48
+ #
49
+ # while the contents of regular files are represented as:
50
+ #
51
+ # file $path
52
+ #
53
+ # and then appended by the binary contents of the file/
54
+ #
55
+ # @param [String] path
56
+ # the path of the directory to digest
57
+ # @param [Symbol] type
58
+ # the type of digest to use
59
+ #
60
+ # @return [String]
61
+ # the hexdigest of the directory
62
+ #
63
+ def digest_directory(path, type = :md5)
64
+ digest = digest_from_type(type)
65
+
66
+ Dir.glob("#{path}/**/*").each do |filename|
67
+ case ftype = File.ftype(filename)
68
+ when 'file'
69
+ update_with_string(digest, "#{ftype} #{filename}")
70
+ update_with_file_contents(digest, filename)
71
+ else
72
+ update_with_string(digest, "#{ftype} #{filename}")
73
+ end
74
+ end
75
+
76
+ digest.hexdigest
77
+ end
78
+
79
+ private
80
+
81
+ #
82
+ # Create a new instance of the {Digest} class that corresponds to the given
83
+ # type.
84
+ #
85
+ # @param [#to_s] type
86
+ # the type of digest to use
87
+ #
88
+ # @return [~Digest]
89
+ # an instance of the digest class
90
+ #
91
+ def digest_from_type(type)
92
+ id = type.to_s.upcase
93
+ instance = Digest.const_get(id).new
94
+ end
95
+
96
+ #
97
+ # Update the digest with the given contents of the file, reading in small
98
+ # chunks to reduce memory. This method will update the given +digest+
99
+ # parameter, but returns nothing.
100
+ #
101
+ # @param [Digest] digest
102
+ # the digest to update
103
+ # @param [String] filename
104
+ # the path to the file on disk to read
105
+ #
106
+ # @return [void]
107
+ #
108
+ def update_with_file_contents(digest, filename)
109
+ File.open(filename) do |io|
110
+ while (chunk = io.read(1024 * 8))
111
+ digest.update(chunk)
112
+ end
113
+ end
114
+ end
115
+
116
+ #
117
+ # Update the digest with the given string. This method will update the given
118
+ # +digest+ parameter, but returns nothing.
119
+ #
120
+ # @param [Digest] digest
121
+ # the digest to update
122
+ # @param [String] string
123
+ # the string to read
124
+ #
125
+ # @return [void]
126
+ #
127
+ def update_with_string(digest, string)
128
+ digest.update(string)
129
+ end
130
+ end
131
+ end
@@ -15,7 +15,10 @@
15
15
  #
16
16
 
17
17
  module Omnibus
18
- class AbstractMethod < RuntimeError
18
+ class Error < RuntimeError
19
+ end
20
+
21
+ class AbstractMethod < Error
19
22
  def initialize(signature)
20
23
  @signature = signature
21
24
  end
@@ -25,7 +28,7 @@ module Omnibus
25
28
  end
26
29
  end
27
30
 
28
- class ProjectNotFound < RuntimeError
31
+ class ProjectNotFound < Error
29
32
  def initialize(name)
30
33
  @name = name
31
34
  end
@@ -34,15 +37,15 @@ module Omnibus
34
37
  out = "I could not find an Omnibus project named '#{@name}'! "
35
38
  out << "Valid projects are:\n"
36
39
 
37
- Omnibus.project_names.sort.each do |project_name|
38
- out << " * #{project_name}\n"
40
+ Omnibus.projects.sort.each do |project|
41
+ out << " * #{project.name}\n"
39
42
  end
40
43
 
41
44
  out.strip
42
45
  end
43
46
  end
44
47
 
45
- class MissingAsset < RuntimeError
48
+ class MissingAsset < Error
46
49
  def initialize(path)
47
50
  @path = path
48
51
  end
@@ -52,37 +55,7 @@ module Omnibus
52
55
  end
53
56
  end
54
57
 
55
- class InvalidS3Configuration < RuntimeError
56
- def initialize(s3_bucket, s3_access_key, s3_secret_key)
57
- @s3_bucket, @s3_access_key, @s3_secret_key = s3_bucket, s3_access_key, s3_secret_key
58
- end
59
-
60
- def to_s
61
- <<-EOH
62
- One or more required S3 configuration values is missing.
63
-
64
- Your effective configuration was the following:
65
-
66
- s3_bucket #{@s3_bucket.inspect}
67
- s3_access_key #{@s3_access_key.inspect}
68
- s3_secret_key #{@s3_secret_key.inspect}
69
-
70
- If you truly do want S3 caching, you should add values similar to the following
71
- in your Omnibus config file:
72
-
73
- s3_bucket ENV['S3_BUCKET_NAME']
74
- s3_access_key ENV['S3_ACCESS_KEY']
75
- s3_secret_key ENV['S3_SECRET_KEY']
76
-
77
- Note that you are not required to use environment variables as illustrated (and
78
- the ones listed have no special significance in Omnibus), but it is encouraged
79
- to prevent spread of sensitive information and inadvertent check-in of same to
80
- version control systems.
81
- EOH
82
- end
83
- end
84
-
85
- class BadReplacesLine < RuntimeError
58
+ class BadReplacesLine < Error
86
59
  def to_s
87
60
  <<-EOH
88
61
  The `replaces` project DSL statement should never equal the `package_name` or
@@ -103,7 +76,7 @@ should never use the replaces line.
103
76
  end
104
77
  end
105
78
 
106
- class NoPackageFile < RuntimeError
79
+ class NoPackageFile < Error
107
80
  def initialize(package_path)
108
81
  @package_path = package_path
109
82
  end
@@ -117,7 +90,7 @@ should never use the replaces line.
117
90
  end
118
91
  end
119
92
 
120
- class NoPackageMetadataFile < RuntimeError
93
+ class NoPackageMetadataFile < Error
121
94
  def initialize(package_metadata_path)
122
95
  @package_metadata_path = package_metadata_path
123
96
  end
@@ -131,41 +104,9 @@ should never use the replaces line.
131
104
  end
132
105
  end
133
106
 
134
- class InvalidS3ReleaseConfiguration < RuntimeError
135
- def initialize(s3_bucket, s3_access_key, s3_secret_key)
136
- @s3_bucket, @s3_access_key, @s3_secret_key = s3_bucket, s3_access_key, s3_secret_key
137
- end
138
-
139
- def to_s
140
- """
141
- One or more required S3 configuration values is missing.
142
-
143
- Your effective configuration was the following:
144
-
145
- release_s3_bucket => #{@s3_bucket.inspect}
146
- release_s3_access_key => #{@s3_access_key.inspect}
147
- release_s3_secret_key => #{@s3_secret_key.inspect}
148
-
149
- To release a package to S3, add the following values to your
150
- config file:
151
-
152
- release_s3_bucket ENV['S3_BUCKET_NAME']
153
- release_s3_access_key ENV['S3_ACCESS_KEY']
154
- release_s3_secret_key ENV['S3_SECRET_KEY']
155
-
156
- Note that you are not required to use environment variables as
157
- illustrated (and the ones listed have no special significance in
158
- Omnibus), but it is encouraged to prevent spread of sensitive
159
- information and inadvertent check-in of same to version control
160
- systems.
161
-
162
- """
163
- end
164
- end
165
-
166
107
  # Raise this error if a needed Project configuration value has not
167
108
  # been set.
168
- class MissingProjectConfiguration < RuntimeError
109
+ class MissingProjectConfiguration < Error
169
110
  def initialize(parameter_name, sample_value)
170
111
  @parameter_name, @sample_value = parameter_name, sample_value
171
112
  end
@@ -185,7 +126,7 @@ should never use the replaces line.
185
126
 
186
127
  # Raise this error if a needed Software configuration value has not
187
128
  # been set.
188
- class MissingSoftwareConfiguration < RuntimeError
129
+ class MissingSoftwareConfiguration < Error
189
130
  def initialize(software_name, parameter_name, sample_value)
190
131
  @software_name, @parameter_name, @sample_value = software_name, parameter_name, sample_value
191
132
  end
@@ -203,7 +144,7 @@ should never use the replaces line.
203
144
  end
204
145
  end
205
146
 
206
- class MissingPatch < RuntimeError
147
+ class MissingPatch < Error
207
148
  def initialize(patch_name, search_paths)
208
149
  @patch_name, @search_paths = patch_name, search_paths
209
150
  end
@@ -218,7 +159,7 @@ should never use the replaces line.
218
159
  end
219
160
  end
220
161
 
221
- class MissingTemplate < RuntimeError
162
+ class MissingTemplate < Error
222
163
  def initialize(template_name, search_paths)
223
164
  @template_name, @search_paths = template_name, search_paths
224
165
  end
@@ -233,21 +174,160 @@ should never use the replaces line.
233
174
  end
234
175
  end
235
176
 
236
- class MissingProjectDependency < RuntimeError
237
- def initialize(dep_name, search_paths)
238
- @dep_name, @search_paths = dep_name, search_paths
177
+ class MissingProjectDependency < Error
178
+ def initialize(name, directories)
179
+ @name, @directories = name, directories
239
180
  end
240
181
 
241
182
  def to_s
242
- """
243
- Attempting to load the project dependency '#{@dep_name}', but it was
244
- not found at any of the following locations:
183
+ <<-EOH
184
+ I could not find a software named `#{@name}' in any of the sources:
245
185
 
246
- #{@search_paths.join("\n ")}
247
- """
186
+ #{@directories.join("\n ")}
187
+ EOH
188
+ end
189
+ end
190
+
191
+ class UnresolvableGitReference < Error
192
+ end
193
+
194
+ class UnknownPublisher < Error
195
+ def initialize(backend)
196
+ @backend = backend
197
+ @backends = Omnibus.constants
198
+ .map(&:to_s)
199
+ .select { |const| const.to_s =~ /^(.+)Publisher$/ }
200
+ .sort
201
+ end
202
+
203
+ def to_s
204
+ <<-EOH
205
+ I could not find a publisher named #{@backend}. Valid publishers are:
206
+
207
+ #{@backends.join("\n ")}
208
+
209
+ Please make sure you have spelled everything correctly and try again. If this
210
+ error persists, please open an issue on GitHub.
211
+ EOH
248
212
  end
249
213
  end
250
214
 
251
- class UnresolvableGitReference < RuntimeError
215
+ class GemNotInstalled < Error
216
+ def initialize(name)
217
+ @name = name
218
+ end
219
+
220
+ def to_s
221
+ <<-EOH
222
+ I could not load the '#{@name}' gem. Please make sure the gem is installed on
223
+ your local system by running `gem install #{@name}`, or by adding the following
224
+ to your Gemfile:
225
+
226
+ gem '#{@name}'
227
+
228
+ EOH
229
+ end
230
+ end
231
+
232
+ class MissingConfigOption < Error
233
+ def initialize(key, example_value = "'...'")
234
+ @key, @example_value = key, example_value
235
+ end
236
+
237
+ def to_s
238
+ <<-EOH
239
+ The Omnibus configuration is missing the required configuration option
240
+ '#{@key}'. Please define it in your Omnibus config:
241
+
242
+ #{@key} #{@example_value}
243
+ EOH
244
+ end
245
+ end
246
+
247
+ class OldMetadata < Error
248
+ def initialize(path)
249
+ @path = path
250
+ end
251
+
252
+ def to_s
253
+ <<-EOH
254
+ The metadata at '#{@path}'
255
+ was generated by an older version of Omnibus. Please regenerate the package with
256
+ this version of Omnibus and retry.
257
+ EOH
258
+ end
259
+ end
260
+
261
+ class InsufficientSpecification < Error
262
+ def initialize(key, package)
263
+ @key, @package = key, package
264
+ end
265
+
266
+ def to_s
267
+ <<-EOH
268
+ Software must specify a #{@key} to cache it in S3 (#{@package})!
269
+ EOH
270
+ end
271
+ end
272
+
273
+ class InvalidValue < Error
274
+ #
275
+ # @param [Symbol] source
276
+ # the source method that received an invalid value
277
+ # @Param [String] message
278
+ # the message about why the value is invalid
279
+ #
280
+ def initialize(source, message)
281
+ @source = source
282
+ @message = message
283
+ end
284
+
285
+ def to_s
286
+ <<-EOH
287
+ Invalid value for #{@source}. Expected #{@source} to #{@message}!
288
+ EOH
289
+ end
290
+ end
291
+
292
+ #
293
+ # Raised when Omnibus encounters a platform_family it does not know how to
294
+ # build/check/handle.
295
+ #
296
+ class UnknownPlatformFamily < Error
297
+ def initialize(family)
298
+ @family = family
299
+ end
300
+
301
+ def to_s
302
+ <<-EOH
303
+ Unknown platform family `#{@family}'!
304
+ I do not know how to proceed!"
305
+ EOH
306
+ end
307
+ end
308
+
309
+ #
310
+ # Raised when Omnibus encounters a platform_version it does not know how to
311
+ # build/check/handle.
312
+ #
313
+ class UnknownPlatformVersion < Error
314
+ def initialize(platform, version)
315
+ @platform, @version = platform, version
316
+ end
317
+
318
+ def to_s
319
+ <<-EOH
320
+ Unknown platform version `#{@version}' for #{@platform}!
321
+ I do not know how to proceed!"
322
+ EOH
323
+ end
324
+ end
325
+
326
+ class HealthCheckFailed < Error
327
+ def to_s
328
+ <<-EOH
329
+ The health check failed! Please see above for important information.
330
+ EOH
331
+ end
252
332
  end
253
333
  end