berkshelf 7.0.8 → 7.2.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.
- checksums.yaml +4 -4
- data/Gemfile +4 -12
- data/Rakefile +3 -3
- data/berkshelf.gemspec +3 -4
- data/bin/berks +1 -1
- data/lib/berkshelf.rb +8 -9
- data/lib/berkshelf/api_client/chef_server_connection.rb +3 -2
- data/lib/berkshelf/api_client/connection.rb +1 -1
- data/lib/berkshelf/api_client/remote_cookbook.rb +1 -1
- data/lib/berkshelf/berksfile.rb +41 -39
- data/lib/berkshelf/cached_cookbook.rb +5 -3
- data/lib/berkshelf/chef_config_compat.rb +1 -1
- data/lib/berkshelf/chef_repo_universe.rb +4 -2
- data/lib/berkshelf/cli.rb +6 -6
- data/lib/berkshelf/commands/shelf.rb +1 -1
- data/lib/berkshelf/community_rest.rb +6 -6
- data/lib/berkshelf/config.rb +3 -3
- data/lib/berkshelf/cookbook_store.rb +2 -4
- data/lib/berkshelf/core_ext.rb +1 -1
- data/lib/berkshelf/core_ext/file_utils.rb +3 -3
- data/lib/berkshelf/dependency.rb +1 -1
- data/lib/berkshelf/downloader.rb +9 -6
- data/lib/berkshelf/errors.rb +5 -2
- data/lib/berkshelf/file_syncer.rb +10 -12
- data/lib/berkshelf/formatters/human.rb +1 -1
- data/lib/berkshelf/formatters/json.rb +1 -1
- data/lib/berkshelf/installer.rb +1 -1
- data/lib/berkshelf/location.rb +3 -3
- data/lib/berkshelf/locations/git.rb +6 -12
- data/lib/berkshelf/lockfile.rb +11 -11
- data/lib/berkshelf/logger.rb +4 -2
- data/lib/berkshelf/mixin/git.rb +3 -3
- data/lib/berkshelf/packager.rb +5 -7
- data/lib/berkshelf/resolver.rb +1 -1
- data/lib/berkshelf/ridley_compat.rb +1 -1
- data/lib/berkshelf/shell.rb +2 -1
- data/lib/berkshelf/shell_out.rb +4 -3
- data/lib/berkshelf/source.rb +8 -7
- data/lib/berkshelf/source_uri.rb +1 -1
- data/lib/berkshelf/ssl_policies.rb +5 -9
- data/lib/berkshelf/thor.rb +1 -1
- data/lib/berkshelf/thor_ext.rb +1 -1
- data/lib/berkshelf/uploader.rb +8 -6
- data/lib/berkshelf/validator.rb +2 -8
- data/lib/berkshelf/version.rb +1 -1
- data/lib/berkshelf/visualizer.rb +3 -3
- data/spec/config/knife.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/chef_server.rb +2 -2
- data/spec/support/git.rb +18 -18
- data/spec/support/path_helpers.rb +4 -4
- data/spec/unit/berkshelf/berksfile_spec.rb +7 -7
- data/spec/unit/berkshelf/cli_spec.rb +1 -2
- data/spec/unit/berkshelf/community_rest_spec.rb +1 -1
- data/spec/unit/berkshelf/core_ext/file_utils_spec.rb +2 -2
- data/spec/unit/berkshelf/dependency_spec.rb +5 -5
- data/spec/unit/berkshelf/downloader_spec.rb +4 -8
- data/spec/unit/berkshelf/locations/base_spec.rb +1 -2
- data/spec/unit/berkshelf/locations/git_spec.rb +2 -5
- data/spec/unit/berkshelf/locations/path_spec.rb +1 -2
- data/spec/unit/berkshelf/lockfile_spec.rb +9 -18
- data/spec/unit/berkshelf/ridley_compat_spec.rb +2 -2
- data/spec/unit/berkshelf/source_spec.rb +30 -19
- data/spec/unit/berkshelf/ssl_policies_spec.rb +3 -6
- data/spec/unit/berkshelf/uploader_spec.rb +6 -10
- data/spec/unit/berkshelf/validator_spec.rb +0 -13
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4950e40e68a8fa20ad29aa5d589f27e4dd3fa0d7966abaedae2a9fc81398bc42
|
4
|
+
data.tar.gz: 706ca0ccbf4033186ac0adb6b1da988a55028fa1ccfae5c09a02c2ac414d31b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4207838b3b203d6446a6f4d529e2d74a67a4109dadb206011be3e9f34a7bd3ca5373df4e3ec5e07994da54571d6c9d91c7c245cd45b4afdbe5b6481c5db9aec
|
7
|
+
data.tar.gz: 4a57a2691d696385dbf46aa141b69b5dcd619a920f9abfb3a8b4ce0f5c3155591216b7c1267a804f3f80c8b805875253824b67686a1141df0107e772329fb3dc
|
data/Gemfile
CHANGED
@@ -2,18 +2,14 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
group :changelog do
|
6
|
-
gem "github_changelog_generator"
|
7
|
-
end
|
8
|
-
|
9
5
|
group :build do
|
10
6
|
gem "rake", ">= 10.1"
|
11
7
|
end
|
12
8
|
|
13
9
|
group :development do
|
14
|
-
|
15
|
-
|
16
|
-
gem "
|
10
|
+
gem "chef-bin" # for the proxy tests
|
11
|
+
gem "aruba", "~> 0.10" # Stay below 1 until aruba/in_process monkeypatching stops
|
12
|
+
gem "cucumber", "< 4.0" # until we identify what is generating the ~@no_run tag in CI
|
17
13
|
gem "cucumber-expressions", "= 5.0.13"
|
18
14
|
gem "chef-zero", ">= 4.0"
|
19
15
|
gem "dep_selector", ">= 1.0"
|
@@ -22,11 +18,7 @@ group :development do
|
|
22
18
|
gem "rspec-its", ">= 1.2"
|
23
19
|
gem "webmock", ">= 1.11"
|
24
20
|
gem "http", ">= 0.9.8"
|
25
|
-
gem "chefstyle"
|
26
|
-
end
|
27
|
-
|
28
|
-
group :docs do
|
29
|
-
gem "yard", ">= 0.8"
|
21
|
+
gem "chefstyle"
|
30
22
|
end
|
31
23
|
|
32
24
|
instance_eval(ENV["GEMFILE_MOD"]) if ENV["GEMFILE_MOD"]
|
data/Rakefile
CHANGED
@@ -14,8 +14,8 @@ begin
|
|
14
14
|
require "cucumber"
|
15
15
|
require "cucumber/rake/task"
|
16
16
|
Cucumber::Rake::Task.new(:features) do |t|
|
17
|
-
if RUBY_PLATFORM =~ WINDOWS_PLATFORM
|
18
|
-
t.cucumber_opts = "--tags
|
17
|
+
if RUBY_PLATFORM =~ WINDOWS_PLATFORM || RUBY_PLATFORM =~ /darwin/
|
18
|
+
t.cucumber_opts = "--tags 'not @not-windows'"
|
19
19
|
end
|
20
20
|
end
|
21
21
|
rescue LoadError
|
@@ -35,7 +35,7 @@ begin
|
|
35
35
|
rescue LoadError
|
36
36
|
end
|
37
37
|
|
38
|
-
task default:
|
38
|
+
task default: %i{spec features}
|
39
39
|
task :ci do
|
40
40
|
ENV["CI"] = "true"
|
41
41
|
Rake::Task[:spec].invoke
|
data/berkshelf.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require File.expand_path("../lib/berkshelf/version", __FILE__)
|
1
|
+
require File.expand_path("lib/berkshelf/version", __dir__)
|
3
2
|
|
4
3
|
Gem::Specification.new do |s|
|
5
4
|
s.authors = [
|
@@ -36,9 +35,9 @@ Gem::Specification.new do |s|
|
|
36
35
|
s.add_dependency "solve", "~> 4.0"
|
37
36
|
s.add_dependency "thor", ">= 0.20"
|
38
37
|
s.add_dependency "octokit", "~> 4.0"
|
39
|
-
s.add_dependency "mixlib-archive", ">=
|
38
|
+
s.add_dependency "mixlib-archive", ">= 1.1.4", "< 2.0" # needed for ruby 3.0 / Dir.chdir removal
|
40
39
|
s.add_dependency "concurrent-ruby", "~> 1.0"
|
41
|
-
s.add_dependency "chef", ">=
|
40
|
+
s.add_dependency "chef", ">= 15.7.32" # needed for --skip-syntax-check
|
42
41
|
s.add_dependency "chef-config"
|
43
42
|
# this is required for Mixlib::Config#from_json
|
44
43
|
s.add_dependency "mixlib-config", ">= 2.2.5"
|
data/bin/berks
CHANGED
data/lib/berkshelf.rb
CHANGED
@@ -10,20 +10,20 @@ rescue LoadError
|
|
10
10
|
end
|
11
11
|
|
12
12
|
require "cleanroom"
|
13
|
-
require "digest/md5"
|
14
|
-
require "forwardable"
|
15
|
-
require "json"
|
16
|
-
require "pathname"
|
13
|
+
require "digest/md5" unless defined?(Digest::MD5)
|
14
|
+
require "forwardable" unless defined?(Forwardable)
|
15
|
+
require "json" unless defined?(JSON)
|
16
|
+
require "pathname" unless defined?(Pathname)
|
17
17
|
require "semverse"
|
18
18
|
require "solve"
|
19
|
-
require "thor"
|
20
|
-
require "uri"
|
19
|
+
require "thor" unless defined?(Thor)
|
20
|
+
require "uri" unless defined?(URI)
|
21
21
|
|
22
22
|
JSON.create_id = nil
|
23
23
|
|
24
24
|
require_relative "berkshelf/core_ext"
|
25
25
|
require_relative "berkshelf/thor_ext"
|
26
|
-
|
26
|
+
require_relative "berkshelf/chef_config_compat"
|
27
27
|
|
28
28
|
module Berkshelf
|
29
29
|
Encoding.default_external = Encoding::UTF_8
|
@@ -169,7 +169,7 @@ module Berkshelf
|
|
169
169
|
raise ChefConnectionError, "Missing required attribute in your Berkshelf configuration: chef.client_key"
|
170
170
|
end
|
171
171
|
|
172
|
-
RidleyCompat.new_client(ridley_options, &block)
|
172
|
+
RidleyCompat.new_client(**ridley_options, &block)
|
173
173
|
rescue ChefConnectionError, BerkshelfError
|
174
174
|
raise
|
175
175
|
rescue => ex
|
@@ -222,7 +222,6 @@ require_relative "berkshelf/lockfile"
|
|
222
222
|
require_relative "berkshelf/berksfile"
|
223
223
|
require_relative "berkshelf/cached_cookbook"
|
224
224
|
require_relative "berkshelf/cli"
|
225
|
-
require_relative "berkshelf/chef_config_compat"
|
226
225
|
require_relative "berkshelf/community_rest"
|
227
226
|
require_relative "berkshelf/cookbook_store"
|
228
227
|
require_relative "berkshelf/config"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "../ridley_compat"
|
2
2
|
|
3
3
|
module Berkshelf
|
4
4
|
module APIClient
|
@@ -19,7 +19,8 @@ module Berkshelf
|
|
19
19
|
response.each do |name, versions|
|
20
20
|
versions.each do |version, attributes|
|
21
21
|
attributes[:location_path] = @url
|
22
|
-
cookbooks << RemoteCookbook.new(name, version, attributes)
|
22
|
+
cookbooks << RemoteCookbook.new(name, version, attributes)
|
23
|
+
end
|
23
24
|
end
|
24
25
|
end
|
25
26
|
rescue Ridley::Errors::HTTPNotFound
|
data/lib/berkshelf/berksfile.rb
CHANGED
@@ -13,7 +13,7 @@ module Berkshelf
|
|
13
13
|
def from_options(options = {})
|
14
14
|
options[:berksfile] ||= File.join(Dir.pwd, Berkshelf::DEFAULT_FILENAME)
|
15
15
|
symbolized = Hash[options.map { |k, v| [k.to_sym, v] }]
|
16
|
-
from_file(options[:berksfile], symbolized.select { |k,|
|
16
|
+
from_file(options[:berksfile], symbolized.select { |k,| %i{except only delete}.include? k })
|
17
17
|
end
|
18
18
|
|
19
19
|
# @param [#to_s] file
|
@@ -66,8 +66,8 @@ module Berkshelf
|
|
66
66
|
# group to be installed and all others to be ignored
|
67
67
|
def initialize(path, options = {})
|
68
68
|
@filepath = File.expand_path(path)
|
69
|
-
@dependencies =
|
70
|
-
@sources =
|
69
|
+
@dependencies = {}
|
70
|
+
@sources = {}
|
71
71
|
@delete = options[:delete]
|
72
72
|
|
73
73
|
# defaults for what solvers to use
|
@@ -146,7 +146,7 @@ module Berkshelf
|
|
146
146
|
# @see PathLocation
|
147
147
|
# @see GitLocation
|
148
148
|
def cookbook(*args)
|
149
|
-
options = args.last.is_a?(Hash) ? args.pop :
|
149
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
150
150
|
name, constraint = args
|
151
151
|
|
152
152
|
options[:path] &&= File.expand_path(options[:path], File.dirname(filepath))
|
@@ -176,10 +176,10 @@ module Berkshelf
|
|
176
176
|
# @option options [String] :path
|
177
177
|
# path to the metadata file
|
178
178
|
def metadata(options = {})
|
179
|
-
path
|
179
|
+
path = options[:path] || File.dirname(filepath)
|
180
180
|
|
181
181
|
loader = Chef::Cookbook::CookbookVersionLoader.new(path)
|
182
|
-
loader.
|
182
|
+
loader.load!
|
183
183
|
cookbook_version = loader.cookbook_version
|
184
184
|
metadata = cookbook_version.metadata
|
185
185
|
|
@@ -282,7 +282,7 @@ module Berkshelf
|
|
282
282
|
if @dependencies[name]
|
283
283
|
# Only raise an exception if the dependency is a true duplicate
|
284
284
|
groups = (options[:group].nil? || options[:group].empty?) ? [:default] : options[:group]
|
285
|
-
|
285
|
+
unless (@dependencies[name].groups & groups).empty?
|
286
286
|
raise DuplicateDependencyDefined.new(name)
|
287
287
|
end
|
288
288
|
end
|
@@ -500,7 +500,7 @@ module Berkshelf
|
|
500
500
|
latest = cookbooks.select do |cookbook|
|
501
501
|
(include_non_satisfying || dependency.version_constraint.satisfies?(cookbook.version)) &&
|
502
502
|
Semverse::Version.coerce(cookbook.version) > dependency.locked_version
|
503
|
-
end.
|
503
|
+
end.max_by(&:version)
|
504
504
|
|
505
505
|
unless latest.nil?
|
506
506
|
hash[name] ||= {
|
@@ -659,7 +659,7 @@ module Berkshelf
|
|
659
659
|
files.reject! { |file_path| chefignore.ignored?(file_path) }
|
660
660
|
|
661
661
|
# convert Pathname objects back to strings
|
662
|
-
files.map!
|
662
|
+
files.map!(&:to_s)
|
663
663
|
|
664
664
|
# copy each file to destination
|
665
665
|
files.each do |rpath|
|
@@ -740,39 +740,41 @@ module Berkshelf
|
|
740
740
|
|
741
741
|
private
|
742
742
|
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
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
749
|
def validate_lockfile_present!
|
750
750
|
raise LockfileNotFound unless lockfile.present?
|
751
|
+
|
751
752
|
true
|
752
753
|
end
|
753
754
|
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
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]
|
762
763
|
def validate_lockfile_trusted!
|
763
764
|
raise LockfileOutOfSync unless lockfile.trusted?
|
765
|
+
|
764
766
|
true
|
765
767
|
end
|
766
768
|
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
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]
|
776
778
|
def validate_dependencies_installed!
|
777
779
|
lockfile.graph.locks.each do |_, dependency|
|
778
780
|
unless dependency.installed?
|
@@ -783,13 +785,13 @@ module Berkshelf
|
|
783
785
|
true
|
784
786
|
end
|
785
787
|
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
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
|
793
795
|
def validate_cookbook_names!(names)
|
794
796
|
missing = names - lockfile.graph.locks.keys
|
795
797
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "chef/cookbook/cookbook_version_loader"
|
2
2
|
require "chef/cookbook/syntax_check"
|
3
|
-
|
3
|
+
require_relative "errors"
|
4
4
|
require "chef/json_compat"
|
5
5
|
|
6
6
|
module Berkshelf
|
@@ -66,7 +66,7 @@ module Berkshelf
|
|
66
66
|
@loader ||=
|
67
67
|
begin
|
68
68
|
loader = Chef::Cookbook::CookbookVersionLoader.new(@path)
|
69
|
-
loader.
|
69
|
+
loader.load!
|
70
70
|
loader
|
71
71
|
end
|
72
72
|
end
|
@@ -151,7 +151,8 @@ module Berkshelf
|
|
151
151
|
def validate
|
152
152
|
raise IOError, "No Cookbook found at: #{path}" unless path.exist?
|
153
153
|
|
154
|
-
syntax_checker = Chef::Cookbook::SyntaxCheck.
|
154
|
+
syntax_checker = Chef::Cookbook::SyntaxCheck.new(path.to_path)
|
155
|
+
|
155
156
|
unless syntax_checker.validate_ruby_files
|
156
157
|
raise Berkshelf::Errors::CookbookSyntaxError, "Invalid ruby files in cookbook: #{cookbook_name} (#{version})."
|
157
158
|
end
|
@@ -166,6 +167,7 @@ module Berkshelf
|
|
166
167
|
json_file = "#{path}/metadata.json"
|
167
168
|
rb_file = "#{path}/metadata.rb"
|
168
169
|
return nil if File.exist?(json_file)
|
170
|
+
|
169
171
|
md = Chef::Cookbook::Metadata.new
|
170
172
|
md.from_file(rb_file)
|
171
173
|
f = File.open(json_file, "w")
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative "api_client/remote_cookbook"
|
2
|
+
require_relative "cached_cookbook"
|
3
3
|
|
4
4
|
module Berkshelf
|
5
5
|
# Shim to look like a Berkshelf::APIClient but for a chef repo folder.
|
@@ -15,8 +15,10 @@ module Berkshelf
|
|
15
15
|
def universe
|
16
16
|
Dir.entries(cookbooks_path).sort.each_with_object([]) do |entry, cookbooks|
|
17
17
|
next if entry[0] == "." # Skip hidden folders.
|
18
|
+
|
18
19
|
entry_path = "#{cookbooks_path}/#{entry}"
|
19
20
|
next unless File.directory?(entry_path) # Skip non-dirs.
|
21
|
+
|
20
22
|
cookbook = begin
|
21
23
|
Berkshelf::CachedCookbook.from_path(entry_path)
|
22
24
|
rescue IOError
|
data/lib/berkshelf/cli.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "../berkshelf"
|
2
2
|
require_relative "config"
|
3
3
|
require_relative "commands/shelf"
|
4
4
|
|
@@ -419,11 +419,11 @@ module Berkshelf
|
|
419
419
|
|
420
420
|
private
|
421
421
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
422
|
+
# Print a list of the given cookbooks. This is used by various
|
423
|
+
# methods like {list} and {contingent}.
|
424
|
+
#
|
425
|
+
# @param [Array<CachedCookbook>] cookbooks
|
426
|
+
#
|
427
427
|
def print_list(cookbooks)
|
428
428
|
Array(cookbooks).sort.each do |cookbook|
|
429
429
|
Berkshelf.formatter.msg " * #{cookbook.cookbook_name} (#{cookbook.version})"
|
@@ -13,7 +13,7 @@ module Berkshelf
|
|
13
13
|
else
|
14
14
|
Berkshelf.formatter.msg "Cookbooks in the Berkshelf shelf:"
|
15
15
|
cookbooks.sort.each do |cookbook, versions|
|
16
|
-
Berkshelf.formatter.msg(" * #{cookbook} (#{versions.sort.join(
|
16
|
+
Berkshelf.formatter.msg(" * #{cookbook} (#{versions.sort.join(", ")})")
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require "retryable"
|
2
|
-
require "mixlib/archive"
|
1
|
+
require "retryable" unless defined?(Retryable)
|
2
|
+
require "mixlib/archive" unless defined?(Mixlib::Archive)
|
3
3
|
|
4
4
|
module Berkshelf
|
5
5
|
class CommunityREST
|
@@ -69,13 +69,13 @@ module Berkshelf
|
|
69
69
|
# how often we should pause between retries
|
70
70
|
def initialize(uri = V1_API, options = {})
|
71
71
|
options = options.dup
|
72
|
-
options
|
73
|
-
@api_uri
|
72
|
+
options = { retries: 5, retry_interval: 0.5, ssl: Berkshelf::Config.instance.ssl }.merge(options)
|
73
|
+
@api_uri = uri
|
74
74
|
options[:server_url] = uri
|
75
|
-
@retries
|
75
|
+
@retries = options.delete(:retries)
|
76
76
|
@retry_interval = options.delete(:retry_interval)
|
77
77
|
|
78
|
-
@connection = Berkshelf::RidleyCompatJSON.new(options)
|
78
|
+
@connection = Berkshelf::RidleyCompatJSON.new(**options)
|
79
79
|
end
|
80
80
|
|
81
81
|
# Download and extract target cookbook archive to the local file system,
|