berkshelf 5.2.0 → 8.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +19 -47
- data/Rakefile +14 -4
- data/berkshelf.gemspec +61 -40
- data/bin/berks +2 -2
- data/lib/berkshelf/api-client.rb +1 -0
- data/lib/berkshelf/api_client/chef_server_connection.rb +29 -0
- data/lib/berkshelf/api_client/connection.rb +57 -0
- data/lib/berkshelf/api_client/errors.rb +10 -0
- data/lib/berkshelf/api_client/remote_cookbook.rb +56 -0
- data/lib/berkshelf/api_client/version.rb +5 -0
- data/lib/berkshelf/api_client.rb +24 -0
- data/lib/berkshelf/berksfile.rb +149 -122
- data/lib/berkshelf/cached_cookbook.rb +127 -24
- data/lib/berkshelf/chef_config_compat.rb +51 -0
- data/lib/berkshelf/chef_repo_universe.rb +47 -0
- data/lib/berkshelf/cli.rb +143 -174
- data/lib/berkshelf/commands/shelf.rb +20 -19
- data/lib/berkshelf/community_rest.rb +59 -94
- data/lib/berkshelf/config.rb +97 -127
- data/lib/berkshelf/cookbook_store.rb +7 -6
- data/lib/berkshelf/core_ext/file.rb +1 -1
- data/lib/berkshelf/core_ext/file_utils.rb +4 -4
- data/lib/berkshelf/core_ext.rb +1 -1
- data/lib/berkshelf/dependency.rb +25 -32
- data/lib/berkshelf/downloader.rb +66 -39
- data/lib/berkshelf/errors.rb +23 -17
- data/lib/berkshelf/file_syncer.rb +24 -47
- data/lib/berkshelf/formatters/human.rb +7 -5
- data/lib/berkshelf/formatters/json.rb +6 -6
- data/lib/berkshelf/installer.rb +120 -111
- data/lib/berkshelf/location.rb +14 -14
- data/lib/berkshelf/locations/base.rb +1 -1
- data/lib/berkshelf/locations/git.rb +16 -24
- data/lib/berkshelf/locations/github.rb +2 -2
- data/lib/berkshelf/locations/path.rb +2 -2
- data/lib/berkshelf/lockfile.rb +326 -328
- data/lib/berkshelf/logger.rb +64 -1
- data/lib/berkshelf/mixin/git.rb +6 -5
- data/lib/berkshelf/packager.rb +44 -10
- data/lib/berkshelf/resolver/graph.rb +1 -1
- data/lib/berkshelf/resolver.rb +4 -4
- data/lib/berkshelf/ridley_compat.rb +109 -0
- data/lib/berkshelf/shell.rb +2 -1
- data/lib/berkshelf/shell_out.rb +18 -0
- data/lib/berkshelf/source.rb +77 -33
- data/lib/berkshelf/source_uri.rb +4 -4
- data/lib/berkshelf/ssl_policies.rb +38 -0
- data/lib/berkshelf/thor.rb +1 -1
- data/lib/berkshelf/thor_ext/hash_with_indifferent_access.rb +1 -1
- data/lib/berkshelf/thor_ext.rb +1 -1
- data/lib/berkshelf/uploader.rb +106 -70
- data/lib/berkshelf/validator.rb +13 -5
- data/lib/berkshelf/version.rb +1 -1
- data/lib/berkshelf/visualizer.rb +16 -11
- data/lib/berkshelf.rb +106 -81
- data/spec/config/knife.rb +4 -4
- data/spec/data/trusted_certs/example.crt +22 -0
- data/spec/fixtures/Berksfile +3 -3
- data/spec/fixtures/complex-cookbook-path/cookbooks/app/metadata.rb +2 -0
- data/spec/fixtures/complex-cookbook-path/cookbooks/jenkins/metadata.rb +2 -0
- data/spec/fixtures/complex-cookbook-path/cookbooks/jenkins-config/metadata.rb +4 -0
- data/spec/fixtures/cookbook-path/jenkins-config/metadata.rb +3 -3
- data/spec/fixtures/cookbook-path-uploader/apt-2.3.6/metadata.rb +2 -0
- data/spec/fixtures/cookbook-path-uploader/build-essential-1.4.2/metadata.rb +2 -0
- data/spec/fixtures/cookbook-path-uploader/jenkins-2.0.3/metadata.rb +5 -0
- data/spec/fixtures/cookbook-path-uploader/jenkins-config-0.1.0/metadata.rb +4 -0
- data/spec/fixtures/cookbook-path-uploader/runit-1.5.8/metadata.rb +5 -0
- data/spec/fixtures/cookbook-path-uploader/yum-3.0.6/metadata.rb +2 -0
- data/spec/fixtures/cookbook-path-uploader/yum-epel-0.2.0/metadata.rb +3 -0
- data/spec/fixtures/cookbook-store/jenkins-2.0.3/metadata.rb +5 -5
- data/spec/fixtures/cookbook-store/jenkins-2.0.4/metadata.rb +4 -4
- data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +3 -3
- data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +3 -3
- data/spec/spec_helper.rb +56 -64
- data/spec/support/chef_api.rb +15 -16
- data/spec/support/chef_server.rb +71 -69
- data/spec/support/git.rb +59 -58
- data/spec/support/kitchen.rb +0 -14
- data/spec/support/matchers/file_system_matchers.rb +4 -5
- data/spec/support/matchers/filepath_matchers.rb +2 -2
- data/spec/support/path_helpers.rb +17 -17
- data/spec/support/shared_examples/formatter.rb +1 -1
- data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/attributes/default.rb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/files/default/file.h +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/metadata.rb +2 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/recipes/default.rb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/templates/default/template.erb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/attributes/default.rb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/files/default/file.h +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/metadata.rb +2 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/recipes/default.rb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/templates/default/template.erb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/attributes/default.rb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/files/default/file.h +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/metadata.rb +2 -0
- data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/recipes/default.rb +0 -0
- data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/templates/default/template.erb +0 -0
- data/spec/unit/berkshelf/berksfile_spec.rb +84 -105
- data/spec/unit/berkshelf/berkshelf/api_client/chef_server_connection_spec.rb +65 -0
- data/spec/unit/berkshelf/berkshelf/api_client/connection_spec.rb +157 -0
- data/spec/unit/berkshelf/berkshelf/api_client/remote_cookbook_spec.rb +23 -0
- data/spec/unit/berkshelf/berkshelf/api_client_spec.rb +9 -0
- data/spec/unit/berkshelf/cached_cookbook_spec.rb +45 -47
- data/spec/unit/berkshelf/chef_repo_universe_spec.rb +37 -0
- data/spec/unit/berkshelf/cli_spec.rb +7 -8
- data/spec/unit/berkshelf/community_rest_spec.rb +82 -90
- data/spec/unit/berkshelf/config_spec.rb +51 -22
- data/spec/unit/berkshelf/cookbook_store_spec.rb +41 -41
- data/spec/unit/berkshelf/core_ext/file_utils_spec.rb +7 -8
- data/spec/unit/berkshelf/core_ext/pathname_spec.rb +1 -1
- data/spec/unit/berkshelf/dependency_spec.rb +48 -48
- data/spec/unit/berkshelf/downloader_spec.rb +191 -34
- data/spec/unit/berkshelf/errors_spec.rb +3 -3
- data/spec/unit/berkshelf/file_syncer_spec.rb +87 -87
- data/spec/unit/berkshelf/formatters/base_spec.rb +23 -23
- data/spec/unit/berkshelf/formatters/human_spec.rb +2 -2
- data/spec/unit/berkshelf/formatters/json_spec.rb +2 -2
- data/spec/unit/berkshelf/formatters/null_spec.rb +3 -3
- data/spec/unit/berkshelf/installer_spec.rb +8 -8
- data/spec/unit/berkshelf/location_spec.rb +11 -11
- data/spec/unit/berkshelf/locations/base_spec.rb +35 -36
- data/spec/unit/berkshelf/locations/git_spec.rb +90 -93
- data/spec/unit/berkshelf/locations/path_spec.rb +40 -41
- data/spec/unit/berkshelf/lockfile_parser_spec.rb +71 -71
- data/spec/unit/berkshelf/lockfile_spec.rb +205 -211
- data/spec/unit/berkshelf/logger_spec.rb +3 -3
- data/spec/unit/berkshelf/mixin/logging_spec.rb +5 -5
- data/spec/unit/berkshelf/packager_spec.rb +2 -2
- data/spec/unit/berkshelf/resolver/graph_spec.rb +10 -8
- data/spec/unit/berkshelf/resolver_spec.rb +17 -17
- data/spec/unit/berkshelf/ridley_compat_spec.rb +16 -0
- data/spec/unit/berkshelf/shell_spec.rb +34 -34
- data/spec/unit/berkshelf/source_spec.rb +186 -20
- data/spec/unit/berkshelf/source_uri_spec.rb +1 -1
- data/spec/unit/berkshelf/ssl_policies_spec.rb +86 -0
- data/spec/unit/berkshelf/uploader_spec.rb +146 -64
- data/spec/unit/berkshelf/validator_spec.rb +23 -16
- data/spec/unit/berkshelf/visualizer_spec.rb +24 -15
- data/spec/unit/berkshelf_spec.rb +18 -18
- metadata +138 -289
- data/.gitignore +0 -29
- data/.travis.yml +0 -64
- data/CHANGELOG.legacy.md +0 -307
- data/CHANGELOG.md +0 -1358
- data/CONTRIBUTING.md +0 -64
- data/Gemfile.lock +0 -399
- data/Guardfile +0 -23
- data/PLUGINS.md +0 -25
- data/README.md +0 -70
- data/Thorfile +0 -61
- data/appveyor.yml +0 -31
- data/docs/berkshelf_for_newcomers.md +0 -65
- data/features/berksfile.feature +0 -46
- data/features/commands/apply.feature +0 -41
- data/features/commands/contingent.feature +0 -48
- data/features/commands/cookbook.feature +0 -35
- data/features/commands/info.feature +0 -99
- data/features/commands/init.feature +0 -27
- data/features/commands/install.feature +0 -636
- data/features/commands/list.feature +0 -78
- data/features/commands/outdated.feature +0 -130
- data/features/commands/package.feature +0 -17
- data/features/commands/search.feature +0 -17
- data/features/commands/shelf/list.feature +0 -32
- data/features/commands/shelf/show.feature +0 -143
- data/features/commands/shelf/uninstall.feature +0 -96
- data/features/commands/show.feature +0 -83
- data/features/commands/update.feature +0 -142
- data/features/commands/upload.feature +0 -426
- data/features/commands/vendor.feature +0 -111
- data/features/commands/verify.feature +0 -29
- data/features/commands/viz.feature +0 -66
- data/features/community_site.feature +0 -37
- data/features/config.feature +0 -111
- data/features/help.feature +0 -11
- data/features/json_formatter.feature +0 -161
- data/features/lifecycle.feature +0 -378
- data/features/lockfile.feature +0 -378
- data/features/step_definitions/berksfile_steps.rb +0 -39
- data/features/step_definitions/chef/config_steps.rb +0 -12
- data/features/step_definitions/chef_server_steps.rb +0 -60
- data/features/step_definitions/cli_steps.rb +0 -18
- data/features/step_definitions/config_steps.rb +0 -46
- data/features/step_definitions/environment_steps.rb +0 -7
- data/features/step_definitions/filesystem_steps.rb +0 -269
- data/features/step_definitions/gem_steps.rb +0 -13
- data/features/step_definitions/json_steps.rb +0 -23
- data/features/step_definitions/utility_steps.rb +0 -11
- data/features/support/aruba.rb +0 -12
- data/features/support/env.rb +0 -82
- data/generator_files/Berksfile.erb +0 -11
- data/generator_files/CHANGELOG.md.erb +0 -3
- data/generator_files/Gemfile.erb +0 -8
- data/generator_files/README.md.erb +0 -42
- data/generator_files/Thorfile.erb +0 -11
- data/generator_files/Vagrantfile.erb +0 -117
- data/generator_files/chefignore +0 -94
- data/generator_files/default_recipe.erb +0 -6
- data/generator_files/default_test.rb.erb +0 -11
- data/generator_files/gitignore.erb +0 -23
- data/generator_files/helpers.rb.erb +0 -7
- data/generator_files/licenses/apachev2.erb +0 -13
- data/generator_files/licenses/gplv2.erb +0 -15
- data/generator_files/licenses/gplv3.erb +0 -14
- data/generator_files/licenses/mit.erb +0 -20
- data/generator_files/licenses/reserved.erb +0 -3
- data/generator_files/metadata.rb.erb +0 -11
- data/lib/berkshelf/base_generator.rb +0 -43
- data/lib/berkshelf/commands/test_command.rb +0 -13
- data/lib/berkshelf/cookbook_generator.rb +0 -133
- data/lib/berkshelf/init_generator.rb +0 -195
- data/spec/fixtures/cookbooks/example_cookbook/.gitignore +0 -2
- data/spec/fixtures/cookbooks/example_cookbook/.kitchen.yml +0 -26
- data/spec/unit/berkshelf/cookbook_generator_spec.rb +0 -110
- data/spec/unit/berkshelf/init_generator_spec.rb +0 -263
data/lib/berkshelf/berksfile.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require_relative "packager"
|
2
2
|
|
3
|
+
require "chef/cookbook/chefignore"
|
4
|
+
require "chef/util/path_helper"
|
5
|
+
|
3
6
|
module Berkshelf
|
4
7
|
class Berksfile
|
5
8
|
class << self
|
@@ -9,7 +12,8 @@ module Berkshelf
|
|
9
12
|
# @param (see Berksfile#initialize)
|
10
13
|
def from_options(options = {})
|
11
14
|
options[:berksfile] ||= File.join(Dir.pwd, Berkshelf::DEFAULT_FILENAME)
|
12
|
-
|
15
|
+
symbolized = Hash[options.map { |k, v| [k.to_sym, v] }]
|
16
|
+
from_file(options[:berksfile], symbolized.select { |k,| %i{except only delete}.include? k })
|
13
17
|
end
|
14
18
|
|
15
19
|
# @param [#to_s] file
|
@@ -31,7 +35,7 @@ module Berkshelf
|
|
31
35
|
|
32
36
|
# Don't vendor VCS files.
|
33
37
|
# Reference GNU tar --exclude-vcs: https://www.gnu.org/software/tar/manual/html_section/tar_49.html
|
34
|
-
EXCLUDED_VCS_FILES_WHEN_VENDORING = [
|
38
|
+
EXCLUDED_VCS_FILES_WHEN_VENDORING = [".arch-ids", "{arch}", ".bzr", ".bzrignore", ".bzrtags", "CVS", ".cvsignore", "_darcs", ".git", ".hg", ".hgignore", ".hgrags", "RCS", "SCCS", ".svn", "**/.git", "**/.svn"].freeze
|
35
39
|
|
36
40
|
include Mixin::Logging
|
37
41
|
include Cleanroom
|
@@ -62,8 +66,8 @@ module Berkshelf
|
|
62
66
|
# group to be installed and all others to be ignored
|
63
67
|
def initialize(path, options = {})
|
64
68
|
@filepath = File.expand_path(path)
|
65
|
-
@dependencies =
|
66
|
-
@sources =
|
69
|
+
@dependencies = {}
|
70
|
+
@sources = {}
|
67
71
|
@delete = options[:delete]
|
68
72
|
|
69
73
|
# defaults for what solvers to use
|
@@ -71,7 +75,7 @@ module Berkshelf
|
|
71
75
|
@preferred_solver = :gecode
|
72
76
|
|
73
77
|
if options[:except] && options[:only]
|
74
|
-
raise ArgumentError,
|
78
|
+
raise ArgumentError, "Cannot specify both :except and :only!"
|
75
79
|
elsif options[:except]
|
76
80
|
except = Array(options[:except]).collect(&:to_sym)
|
77
81
|
@filter = ->(dependency) { (except & dependency.groups).empty? }
|
@@ -114,7 +118,7 @@ module Berkshelf
|
|
114
118
|
# cookbook 'artifact', path: '/Users/reset/code/artifact'
|
115
119
|
#
|
116
120
|
# @example a cookbook dependency that will be retrieved from a Git server
|
117
|
-
# cookbook 'artifact', git: '
|
121
|
+
# cookbook 'artifact', git: 'https://github.com/chef/artifact-cookbook.git'
|
118
122
|
#
|
119
123
|
# @overload cookbook(name, version_constraint, options = {})
|
120
124
|
# @param [#to_s] name
|
@@ -142,7 +146,7 @@ module Berkshelf
|
|
142
146
|
# @see PathLocation
|
143
147
|
# @see GitLocation
|
144
148
|
def cookbook(*args)
|
145
|
-
options = args.last.is_a?(Hash) ? args.pop :
|
149
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
146
150
|
name, constraint = args
|
147
151
|
|
148
152
|
options[:path] &&= File.expand_path(options[:path], File.dirname(filepath))
|
@@ -152,7 +156,7 @@ module Berkshelf
|
|
152
156
|
options[:group] += @active_group
|
153
157
|
end
|
154
158
|
|
155
|
-
add_dependency(name, constraint, options)
|
159
|
+
add_dependency(name, constraint, **options)
|
156
160
|
end
|
157
161
|
expose :cookbook
|
158
162
|
|
@@ -172,9 +176,12 @@ module Berkshelf
|
|
172
176
|
# @option options [String] :path
|
173
177
|
# path to the metadata file
|
174
178
|
def metadata(options = {})
|
175
|
-
path
|
176
|
-
|
177
|
-
|
179
|
+
path = options[:path] || File.dirname(filepath)
|
180
|
+
|
181
|
+
loader = Chef::Cookbook::CookbookVersionLoader.new(path)
|
182
|
+
loader.load!
|
183
|
+
cookbook_version = loader.cookbook_version
|
184
|
+
metadata = cookbook_version.metadata
|
178
185
|
|
179
186
|
add_dependency(metadata.name, nil, path: path, metadata: true)
|
180
187
|
end
|
@@ -191,11 +198,15 @@ module Berkshelf
|
|
191
198
|
# @param [String] api_url
|
192
199
|
# url for the api to add
|
193
200
|
#
|
201
|
+
# @param [Hash] options
|
202
|
+
# extra source options
|
203
|
+
#
|
194
204
|
# @raise [InvalidSourceURI]
|
195
205
|
#
|
196
206
|
# @return [Array<Source>]
|
197
|
-
def source(api_url)
|
198
|
-
|
207
|
+
def source(api_url, **options)
|
208
|
+
source = Source.new(self, api_url, **options)
|
209
|
+
@sources[source.uri.to_s] = source
|
199
210
|
end
|
200
211
|
expose :source
|
201
212
|
|
@@ -249,35 +260,6 @@ module Berkshelf
|
|
249
260
|
sources.find { |source| source.cookbook(name, version) }
|
250
261
|
end
|
251
262
|
|
252
|
-
# @todo remove in Berkshelf 4.0
|
253
|
-
#
|
254
|
-
# @raise [DeprecatedError]
|
255
|
-
def site(*args)
|
256
|
-
if args.first == :opscode
|
257
|
-
Berkshelf.formatter.deprecation "Your Berksfile contains a site location pointing to the Opscode Community " +
|
258
|
-
"Site (site :opscode). Site locations have been replaced by the source location. Change this to: " +
|
259
|
-
"'source \"https://supermarket.chef.io\"' to remove this warning. For more information visit " +
|
260
|
-
"https://github.com/berkshelf/berkshelf/wiki/deprecated-locations"
|
261
|
-
source(DEFAULT_API_URL)
|
262
|
-
return
|
263
|
-
end
|
264
|
-
|
265
|
-
raise DeprecatedError.new "Your Berksfile contains a site location. Site locations have been " +
|
266
|
-
" replaced by the source location. Please remove your site location and try again. For more information " +
|
267
|
-
" visit https://github.com/berkshelf/berkshelf/wiki/deprecated-locations"
|
268
|
-
end
|
269
|
-
expose :site
|
270
|
-
|
271
|
-
# @todo remove in Berkshelf 4.0
|
272
|
-
#
|
273
|
-
# @raise [DeprecatedError]
|
274
|
-
def chef_api(*args)
|
275
|
-
raise DeprecatedError.new "Your Berksfile contains a chef_api location. Chef API locations have " +
|
276
|
-
" been replaced by the source location. Please remove your site location and try again. For more " +
|
277
|
-
" information visit https://github.com/berkshelf/berkshelf/wiki/deprecated-locations"
|
278
|
-
end
|
279
|
-
expose :chef_api
|
280
|
-
|
281
263
|
# Add a dependency of the given name and constraint to the array of dependencies.
|
282
264
|
#
|
283
265
|
# @param [String] name
|
@@ -300,14 +282,15 @@ module Berkshelf
|
|
300
282
|
if @dependencies[name]
|
301
283
|
# Only raise an exception if the dependency is a true duplicate
|
302
284
|
groups = (options[:group].nil? || options[:group].empty?) ? [:default] : options[:group]
|
303
|
-
|
285
|
+
unless (@dependencies[name].groups & groups).empty?
|
304
286
|
raise DuplicateDependencyDefined.new(name)
|
305
287
|
end
|
306
288
|
end
|
307
289
|
|
308
|
-
|
309
|
-
|
310
|
-
|
290
|
+
# this appears to be dead code
|
291
|
+
# if options[:path]
|
292
|
+
# metadata_file = File.join(options[:path], "metadata.rb")
|
293
|
+
# end
|
311
294
|
|
312
295
|
options[:constraint] = constraint
|
313
296
|
|
@@ -444,7 +427,7 @@ module Berkshelf
|
|
444
427
|
end
|
445
428
|
|
446
429
|
# NOTE: We intentionally do NOT pass options to the installer
|
447
|
-
|
430
|
+
install
|
448
431
|
end
|
449
432
|
|
450
433
|
# Retrieve information about a given cookbook that is installed by this Berksfile.
|
@@ -485,6 +468,10 @@ module Berkshelf
|
|
485
468
|
# List of all the cookbooks which have a newer version found at a source
|
486
469
|
# that satisfies the constraints of your dependencies.
|
487
470
|
#
|
471
|
+
# @param [Boolean] include_non_satisfying
|
472
|
+
# include cookbooks that would not satisfy the given constraints in the
|
473
|
+
# +Berksfile+. Defaults to false.
|
474
|
+
#
|
488
475
|
# @return [Hash]
|
489
476
|
# a hash of cached cookbooks and their latest version grouped by their
|
490
477
|
# remote API source. The hash will be empty if there are no newer
|
@@ -500,7 +487,7 @@ module Berkshelf
|
|
500
487
|
# }
|
501
488
|
# }
|
502
489
|
# }
|
503
|
-
def outdated(*names)
|
490
|
+
def outdated(*names, include_non_satisfying: false)
|
504
491
|
validate_lockfile_present!
|
505
492
|
validate_lockfile_trusted!
|
506
493
|
validate_dependencies_installed!
|
@@ -511,16 +498,16 @@ module Berkshelf
|
|
511
498
|
cookbooks = source.versions(name)
|
512
499
|
|
513
500
|
latest = cookbooks.select do |cookbook|
|
514
|
-
dependency.version_constraint.satisfies?(cookbook.version) &&
|
515
|
-
|
516
|
-
end.
|
501
|
+
(include_non_satisfying || dependency.version_constraint.satisfies?(cookbook.version)) &&
|
502
|
+
Semverse::Version.coerce(cookbook.version) > dependency.locked_version
|
503
|
+
end.max_by(&:version)
|
517
504
|
|
518
505
|
unless latest.nil?
|
519
506
|
hash[name] ||= {
|
520
|
-
|
521
|
-
|
522
|
-
source => Semverse::Version.coerce(latest.version)
|
523
|
-
}
|
507
|
+
"local" => dependency.locked_version,
|
508
|
+
"remote" => {
|
509
|
+
source => Semverse::Version.coerce(latest.version),
|
510
|
+
},
|
524
511
|
}
|
525
512
|
end
|
526
513
|
end
|
@@ -609,7 +596,7 @@ module Berkshelf
|
|
609
596
|
packager.validate!
|
610
597
|
|
611
598
|
outdir = Dir.mktmpdir do |temp_dir|
|
612
|
-
Berkshelf.ui.mute { vendor(File.join(temp_dir,
|
599
|
+
Berkshelf.ui.mute { vendor(File.join(temp_dir, "cookbooks")) }
|
613
600
|
packager.run(temp_dir)
|
614
601
|
end
|
615
602
|
|
@@ -617,6 +604,25 @@ module Berkshelf
|
|
617
604
|
outdir
|
618
605
|
end
|
619
606
|
|
607
|
+
# backcompat with ridley lookup of chefignore
|
608
|
+
def find_chefignore(path)
|
609
|
+
filename = "chefignore"
|
610
|
+
|
611
|
+
Pathname.new(path).ascend do |dir|
|
612
|
+
next unless dir.directory?
|
613
|
+
|
614
|
+
[
|
615
|
+
dir.join(filename),
|
616
|
+
dir.join("cookbooks", filename),
|
617
|
+
dir.join(".chef", filename),
|
618
|
+
].each do |possible|
|
619
|
+
return possible.expand_path.to_s if possible.exist?
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
nil
|
624
|
+
end
|
625
|
+
|
620
626
|
# Install the Berksfile or Berksfile.lock and then sync the cached cookbooks
|
621
627
|
# into directories within the given destination matching their name.
|
622
628
|
#
|
@@ -626,32 +632,42 @@ module Berkshelf
|
|
626
632
|
# @return [String, nil]
|
627
633
|
# the expanded path cookbooks were vendored to or nil if nothing was vendored
|
628
634
|
def vendor(destination)
|
629
|
-
Dir.mktmpdir(
|
630
|
-
chefignore = nil
|
635
|
+
Dir.mktmpdir("vendor") do |scratch|
|
631
636
|
cached_cookbooks = install
|
632
|
-
raw_metadata_files = []
|
633
637
|
|
634
638
|
return nil if cached_cookbooks.empty?
|
635
639
|
|
636
640
|
cached_cookbooks.each do |cookbook|
|
637
641
|
Berkshelf.formatter.vendor(cookbook, destination)
|
642
|
+
|
638
643
|
cookbook_destination = File.join(scratch, cookbook.cookbook_name)
|
639
644
|
FileUtils.mkdir_p(cookbook_destination)
|
640
645
|
|
641
646
|
# Dir.glob does not support backslash as a File separator
|
642
|
-
src = cookbook.path.to_s.
|
643
|
-
files = FileSyncer.glob(File.join(src,
|
647
|
+
src = cookbook.path.to_s.tr("\\", "/")
|
648
|
+
files = FileSyncer.glob(File.join(src, "**/*"))
|
644
649
|
|
645
|
-
|
646
|
-
|
650
|
+
# strip directories
|
651
|
+
files.reject! { |file_path| File.directory?(file_path) }
|
647
652
|
|
648
|
-
|
649
|
-
|
650
|
-
|
653
|
+
# convert to relative Pathname objects for chefignore
|
654
|
+
files.map! { |file_path| Chef::Util::PathHelper.relative_path_from(cookbook.path.to_s, file_path) }
|
655
|
+
|
656
|
+
chefignore = Chef::Cookbook::Chefignore.new(find_chefignore(cookbook.path.to_s) || cookbook.path.to_s)
|
657
|
+
|
658
|
+
# apply chefignore
|
659
|
+
files.reject! { |file_path| chefignore.ignored?(file_path) }
|
651
660
|
|
652
|
-
|
661
|
+
# convert Pathname objects back to strings
|
662
|
+
files.map!(&:to_s)
|
653
663
|
|
654
|
-
|
664
|
+
# copy each file to destination
|
665
|
+
files.each do |rpath|
|
666
|
+
FileUtils.mkdir_p( File.join(cookbook_destination, File.dirname(rpath)) )
|
667
|
+
FileUtils.cp( File.join(cookbook.path.to_s, rpath), File.join(cookbook_destination, rpath) )
|
668
|
+
end
|
669
|
+
|
670
|
+
cookbook.compile_metadata(cookbook_destination)
|
655
671
|
end
|
656
672
|
|
657
673
|
# Don't vendor the raw metadata (metadata.rb). The raw metadata is
|
@@ -669,7 +685,7 @@ module Berkshelf
|
|
669
685
|
#
|
670
686
|
# * https://tickets.opscode.com/browse/CHEF-4811
|
671
687
|
# * https://tickets.opscode.com/browse/CHEF-4810
|
672
|
-
FileSyncer.sync(scratch, destination, exclude:
|
688
|
+
FileSyncer.sync(scratch, destination, exclude: EXCLUDED_VCS_FILES_WHEN_VENDORING, delete: @delete)
|
673
689
|
end
|
674
690
|
|
675
691
|
destination
|
@@ -694,12 +710,21 @@ module Berkshelf
|
|
694
710
|
#
|
695
711
|
# @return [String] path
|
696
712
|
# the path where the image was written
|
697
|
-
def viz(outfile = nil)
|
698
|
-
outfile = File.join(Dir.pwd, outfile ||
|
713
|
+
def viz(outfile = nil, format = "png")
|
714
|
+
outfile = File.join(Dir.pwd, outfile || "graph.png")
|
699
715
|
|
700
716
|
validate_lockfile_present!
|
701
717
|
validate_lockfile_trusted!
|
702
|
-
Visualizer.from_lockfile(lockfile)
|
718
|
+
vizualiser = Visualizer.from_lockfile(lockfile)
|
719
|
+
|
720
|
+
case format
|
721
|
+
when "dot"
|
722
|
+
vizualiser.to_dot_file(outfile)
|
723
|
+
when "png"
|
724
|
+
vizualiser.to_png(outfile)
|
725
|
+
else
|
726
|
+
raise ConfigurationError, "Vizualiser format #{format} not recognised."
|
727
|
+
end
|
703
728
|
end
|
704
729
|
|
705
730
|
# Get the lockfile corresponding to this Berksfile. This is necessary because
|
@@ -715,62 +740,64 @@ module Berkshelf
|
|
715
740
|
|
716
741
|
private
|
717
742
|
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
true
|
727
|
-
end
|
743
|
+
# Ensure the lockfile is present on disk.
|
744
|
+
#
|
745
|
+
# @raise [LockfileNotFound]
|
746
|
+
# if the lockfile does not exist on disk
|
747
|
+
#
|
748
|
+
# @return [true]
|
749
|
+
def validate_lockfile_present!
|
750
|
+
raise LockfileNotFound unless lockfile.present?
|
728
751
|
|
729
|
-
|
730
|
-
|
731
|
-
#
|
732
|
-
# @raise [LockfileOutOfSync]
|
733
|
-
# if there are dependencies specified in the Berksfile which do not
|
734
|
-
# exist (or are not satisifed by) the lockfile
|
735
|
-
#
|
736
|
-
# @return [true]
|
737
|
-
def validate_lockfile_trusted!
|
738
|
-
raise LockfileOutOfSync unless lockfile.trusted?
|
739
|
-
true
|
740
|
-
end
|
752
|
+
true
|
753
|
+
end
|
741
754
|
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
lockfile.graph.locks.each do |_, dependency|
|
753
|
-
unless dependency.installed?
|
754
|
-
raise DependencyNotInstalled.new(dependency)
|
755
|
-
end
|
756
|
-
end
|
755
|
+
# Ensure that all dependencies defined in the Berksfile exist in this
|
756
|
+
# lockfile.
|
757
|
+
#
|
758
|
+
# @raise [LockfileOutOfSync]
|
759
|
+
# if there are dependencies specified in the Berksfile which do not
|
760
|
+
# exist (or are not satisifed by) the lockfile
|
761
|
+
#
|
762
|
+
# @return [true]
|
763
|
+
def validate_lockfile_trusted!
|
764
|
+
raise LockfileOutOfSync unless lockfile.trusted?
|
757
765
|
|
758
|
-
|
766
|
+
true
|
767
|
+
end
|
768
|
+
|
769
|
+
# Ensure that all dependencies in the lockfile are installed on this
|
770
|
+
# system. You should validate that the lockfile can be trusted before
|
771
|
+
# using this method.
|
772
|
+
#
|
773
|
+
# @raise [DependencyNotInstalled]
|
774
|
+
# if the dependency in the lockfile is not in the Berkshelf shelf on
|
775
|
+
# this system
|
776
|
+
#
|
777
|
+
# @return [true]
|
778
|
+
def validate_dependencies_installed!
|
779
|
+
lockfile.graph.locks.each do |_, dependency|
|
780
|
+
unless dependency.installed?
|
781
|
+
raise DependencyNotInstalled.new(dependency)
|
782
|
+
end
|
759
783
|
end
|
760
784
|
|
761
|
-
|
762
|
-
|
763
|
-
# @param [Array<String>] names
|
764
|
-
# a list of cookbook names
|
765
|
-
#
|
766
|
-
# @raise [DependencyNotFound]
|
767
|
-
# if a cookbook name is given that does not exist
|
768
|
-
def validate_cookbook_names!(names)
|
769
|
-
missing = names - lockfile.graph.locks.keys
|
785
|
+
true
|
786
|
+
end
|
770
787
|
|
771
|
-
|
772
|
-
|
773
|
-
|
788
|
+
# Determine if any cookbooks were specified that aren't in our shelf.
|
789
|
+
#
|
790
|
+
# @param [Array<String>] names
|
791
|
+
# a list of cookbook names
|
792
|
+
#
|
793
|
+
# @raise [DependencyNotFound]
|
794
|
+
# if a cookbook name is given that does not exist
|
795
|
+
def validate_cookbook_names!(names)
|
796
|
+
missing = names - lockfile.graph.locks.keys
|
797
|
+
|
798
|
+
unless missing.empty?
|
799
|
+
raise DependencyNotFound.new(missing)
|
774
800
|
end
|
801
|
+
end
|
775
802
|
end
|
776
803
|
end
|
@@ -1,5 +1,10 @@
|
|
1
|
+
require "chef/cookbook/cookbook_version_loader"
|
2
|
+
require "chef/cookbook/syntax_check"
|
3
|
+
require_relative "errors"
|
4
|
+
require "chef/json_compat"
|
5
|
+
|
1
6
|
module Berkshelf
|
2
|
-
class CachedCookbook
|
7
|
+
class CachedCookbook
|
3
8
|
class << self
|
4
9
|
# @param [#to_s] path
|
5
10
|
# a path on disk to the location of a Cookbook downloaded by the Downloader
|
@@ -15,38 +20,108 @@ module Berkshelf
|
|
15
20
|
loaded_cookbooks[path.to_s] ||= from_path(path)
|
16
21
|
end
|
17
22
|
|
23
|
+
# Creates a new instance of Berkshelf::CachedCookbook from a path on disk containing
|
24
|
+
# a Cookbook.
|
25
|
+
#
|
26
|
+
# The name of the Cookbook is determined by the value of the name attribute set in
|
27
|
+
# the cookbooks' metadata. If the name attribute is not present the name of the loaded
|
28
|
+
# cookbook is determined by directory containing the cookbook.
|
29
|
+
#
|
30
|
+
# @param [#to_s] path
|
31
|
+
# a path on disk to the location of a Cookbook
|
32
|
+
#
|
33
|
+
# @raise [IOError] if the path does not contain a metadata.rb or metadata.json file
|
34
|
+
#
|
35
|
+
# @return [Ridley::Chef::Cookbook]
|
36
|
+
def from_path(path)
|
37
|
+
path = Pathname.new(path)
|
38
|
+
|
39
|
+
new(path)
|
40
|
+
end
|
41
|
+
|
42
|
+
def checksum(filepath)
|
43
|
+
Chef::Digester.generate_md5_checksum_for_file(filepath)
|
44
|
+
end
|
45
|
+
|
18
46
|
private
|
19
47
|
|
20
|
-
|
21
|
-
|
22
|
-
|
48
|
+
# @return [Hash<String, CachedCookbook>]
|
49
|
+
def loaded_cookbooks
|
50
|
+
@loaded_cookbooks ||= {}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_writer :metadata
|
55
|
+
attr_accessor :path
|
56
|
+
attr_writer :cookbook_version
|
57
|
+
|
58
|
+
def initialize(path)
|
59
|
+
@path = path
|
60
|
+
# eagerly load to force throwing on bad metadata while constructing
|
61
|
+
cookbook_name
|
62
|
+
metadata
|
63
|
+
end
|
64
|
+
|
65
|
+
def loader
|
66
|
+
@loader ||=
|
67
|
+
begin
|
68
|
+
loader = Chef::Cookbook::CookbookVersionLoader.new(@path)
|
69
|
+
loader.load!
|
70
|
+
loader
|
23
71
|
end
|
24
72
|
end
|
25
73
|
|
74
|
+
def cookbook_version
|
75
|
+
@cookbook_version ||= loader.cookbook_version
|
76
|
+
end
|
77
|
+
|
78
|
+
def cookbook_name
|
79
|
+
@cookbook_name ||= cookbook_version.name
|
80
|
+
end
|
81
|
+
|
82
|
+
def metadata
|
83
|
+
@metadata ||= cookbook_version.metadata
|
84
|
+
end
|
85
|
+
|
86
|
+
def reload
|
87
|
+
@metadata = nil
|
88
|
+
@cookbook_name = nil
|
89
|
+
@cookbook_version = nil
|
90
|
+
@loader = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def <=>(other)
|
94
|
+
[cookbook_name, version] <=> [other.cookbook_name, other.version]
|
95
|
+
end
|
96
|
+
|
26
97
|
DIRNAME_REGEXP = /^(.+)-(.+)$/.freeze
|
27
98
|
|
28
99
|
extend Forwardable
|
100
|
+
|
101
|
+
def_delegator :cookbook_version, :version
|
102
|
+
def_delegator :metadata, :name, :cookbook_name
|
29
103
|
def_delegator :metadata, :description
|
30
104
|
def_delegator :metadata, :maintainer
|
31
105
|
def_delegator :metadata, :maintainer_email
|
32
106
|
def_delegator :metadata, :license
|
33
107
|
def_delegator :metadata, :platforms
|
108
|
+
def_delegator :metadata, :name
|
34
109
|
|
35
110
|
# @return [Hash]
|
36
111
|
def dependencies
|
37
|
-
metadata.
|
112
|
+
metadata.dependencies
|
38
113
|
end
|
39
114
|
|
40
115
|
def pretty_print
|
41
116
|
[].tap do |a|
|
42
|
-
a.push " Name: #{cookbook_name}"
|
43
|
-
a.push " Version: #{version}"
|
44
|
-
a.push " Description: #{metadata.description}"
|
45
|
-
a.push " Author: #{metadata.maintainer}"
|
46
|
-
a.push " Email: #{metadata.maintainer_email}"
|
47
|
-
a.push " License: #{metadata.license}"
|
48
|
-
a.push " Platforms: #{pretty_map(metadata.platforms, 14)}"
|
49
|
-
a.push "Dependencies: #{pretty_map(dependencies, 14)}"
|
117
|
+
a.push " Name: #{cookbook_name}" if name && name =~ /\S/
|
118
|
+
a.push " Version: #{version}" if version && version =~ /\S/
|
119
|
+
a.push " Description: #{metadata.description}" if metadata.description && metadata.description =~ /\S/
|
120
|
+
a.push " Author: #{metadata.maintainer}" if metadata.maintainer && metadata.maintainer =~ /\S/
|
121
|
+
a.push " Email: #{metadata.maintainer_email}" if metadata.maintainer_email && metadata.maintainer_email =~ /\S/
|
122
|
+
a.push " License: #{metadata.license}" if metadata.license && metadata.license =~ /\S/
|
123
|
+
a.push " Platforms: #{pretty_map(metadata.platforms, 14)}" if metadata.platforms && !metadata.platforms.empty?
|
124
|
+
a.push "Dependencies: #{pretty_map(dependencies, 14)}" if dependencies && !dependencies.empty?
|
50
125
|
end.join("\n")
|
51
126
|
end
|
52
127
|
|
@@ -62,21 +137,49 @@ module Berkshelf
|
|
62
137
|
# @return [Hash]
|
63
138
|
def pretty_hash
|
64
139
|
{}.tap do |h|
|
65
|
-
h[:name] = cookbook_name
|
66
|
-
h[:version] = version
|
67
|
-
h[:description] = description
|
68
|
-
h[:author] = maintainer
|
69
|
-
h[:email] = maintainer_email
|
70
|
-
h[:license] = license
|
71
|
-
h[:platforms] = platforms.to_hash
|
72
|
-
h[:dependencies] = dependencies.to_hash
|
140
|
+
h[:name] = cookbook_name if cookbook_name && cookbook_name =~ /\S/
|
141
|
+
h[:version] = version if version && version =~ /\S/
|
142
|
+
h[:description] = description if description && description =~ /\S/
|
143
|
+
h[:author] = maintainer if maintainer && maintainer =~ /\S/
|
144
|
+
h[:email] = maintainer_email if maintainer_email && maintainer_email =~ /\S/
|
145
|
+
h[:license] = license if license && license =~ /\S/
|
146
|
+
h[:platforms] = platforms.to_hash if platforms && !platforms.empty?
|
147
|
+
h[:dependencies] = dependencies.to_hash if dependencies && !dependencies.empty?
|
73
148
|
end
|
74
149
|
end
|
75
150
|
|
76
|
-
|
151
|
+
def validate
|
152
|
+
raise IOError, "No Cookbook found at: #{path}" unless path.exist?
|
153
|
+
|
154
|
+
syntax_checker = Chef::Cookbook::SyntaxCheck.new(path.to_path)
|
77
155
|
|
78
|
-
|
79
|
-
|
156
|
+
unless syntax_checker.validate_ruby_files
|
157
|
+
raise Berkshelf::Errors::CookbookSyntaxError, "Invalid ruby files in cookbook: #{cookbook_name} (#{version})."
|
80
158
|
end
|
159
|
+
unless syntax_checker.validate_templates
|
160
|
+
raise Berkshelf::Errors::CookbookSyntaxError, "Invalid template files in cookbook: #{cookbook_name} (#{version})."
|
161
|
+
end
|
162
|
+
|
163
|
+
true
|
164
|
+
end
|
165
|
+
|
166
|
+
def compile_metadata(path = self.path)
|
167
|
+
json_file = "#{path}/metadata.json"
|
168
|
+
rb_file = "#{path}/metadata.rb"
|
169
|
+
return nil if File.exist?(json_file)
|
170
|
+
|
171
|
+
md = Chef::Cookbook::Metadata.new
|
172
|
+
md.from_file(rb_file)
|
173
|
+
f = File.open(json_file, "w")
|
174
|
+
f.write(Chef::JSONCompat.to_json_pretty(md))
|
175
|
+
f.close
|
176
|
+
f.path
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def pretty_map(hash, padding)
|
182
|
+
hash.map { |k, v| "#{k} (#{v})" }.join("\n" + " " * padding)
|
183
|
+
end
|
81
184
|
end
|
82
185
|
end
|