berkshelf 5.2.0 → 8.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +19 -47
  3. data/Rakefile +14 -4
  4. data/berkshelf.gemspec +61 -40
  5. data/bin/berks +2 -2
  6. data/lib/berkshelf/api-client.rb +1 -0
  7. data/lib/berkshelf/api_client/chef_server_connection.rb +29 -0
  8. data/lib/berkshelf/api_client/connection.rb +57 -0
  9. data/lib/berkshelf/api_client/errors.rb +10 -0
  10. data/lib/berkshelf/api_client/remote_cookbook.rb +56 -0
  11. data/lib/berkshelf/api_client/version.rb +5 -0
  12. data/lib/berkshelf/api_client.rb +24 -0
  13. data/lib/berkshelf/berksfile.rb +149 -122
  14. data/lib/berkshelf/cached_cookbook.rb +127 -24
  15. data/lib/berkshelf/chef_config_compat.rb +51 -0
  16. data/lib/berkshelf/chef_repo_universe.rb +47 -0
  17. data/lib/berkshelf/cli.rb +143 -174
  18. data/lib/berkshelf/commands/shelf.rb +20 -19
  19. data/lib/berkshelf/community_rest.rb +59 -94
  20. data/lib/berkshelf/config.rb +97 -127
  21. data/lib/berkshelf/cookbook_store.rb +7 -6
  22. data/lib/berkshelf/core_ext/file.rb +1 -1
  23. data/lib/berkshelf/core_ext/file_utils.rb +4 -4
  24. data/lib/berkshelf/core_ext.rb +1 -1
  25. data/lib/berkshelf/dependency.rb +25 -32
  26. data/lib/berkshelf/downloader.rb +66 -39
  27. data/lib/berkshelf/errors.rb +23 -17
  28. data/lib/berkshelf/file_syncer.rb +24 -47
  29. data/lib/berkshelf/formatters/human.rb +7 -5
  30. data/lib/berkshelf/formatters/json.rb +6 -6
  31. data/lib/berkshelf/installer.rb +120 -111
  32. data/lib/berkshelf/location.rb +14 -14
  33. data/lib/berkshelf/locations/base.rb +1 -1
  34. data/lib/berkshelf/locations/git.rb +16 -24
  35. data/lib/berkshelf/locations/github.rb +2 -2
  36. data/lib/berkshelf/locations/path.rb +2 -2
  37. data/lib/berkshelf/lockfile.rb +326 -328
  38. data/lib/berkshelf/logger.rb +64 -1
  39. data/lib/berkshelf/mixin/git.rb +6 -5
  40. data/lib/berkshelf/packager.rb +44 -10
  41. data/lib/berkshelf/resolver/graph.rb +1 -1
  42. data/lib/berkshelf/resolver.rb +4 -4
  43. data/lib/berkshelf/ridley_compat.rb +109 -0
  44. data/lib/berkshelf/shell.rb +2 -1
  45. data/lib/berkshelf/shell_out.rb +18 -0
  46. data/lib/berkshelf/source.rb +77 -33
  47. data/lib/berkshelf/source_uri.rb +4 -4
  48. data/lib/berkshelf/ssl_policies.rb +38 -0
  49. data/lib/berkshelf/thor.rb +1 -1
  50. data/lib/berkshelf/thor_ext/hash_with_indifferent_access.rb +1 -1
  51. data/lib/berkshelf/thor_ext.rb +1 -1
  52. data/lib/berkshelf/uploader.rb +106 -70
  53. data/lib/berkshelf/validator.rb +13 -5
  54. data/lib/berkshelf/version.rb +1 -1
  55. data/lib/berkshelf/visualizer.rb +16 -11
  56. data/lib/berkshelf.rb +106 -81
  57. data/spec/config/knife.rb +4 -4
  58. data/spec/data/trusted_certs/example.crt +22 -0
  59. data/spec/fixtures/Berksfile +3 -3
  60. data/spec/fixtures/complex-cookbook-path/cookbooks/app/metadata.rb +2 -0
  61. data/spec/fixtures/complex-cookbook-path/cookbooks/jenkins/metadata.rb +2 -0
  62. data/spec/fixtures/complex-cookbook-path/cookbooks/jenkins-config/metadata.rb +4 -0
  63. data/spec/fixtures/cookbook-path/jenkins-config/metadata.rb +3 -3
  64. data/spec/fixtures/cookbook-path-uploader/apt-2.3.6/metadata.rb +2 -0
  65. data/spec/fixtures/cookbook-path-uploader/build-essential-1.4.2/metadata.rb +2 -0
  66. data/spec/fixtures/cookbook-path-uploader/jenkins-2.0.3/metadata.rb +5 -0
  67. data/spec/fixtures/cookbook-path-uploader/jenkins-config-0.1.0/metadata.rb +4 -0
  68. data/spec/fixtures/cookbook-path-uploader/runit-1.5.8/metadata.rb +5 -0
  69. data/spec/fixtures/cookbook-path-uploader/yum-3.0.6/metadata.rb +2 -0
  70. data/spec/fixtures/cookbook-path-uploader/yum-epel-0.2.0/metadata.rb +3 -0
  71. data/spec/fixtures/cookbook-store/jenkins-2.0.3/metadata.rb +5 -5
  72. data/spec/fixtures/cookbook-store/jenkins-2.0.4/metadata.rb +4 -4
  73. data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +3 -3
  74. data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +3 -3
  75. data/spec/spec_helper.rb +56 -64
  76. data/spec/support/chef_api.rb +15 -16
  77. data/spec/support/chef_server.rb +71 -69
  78. data/spec/support/git.rb +59 -58
  79. data/spec/support/kitchen.rb +0 -14
  80. data/spec/support/matchers/file_system_matchers.rb +4 -5
  81. data/spec/support/matchers/filepath_matchers.rb +2 -2
  82. data/spec/support/path_helpers.rb +17 -17
  83. data/spec/support/shared_examples/formatter.rb +1 -1
  84. data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/attributes/default.rb +0 -0
  85. data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/files/default/file.h +0 -0
  86. data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/metadata.rb +2 -0
  87. data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/recipes/default.rb +0 -0
  88. data/spec/tmp/berkshelf/cookbooks/fake-0.1.0/templates/default/template.erb +0 -0
  89. data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/attributes/default.rb +0 -0
  90. data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/files/default/file.h +0 -0
  91. data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/metadata.rb +2 -0
  92. data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/recipes/default.rb +0 -0
  93. data/spec/tmp/berkshelf/cookbooks/fake-0.2.0/templates/default/template.erb +0 -0
  94. data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/attributes/default.rb +0 -0
  95. data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/files/default/file.h +0 -0
  96. data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/metadata.rb +2 -0
  97. data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/recipes/default.rb +0 -0
  98. data/spec/tmp/berkshelf/cookbooks/fake-1.0.0/templates/default/template.erb +0 -0
  99. data/spec/unit/berkshelf/berksfile_spec.rb +84 -105
  100. data/spec/unit/berkshelf/berkshelf/api_client/chef_server_connection_spec.rb +65 -0
  101. data/spec/unit/berkshelf/berkshelf/api_client/connection_spec.rb +157 -0
  102. data/spec/unit/berkshelf/berkshelf/api_client/remote_cookbook_spec.rb +23 -0
  103. data/spec/unit/berkshelf/berkshelf/api_client_spec.rb +9 -0
  104. data/spec/unit/berkshelf/cached_cookbook_spec.rb +45 -47
  105. data/spec/unit/berkshelf/chef_repo_universe_spec.rb +37 -0
  106. data/spec/unit/berkshelf/cli_spec.rb +7 -8
  107. data/spec/unit/berkshelf/community_rest_spec.rb +82 -90
  108. data/spec/unit/berkshelf/config_spec.rb +51 -22
  109. data/spec/unit/berkshelf/cookbook_store_spec.rb +41 -41
  110. data/spec/unit/berkshelf/core_ext/file_utils_spec.rb +7 -8
  111. data/spec/unit/berkshelf/core_ext/pathname_spec.rb +1 -1
  112. data/spec/unit/berkshelf/dependency_spec.rb +48 -48
  113. data/spec/unit/berkshelf/downloader_spec.rb +191 -34
  114. data/spec/unit/berkshelf/errors_spec.rb +3 -3
  115. data/spec/unit/berkshelf/file_syncer_spec.rb +87 -87
  116. data/spec/unit/berkshelf/formatters/base_spec.rb +23 -23
  117. data/spec/unit/berkshelf/formatters/human_spec.rb +2 -2
  118. data/spec/unit/berkshelf/formatters/json_spec.rb +2 -2
  119. data/spec/unit/berkshelf/formatters/null_spec.rb +3 -3
  120. data/spec/unit/berkshelf/installer_spec.rb +8 -8
  121. data/spec/unit/berkshelf/location_spec.rb +11 -11
  122. data/spec/unit/berkshelf/locations/base_spec.rb +35 -36
  123. data/spec/unit/berkshelf/locations/git_spec.rb +90 -93
  124. data/spec/unit/berkshelf/locations/path_spec.rb +40 -41
  125. data/spec/unit/berkshelf/lockfile_parser_spec.rb +71 -71
  126. data/spec/unit/berkshelf/lockfile_spec.rb +205 -211
  127. data/spec/unit/berkshelf/logger_spec.rb +3 -3
  128. data/spec/unit/berkshelf/mixin/logging_spec.rb +5 -5
  129. data/spec/unit/berkshelf/packager_spec.rb +2 -2
  130. data/spec/unit/berkshelf/resolver/graph_spec.rb +10 -8
  131. data/spec/unit/berkshelf/resolver_spec.rb +17 -17
  132. data/spec/unit/berkshelf/ridley_compat_spec.rb +16 -0
  133. data/spec/unit/berkshelf/shell_spec.rb +34 -34
  134. data/spec/unit/berkshelf/source_spec.rb +186 -20
  135. data/spec/unit/berkshelf/source_uri_spec.rb +1 -1
  136. data/spec/unit/berkshelf/ssl_policies_spec.rb +86 -0
  137. data/spec/unit/berkshelf/uploader_spec.rb +146 -64
  138. data/spec/unit/berkshelf/validator_spec.rb +23 -16
  139. data/spec/unit/berkshelf/visualizer_spec.rb +24 -15
  140. data/spec/unit/berkshelf_spec.rb +18 -18
  141. metadata +138 -289
  142. data/.gitignore +0 -29
  143. data/.travis.yml +0 -64
  144. data/CHANGELOG.legacy.md +0 -307
  145. data/CHANGELOG.md +0 -1358
  146. data/CONTRIBUTING.md +0 -64
  147. data/Gemfile.lock +0 -399
  148. data/Guardfile +0 -23
  149. data/PLUGINS.md +0 -25
  150. data/README.md +0 -70
  151. data/Thorfile +0 -61
  152. data/appveyor.yml +0 -31
  153. data/docs/berkshelf_for_newcomers.md +0 -65
  154. data/features/berksfile.feature +0 -46
  155. data/features/commands/apply.feature +0 -41
  156. data/features/commands/contingent.feature +0 -48
  157. data/features/commands/cookbook.feature +0 -35
  158. data/features/commands/info.feature +0 -99
  159. data/features/commands/init.feature +0 -27
  160. data/features/commands/install.feature +0 -636
  161. data/features/commands/list.feature +0 -78
  162. data/features/commands/outdated.feature +0 -130
  163. data/features/commands/package.feature +0 -17
  164. data/features/commands/search.feature +0 -17
  165. data/features/commands/shelf/list.feature +0 -32
  166. data/features/commands/shelf/show.feature +0 -143
  167. data/features/commands/shelf/uninstall.feature +0 -96
  168. data/features/commands/show.feature +0 -83
  169. data/features/commands/update.feature +0 -142
  170. data/features/commands/upload.feature +0 -426
  171. data/features/commands/vendor.feature +0 -111
  172. data/features/commands/verify.feature +0 -29
  173. data/features/commands/viz.feature +0 -66
  174. data/features/community_site.feature +0 -37
  175. data/features/config.feature +0 -111
  176. data/features/help.feature +0 -11
  177. data/features/json_formatter.feature +0 -161
  178. data/features/lifecycle.feature +0 -378
  179. data/features/lockfile.feature +0 -378
  180. data/features/step_definitions/berksfile_steps.rb +0 -39
  181. data/features/step_definitions/chef/config_steps.rb +0 -12
  182. data/features/step_definitions/chef_server_steps.rb +0 -60
  183. data/features/step_definitions/cli_steps.rb +0 -18
  184. data/features/step_definitions/config_steps.rb +0 -46
  185. data/features/step_definitions/environment_steps.rb +0 -7
  186. data/features/step_definitions/filesystem_steps.rb +0 -269
  187. data/features/step_definitions/gem_steps.rb +0 -13
  188. data/features/step_definitions/json_steps.rb +0 -23
  189. data/features/step_definitions/utility_steps.rb +0 -11
  190. data/features/support/aruba.rb +0 -12
  191. data/features/support/env.rb +0 -82
  192. data/generator_files/Berksfile.erb +0 -11
  193. data/generator_files/CHANGELOG.md.erb +0 -3
  194. data/generator_files/Gemfile.erb +0 -8
  195. data/generator_files/README.md.erb +0 -42
  196. data/generator_files/Thorfile.erb +0 -11
  197. data/generator_files/Vagrantfile.erb +0 -117
  198. data/generator_files/chefignore +0 -94
  199. data/generator_files/default_recipe.erb +0 -6
  200. data/generator_files/default_test.rb.erb +0 -11
  201. data/generator_files/gitignore.erb +0 -23
  202. data/generator_files/helpers.rb.erb +0 -7
  203. data/generator_files/licenses/apachev2.erb +0 -13
  204. data/generator_files/licenses/gplv2.erb +0 -15
  205. data/generator_files/licenses/gplv3.erb +0 -14
  206. data/generator_files/licenses/mit.erb +0 -20
  207. data/generator_files/licenses/reserved.erb +0 -3
  208. data/generator_files/metadata.rb.erb +0 -11
  209. data/lib/berkshelf/base_generator.rb +0 -43
  210. data/lib/berkshelf/commands/test_command.rb +0 -13
  211. data/lib/berkshelf/cookbook_generator.rb +0 -133
  212. data/lib/berkshelf/init_generator.rb +0 -195
  213. data/spec/fixtures/cookbooks/example_cookbook/.gitignore +0 -2
  214. data/spec/fixtures/cookbooks/example_cookbook/.kitchen.yml +0 -26
  215. data/spec/unit/berkshelf/cookbook_generator_spec.rb +0 -110
  216. data/spec/unit/berkshelf/init_generator_spec.rb +0 -263
@@ -1,4 +1,4 @@
1
- require 'fileutils'
1
+ require "fileutils" unless defined?(FileUtils)
2
2
 
3
3
  module FileUtils
4
4
  class << self
@@ -14,10 +14,10 @@ module FileUtils
14
14
  # symlink on Linux
15
15
  # @see {FileUtils::mv}
16
16
  def mv(src, dest, options = {})
17
- old_mv(src, dest, options)
17
+ old_mv(src, dest, **options)
18
18
  rescue Errno::EACCES, Errno::ENOENT
19
- options.delete(:force) if options.has_key?(:force)
20
- FileUtils.cp_r(src, dest, options)
19
+ options.delete(:force) if options.key?(:force)
20
+ FileUtils.cp_r(src, dest, **options)
21
21
  FileUtils.rm_rf(src)
22
22
  end
23
23
  end
@@ -1,3 +1,3 @@
1
1
  Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].sort.each do |path|
2
- require_relative "core_ext/#{File.basename(path, '.rb')}"
2
+ require_relative "core_ext/#{File.basename(path, ".rb")}"
3
3
  end
@@ -22,7 +22,7 @@ module Berkshelf
22
22
  # @return [String]
23
23
  attr_reader :name
24
24
  # @return [Array<String,Symbol>]
25
- attr_reader :groups
25
+ attr_writer :groups
26
26
  # @return [Berkshelf::Location]
27
27
  attr_reader :location
28
28
  # @return [Semverse::Version]
@@ -122,23 +122,24 @@ module Berkshelf
122
122
  def cached_cookbook
123
123
  return @cached_cookbook if @cached_cookbook
124
124
 
125
- @cached_cookbook = if location
126
- cookbook = location.cached_cookbook
125
+ @cached_cookbook =
126
+ if location
127
+ cookbook = location.cached_cookbook
127
128
 
128
- # If we have a cached cookbook, tighten our constraints
129
- if cookbook
130
- self.locked_version = cookbook.version
131
- self.version_constraint = cookbook.version
132
- end
129
+ # If we have a cached cookbook, tighten our constraints
130
+ if cookbook
131
+ self.locked_version = cookbook.version
132
+ self.version_constraint = cookbook.version
133
+ end
133
134
 
134
- cookbook
135
- else
136
- if locked_version
137
- CookbookStore.instance.cookbook(name, locked_version)
135
+ cookbook
138
136
  else
139
- CookbookStore.instance.satisfy(name, version_constraint)
137
+ if locked_version
138
+ CookbookStore.instance.cookbook(name, locked_version)
139
+ else
140
+ CookbookStore.instance.satisfy(name, version_constraint)
141
+ end
140
142
  end
141
- end
142
143
 
143
144
  @cached_cookbook
144
145
  end
@@ -150,15 +151,6 @@ module Berkshelf
150
151
  groups.include?(group.to_sym)
151
152
  end
152
153
 
153
- # The location for this dependency, such as a remote Chef Server, the
154
- # community API, :git, or a :path location. By default, this will be the
155
- # community API.
156
- #
157
- # @return [Berkshelf::Location]
158
- def location
159
- @location
160
- end
161
-
162
154
  # The list of groups this dependency belongs to.
163
155
  #
164
156
  # @return [Array<Symbol>]
@@ -167,7 +159,7 @@ module Berkshelf
167
159
  end
168
160
 
169
161
  def <=>(other)
170
- [self.name, self.version_constraint] <=> [other.name, other.version_constraint]
162
+ [name, version_constraint] <=> [other.name, other.version_constraint]
171
163
  end
172
164
 
173
165
  def to_s
@@ -175,20 +167,21 @@ module Berkshelf
175
167
  end
176
168
 
177
169
  def inspect
178
- '#<Berkshelf::Dependency: ' << [
170
+ "#<Berkshelf::Dependency: " << [
179
171
  "#{name} (#{version_constraint})",
180
172
  "locked_version: #{locked_version.inspect}",
181
173
  "groups: #{groups}",
182
- "location: #{location || 'default'}>"
183
- ].join(', ')
174
+ "location: #{location || "default"}>",
175
+ ].join(", ")
184
176
  end
185
177
 
186
178
  def to_lock
187
- out = if location || version_constraint.to_s == '>= 0.0.0'
188
- " #{name}\n"
189
- else
190
- " #{name} (#{version_constraint})\n"
191
- end
179
+ out =
180
+ if location || version_constraint.to_s == ">= 0.0.0"
181
+ " #{name}\n"
182
+ else
183
+ " #{name} (#{version_constraint})\n"
184
+ end
192
185
 
193
186
  out << location.to_lock if location
194
187
  out
@@ -1,5 +1,7 @@
1
- require 'net/http'
2
- require 'mixlib/archive'
1
+ require "net/http" unless defined?(Net::HTTP)
2
+ require "mixlib/archive" unless defined?(Mixlib::Archive)
3
+ require_relative "ssl_policies"
4
+ require "faraday" unless defined?(Faraday)
3
5
 
4
6
  module Berkshelf
5
7
  class Downloader
@@ -14,6 +16,10 @@ module Berkshelf
14
16
  @berksfile = berksfile
15
17
  end
16
18
 
19
+ def ssl_policy
20
+ @ssl_policy ||= SSLPolicy.new
21
+ end
22
+
17
23
  # Download the given Berkshelf::Dependency. If the optional block is given,
18
24
  # the temporary path to the cookbook is yielded and automatically deleted
19
25
  # when the block returns. If no block is given, it is the responsibility of
@@ -28,11 +34,12 @@ module Berkshelf
28
34
  #
29
35
  # @return [String]
30
36
  def download(*args, &block)
31
- options = args.last.is_a?(Hash) ? args.pop : Hash.new
37
+ # options are ignored
38
+ # options = args.last.is_a?(Hash) ? args.pop : Hash.new
32
39
  dependency, version = args
33
40
 
34
41
  sources.each do |source|
35
- if result = try_download(source, dependency, version)
42
+ if ( result = try_download(source, dependency, version) )
36
43
  if block_given?
37
44
  value = yield result
38
45
  FileUtils.rm_rf(result)
@@ -43,7 +50,7 @@ module Berkshelf
43
50
  end
44
51
  end
45
52
 
46
- raise CookbookNotFound.new(dependency, version, 'in any of the sources')
53
+ raise CookbookNotFound.new(dependency, version, "in any of the sources")
47
54
  end
48
55
 
49
56
  # @param [Berkshelf::Source] source
@@ -52,27 +59,46 @@ module Berkshelf
52
59
  #
53
60
  # @return [String]
54
61
  def try_download(source, name, version)
55
- unless remote_cookbook = source.cookbook(name, version)
62
+ unless ( remote_cookbook = source.cookbook(name, version) )
56
63
  return nil
57
64
  end
58
65
 
59
66
  case remote_cookbook.location_type
60
67
  when :opscode, :supermarket
61
- CommunityREST.new(remote_cookbook.location_path).download(name, version)
68
+ options = { ssl: source.options[:ssl] }
69
+ if source.type == :artifactory
70
+ options[:headers] = { "X-Jfrog-Art-Api" => source.options[:api_key] }
71
+ end
72
+
73
+ # Allow Berkshelf install to function if a relative url exists in location_path
74
+ path = URI.parse(remote_cookbook.location_path).absolute? ? remote_cookbook.location_path : "#{source.uri_string}#{remote_cookbook.location_path}"
75
+
76
+ CommunityREST.new(path, options).download(name, version)
62
77
  when :chef_server
78
+ tmp_dir = Dir.mktmpdir
79
+ unpack_dir = Pathname.new(tmp_dir) + "#{name}-#{version}"
63
80
  # @todo Dynamically get credentials for remote_cookbook.location_path
64
81
  credentials = {
65
82
  server_url: remote_cookbook.location_path,
66
- client_name: Berkshelf::Config.instance.chef.node_name,
67
- client_key: Berkshelf::Config.instance.chef.client_key,
68
- ssl: Berkshelf::Config.instance.ssl
83
+ client_name: source.options[:client_name] || Berkshelf::Config.instance.chef.node_name,
84
+ client_key: source.options[:client_key] || Berkshelf::Config.instance.chef.client_key,
85
+ ssl: source.options[:ssl],
69
86
  }
70
- # @todo Something scary going on here - getting an instance of Kitchen::Logger from test-kitchen
71
- # https://github.com/opscode/test-kitchen/blob/master/lib/kitchen.rb#L99
72
- Celluloid.logger = nil unless ENV["DEBUG_CELLULOID"]
73
- Ridley.open(credentials) { |r| r.cookbook.download(name, version) }
87
+ RidleyCompat.new_client(**credentials) do |conn|
88
+ cookbook = Chef::CookbookVersion.load(name, version)
89
+ manifest = cookbook.cookbook_manifest
90
+ manifest.by_parent_directory.each do |segment, files|
91
+ files.each do |segment_file|
92
+ dest = File.join(unpack_dir, segment_file["path"].gsub("/", File::SEPARATOR))
93
+ FileUtils.mkdir_p(File.dirname(dest))
94
+ tempfile = conn.streaming_request(segment_file["url"])
95
+ FileUtils.mv(tempfile.path, dest)
96
+ end
97
+ end
98
+ end
99
+ unpack_dir
74
100
  when :github
75
- Thread.exclusive { require 'octokit' unless defined?(Octokit) }
101
+ require "octokit"
76
102
 
77
103
  tmp_dir = Dir.mktmpdir
78
104
  archive_path = File.join(tmp_dir, "#{name}-#{version}.tar.gz")
@@ -81,19 +107,21 @@ module Berkshelf
81
107
  # Find the correct github connection options for this specific cookbook.
82
108
  cookbook_uri = URI.parse(remote_cookbook.location_path)
83
109
  if cookbook_uri.host == "github.com"
84
- options = Berkshelf::Config.instance.github.detect { |opts| opts["web_endpoint"] == nil }
85
- options = {} if options == nil
110
+ options = Berkshelf::Config.instance.github.detect { |opts| opts["web_endpoint"].nil? }
111
+ options = {} if options.nil?
86
112
  else
87
113
  options = Berkshelf::Config.instance.github.detect { |opts| opts["web_endpoint"] == "#{cookbook_uri.scheme}://#{cookbook_uri.host}" }
88
- raise ConfigurationError.new "Missing github endpoint configuration for #{cookbook_uri.scheme}://#{cookbook_uri.host}" if options == nil
114
+ raise ConfigurationError.new "Missing github endpoint configuration for #{cookbook_uri.scheme}://#{cookbook_uri.host}" if options.nil?
89
115
  end
90
116
 
91
- github_client = Octokit::Client.new(access_token: options[:access_token],
92
- api_endpoint: options[:api_endpoint], web_endpoint: options[:web_endpoint],
93
- connection_options: {ssl: {verify: options[:ssl_verify].nil? ? true : options[:ssl_verify]}})
117
+ github_client = Octokit::Client.new(
118
+ access_token: options["access_token"],
119
+ api_endpoint: options["api_endpoint"], web_endpoint: options["web_endpoint"],
120
+ connection_options: { ssl: { verify: options["ssl_verify"].nil? ? true : options["ssl_verify"] } }
121
+ )
94
122
 
95
123
  begin
96
- url = URI(github_client.archive_link(cookbook_uri.path.gsub(/^\//, ""), ref: "v#{version}"))
124
+ url = URI(github_client.archive_link(cookbook_uri.path.gsub(%r{^/}, ""), ref: "v#{version}"))
97
125
  rescue Octokit::Unauthorized
98
126
  return nil
99
127
  end
@@ -101,9 +129,10 @@ module Berkshelf
101
129
  # We use Net::HTTP.new and then get here, because Net::HTTP.get does not support proxy settings.
102
130
  http = Net::HTTP.new(url.host, url.port)
103
131
  http.use_ssl = url.scheme == "https"
104
- http.verify_mode = (options[:ssl_verify].nil? || options[:ssl_verify]) ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
132
+ http.verify_mode = (options["ssl_verify"].nil? || options["ssl_verify"]) ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
105
133
  resp = http.get(url.request_uri)
106
134
  return nil unless resp.is_a?(Net::HTTPSuccess)
135
+
107
136
  open(archive_path, "wb") { |file| file.write(resp.body) }
108
137
 
109
138
  Mixlib::Archive.new(archive_path).extract(unpack_dir)
@@ -111,20 +140,20 @@ module Berkshelf
111
140
  # we need to figure out where the cookbook is located in the archive. This is because the directory name
112
141
  # pattern is not cosistant between private and public github repositories
113
142
  cookbook_directory = Dir.entries(unpack_dir).select do |f|
114
- (! f.start_with?('.')) && (Pathname.new(File.join(unpack_dir, f)).cookbook?)
143
+ (! f.start_with?(".")) && (Pathname.new(File.join(unpack_dir, f)).cookbook?)
115
144
  end[0]
116
145
 
117
146
  File.join(unpack_dir, cookbook_directory)
118
147
  when :uri
119
- Thread.exclusive { require 'open-uri' unless defined?(OpenURI) }
148
+ require "open-uri" unless defined?(OpenURI)
120
149
 
121
150
  tmp_dir = Dir.mktmpdir
122
151
  archive_path = Pathname.new(tmp_dir) + "#{name}-#{version}.tar.gz"
123
152
  unpack_dir = Pathname.new(tmp_dir) + "#{name}-#{version}"
124
153
 
125
154
  url = remote_cookbook.location_path
126
- open(url, 'rb') do |remote_file|
127
- archive_path.open('wb') { |local_file| local_file.write remote_file.read }
155
+ URI.open(url, "rb") do |remote_file|
156
+ archive_path.open("wb") { |local_file| local_file.write remote_file.read }
128
157
  end
129
158
 
130
159
  Mixlib::Archive.new(archive_path).extract(unpack_dir)
@@ -132,13 +161,11 @@ module Berkshelf
132
161
  # The top level directory is inconsistant. So we unpack it and
133
162
  # use the only directory created in the unpack_dir.
134
163
  cookbook_directory = unpack_dir.entries.select do |filename|
135
- (! filename.to_s.start_with?('.')) && (unpack_dir + filename).cookbook?
164
+ (! filename.to_s.start_with?(".")) && (unpack_dir + filename).cookbook?
136
165
  end.first
137
166
 
138
167
  (unpack_dir + cookbook_directory).to_s
139
168
  when :gitlab
140
- #Thread.exclusive { require 'octokit' unless defined?(Octokit) }
141
-
142
169
  tmp_dir = Dir.mktmpdir
143
170
  archive_path = Pathname.new(tmp_dir) + "#{name}-#{version}.tar.gz"
144
171
  unpack_dir = Pathname.new(tmp_dir) + "#{name}-#{version}"
@@ -147,26 +174,26 @@ module Berkshelf
147
174
  cookbook_uri = URI.parse(remote_cookbook.location_path)
148
175
  if cookbook_uri.host
149
176
  options = Berkshelf::Config.instance.gitlab.detect { |opts| opts["web_endpoint"] == "#{cookbook_uri.scheme}://#{cookbook_uri.host}" }
150
- raise ConfigurationError.new "Missing github endpoint configuration for #{cookbook_uri.scheme}://#{cookbook_uri.host}" if options == nil
177
+ raise ConfigurationError.new "Missing github endpoint configuration for #{cookbook_uri.scheme}://#{cookbook_uri.host}" if options.nil?
151
178
  end
152
179
 
153
- connection ||= Faraday.new(url: options[:web_endpoint]) do |faraday|
154
- faraday.headers[:accept] = 'application/x-tar'
180
+ connection ||= Faraday.new(url: options["web_endpoint"]) do |faraday|
181
+ faraday.headers[:accept] = "application/x-tar"
155
182
  faraday.response :logger, @logger unless @logger.nil?
156
- faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
183
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
157
184
  end
158
185
 
159
- resp = connection.get(cookbook_uri.request_uri + '&private_token=' + options[:private_token])
186
+ resp = connection.get(cookbook_uri.request_uri + "&private_token=" + options["private_token"])
160
187
  return nil unless resp.status == 200
188
+
161
189
  open(archive_path, "wb") { |file| file.write(resp.body) }
162
190
 
163
- tgz = Zlib::GzipReader.new(File.open(archive_path, "rb"))
164
- Archive::Tar::Minitar.unpack(tgz, unpack_dir)
191
+ Mixlib::Archive.new(archive_path).extract(unpack_dir)
165
192
 
166
193
  # The top level directory is inconsistant. So we unpack it and
167
194
  # use the only directory created in the unpack_dir.
168
195
  cookbook_directory = unpack_dir.entries.select do |filename|
169
- (! filename.to_s.start_with?('.')) && (unpack_dir + filename).cookbook?
196
+ (! filename.to_s.start_with?(".")) && (unpack_dir + filename).cookbook?
170
197
  end.first
171
198
 
172
199
  (unpack_dir + cookbook_directory).to_s
@@ -175,7 +202,7 @@ module Berkshelf
175
202
  FileUtils.cp_r(remote_cookbook.location_path, tmp_dir)
176
203
  File.join(tmp_dir, name)
177
204
  else
178
- raise RuntimeError, "unknown location type #{remote_cookbook.location_type}"
205
+ raise "unknown location type #{remote_cookbook.location_type}"
179
206
  end
180
207
  rescue CookbookNotFound
181
208
  nil
@@ -61,7 +61,7 @@ module Berkshelf
61
61
  end
62
62
 
63
63
  def to_s
64
- out = "Your Berksfile contains multiple entries named "
64
+ out = "Your Berksfile contains multiple entries named "
65
65
  out << "'#{@name}'. Please remove duplicate dependencies, or put them in "
66
66
  out << "different groups."
67
67
  out
@@ -83,7 +83,7 @@ module Berkshelf
83
83
 
84
84
  def to_s
85
85
  @original_exception.to_s +
86
- "Unable to find a solution for demands: #{demands.join(', ')}"
86
+ "Unable to find a solution for demands: #{demands.join(", ")}"
87
87
  end
88
88
 
89
89
  alias_method :message, :to_s
@@ -91,6 +91,7 @@ module Berkshelf
91
91
 
92
92
  class CookbookSyntaxError < BerkshelfError; set_status_code(107); end
93
93
  class ConstraintNotSatisfied < BerkshelfError; set_status_code(111); end
94
+
94
95
  class BerksfileReadError < BerkshelfError
95
96
  set_status_code(113)
96
97
 
@@ -254,6 +255,7 @@ module Berkshelf
254
255
  end
255
256
 
256
257
  class UploadFailure < BerkshelfError; end
258
+
257
259
  class FrozenCookbook < UploadFailure
258
260
  set_status_code(126)
259
261
 
@@ -285,11 +287,11 @@ module Berkshelf
285
287
 
286
288
  def to_s
287
289
  "Berkshelf could not find compatible versions for cookbook '#{@dependency.name}':\n" +
288
- " In Berksfile:\n" +
289
- " #{@dependency.name} (#{@dependency.version_constraint})\n\n" +
290
- " In Berksfile.lock:\n" +
291
- " #{@locked.name} (#{@locked.version})\n\n" +
292
- "Try running `berks update #{@dependency.name}`, which will try to find '#{@dependency.name}' matching " +
290
+ " In Berksfile:\n" +
291
+ " #{@dependency.name} (#{@dependency.version_constraint})\n\n" +
292
+ " In Berksfile.lock:\n" +
293
+ " #{@locked.name} (#{@locked.version})\n\n" +
294
+ "Try running `berks update #{@dependency.name}`, which will try to find '#{@dependency.name}' matching " +
293
295
  "'#{@dependency.version_constraint}'."
294
296
  end
295
297
 
@@ -314,7 +316,7 @@ module Berkshelf
314
316
  set_status_code(130)
315
317
 
316
318
  def to_s
317
- 'There was an error connecting to the Chef Server'
319
+ "There was an error connecting to the Chef Server"
318
320
  end
319
321
  end
320
322
 
@@ -372,7 +374,7 @@ module Berkshelf
372
374
 
373
375
  def to_s
374
376
  "Unknown license: '#{license}'\n" +
375
- "Available licenses: #{CookbookGenerator::LICENSES.join(', ')}"
377
+ "Available licenses: #{CookbookGenerator::LICENSES.join(", ")}"
376
378
  end
377
379
 
378
380
  alias_method :message, :to_s
@@ -436,11 +438,12 @@ module Berkshelf
436
438
  end
437
439
 
438
440
  class DuplicateDemand < BerkshelfError; set_status_code(138); end
441
+
439
442
  class LockfileNotFound < BerkshelfError
440
443
  set_status_code(140)
441
444
 
442
445
  def to_s
443
- 'Lockfile not found! Run `berks install` to create the lockfile.'
446
+ "Lockfile not found! Run `berks install` to create the lockfile."
444
447
  end
445
448
  end
446
449
 
@@ -467,7 +470,7 @@ module Berkshelf
467
470
  set_status_code(144)
468
471
 
469
472
  def to_s
470
- 'The lockfile is out of sync! Run `berks install` to sync the lockfile.'
473
+ "The lockfile is out of sync! Run `berks install` to sync the lockfile."
471
474
  end
472
475
  end
473
476
 
@@ -527,6 +530,9 @@ module Berkshelf
527
530
  alias_method :message, :to_s
528
531
  end
529
532
 
533
+ class CookbookSyntaxError < BerkshelfError; end
534
+ class RedirectLimitReached < BerkshelfError; end
535
+
530
536
  class MissingLockfileCookbookVersion < CookbookNotFound
531
537
  set_status_code(149)
532
538
 
@@ -544,7 +550,7 @@ module Berkshelf
544
550
  def intialize(environment_file)
545
551
  @environment_file = environment_file
546
552
  end
547
-
553
+
548
554
  def to_s
549
555
  "Could not find environment file #{@environment_file}"
550
556
  end
@@ -556,11 +562,11 @@ module Berkshelf
556
562
 
557
563
  class GitNotInstalled < GitError
558
564
  def initialize
559
- super 'You need to install Git before you can download ' \
560
- 'cookbooks from git repositories. For more information, please ' \
561
- 'see the Git docs: http://git-scm.org. If you have git installed, ' \
562
- 'please make sure it is in your $PATH and accessible by the user ' \
563
- 'running this command.'
565
+ super "You need to install Git before you can download " \
566
+ "cookbooks from git repositories. For more information, please " \
567
+ "see the Git docs: http://git-scm.org. If you have git installed, " \
568
+ "please make sure it is in your $PATH and accessible by the user " \
569
+ "running this command."
564
570
  end
565
571
  end
566
572
 
@@ -1,11 +1,11 @@
1
- require 'fileutils'
1
+ require "fileutils" unless defined?(FileUtils)
2
2
 
3
3
  module Berkshelf
4
4
  module FileSyncer
5
5
  extend self
6
6
 
7
7
  # Files to be ignored during a directory globbing
8
- IGNORED_FILES = %w(. ..).freeze
8
+ IGNORED_FILES = %w{. ..}.freeze
9
9
 
10
10
  #
11
11
  # Glob across the given pattern, accounting for dotfiles, removing Ruby's
@@ -17,8 +17,15 @@ module Berkshelf
17
17
  # @return [Array<String>]
18
18
  # the list of all files
19
19
  #
20
- def glob(pattern)
21
- Dir.glob(pattern, File::FNM_DOTMATCH).sort.reject do |file|
20
+ # @note
21
+ # Globbing on windows is strange. Do not pass a path that contains
22
+ # "symlinked" directories. Dir.glob will not see them. As an example,
23
+ # 'C:\Documents and Settings' is not a real directory and int recent
24
+ # versions of windows points at 'C:\users'. Some users have their
25
+ # temp directory still referring to 'C:\Documents and Settings'.
26
+ #
27
+ def glob(pattern, **kwargs)
28
+ Dir.glob(pattern, File::FNM_DOTMATCH, **kwargs).sort.reject do |file|
22
29
  basename = File.basename(file)
23
30
  IGNORED_FILES.include?(basename)
24
31
  end
@@ -58,24 +65,17 @@ module Berkshelf
58
65
  [exclude, "#{exclude}/*"]
59
66
  end.flatten
60
67
 
61
- # let glob expand the source directory in case it is an abbreviated windows
62
- # user directory: C:/Users/MATTWR~1/AppData/Local/Temp
63
- # so that it matches the parent of source_files
64
- source = glob(source).first
65
-
66
- source_files = glob(File.join(source, '**/*'))
67
- source_files = source_files.reject do |source_file|
68
- basename = relative_path_for(source_file, source)
69
- excludes.any? { |exclude| File.fnmatch?(exclude, basename, File::FNM_DOTMATCH) }
70
- end
68
+ source_files =
69
+ glob("**/*", base: source).reject do |source_file|
70
+ excludes.any? { |exclude| File.fnmatch?(exclude, source_file, File::FNM_DOTMATCH) }
71
+ end
71
72
 
72
73
  # Ensure the destination directory exists
73
74
  FileUtils.mkdir_p(destination) unless File.directory?(destination)
74
75
 
75
76
  # Copy over the filtered source files
76
- source_files.each do |source_file|
77
- relative_path = relative_path_for(source_file, source)
78
-
77
+ source_files.each do |relative_path|
78
+ source_file = File.join(source, relative_path)
79
79
  # Create the parent directory
80
80
  parent = File.join(destination, File.dirname(relative_path))
81
81
  FileUtils.mkdir_p(parent) unless File.directory?(parent)
@@ -87,14 +87,15 @@ module Berkshelf
87
87
  target = File.readlink(source_file)
88
88
 
89
89
  destination = File.expand_path(destination)
90
- Dir.chdir(destination) do
91
- FileUtils.ln_sf(target, "#{destination}/#{relative_path}")
92
- end
90
+ FileUtils.ln_sf(target, "#{destination}/#{relative_path}")
93
91
  when :file
92
+ # TODO: Workaround issue related to [1] which impacts running ChefSpec on Github Actions
93
+ # [1] https://github.com/docker/for-linux/issues/1015
94
+ FileUtils.touch(source_file)
94
95
  FileUtils.cp(source_file, "#{destination}/#{relative_path}")
95
96
  else
96
97
  type = File.ftype(source_file)
97
- raise RuntimeError, "Unknown file type: `#{type}' at " \
98
+ raise "Unknown file type: `#{type}' at " \
98
99
  "`#{source_file}'. Failed to sync `#{source_file}' to " \
99
100
  "`#{destination}/#{relative_path}'!"
100
101
  end
@@ -102,20 +103,11 @@ module Berkshelf
102
103
 
103
104
  if options[:delete]
104
105
  # Remove any files in the destination that are not in the source files
105
- destination_files = glob("#{destination}/**/*")
106
-
107
- # Calculate the relative paths of files so we can compare to the
108
- # source.
109
- relative_source_files = source_files.map do |file|
110
- relative_path_for(file, source)
111
- end
112
- relative_destination_files = destination_files.map do |file|
113
- relative_path_for(file, destination)
114
- end
106
+ destination_files = glob("**/*", base: destination)
115
107
 
116
108
  # Remove any extra files that are present in the destination, but are
117
109
  # not in the source list
118
- extra_files = relative_destination_files - relative_source_files
110
+ extra_files = destination_files - source_files
119
111
  extra_files.each do |file|
120
112
  FileUtils.rm_rf(File.join(destination, file))
121
113
  end
@@ -123,20 +115,5 @@ module Berkshelf
123
115
 
124
116
  true
125
117
  end
126
-
127
- private
128
- #
129
- # The relative path of the given +path+ to the +parent+.
130
- #
131
- # @param [String] path
132
- # the path to get relative with
133
- # @param [String] parent
134
- # the parent where the path is contained (hopefully)
135
- #
136
- # @return [String]
137
- #
138
- def relative_path_for(path, parent)
139
- Pathname.new(path).relative_path_from(Pathname.new(parent)).to_s
140
- end
141
118
  end
142
119
  end
@@ -19,7 +19,9 @@ module Berkshelf
19
19
  def install(source, cookbook)
20
20
  message = "Installing #{cookbook.name} (#{cookbook.version})"
21
21
 
22
- unless source.default?
22
+ if source.type == :chef_repo
23
+ message << " from #{cookbook.location_path}"
24
+ elsif !source.default?
23
25
  message << " from #{source}"
24
26
  message << " ([#{cookbook.location_type}] #{cookbook.location_path})"
25
27
  end
@@ -60,13 +62,13 @@ module Berkshelf
60
62
  # { 'cookbook' => { 'supermarket.chef.io' => #<Cookbook> } }
61
63
  def outdated(hash)
62
64
  if hash.empty?
63
- Berkshelf.ui.info('All cookbooks up to date!')
65
+ Berkshelf.ui.info("All cookbooks up to date!")
64
66
  else
65
- Berkshelf.ui.info('The following cookbooks have newer versions:')
67
+ Berkshelf.ui.info("The following cookbooks have newer versions:")
66
68
 
67
69
  hash.each do |name, info|
68
- info['remote'].each do |remote_source, remote_version|
69
- out = " * #{name} (#{info['local']} => #{remote_version})"
70
+ info["remote"].each do |remote_source, remote_version|
71
+ out = " * #{name} (#{info["local"]} => #{remote_version})"
70
72
 
71
73
  unless remote_source.default?
72
74
  out << " [#{remote_source.uri}]"
@@ -8,11 +8,11 @@ module Berkshelf
8
8
  def initialize
9
9
  @output = {
10
10
  cookbooks: [],
11
- errors: [],
12
- messages: [],
13
- warnings: [],
11
+ errors: [],
12
+ messages: [],
13
+ warnings: [],
14
14
  }
15
- @cookbooks = Hash.new
15
+ @cookbooks = {}
16
16
 
17
17
  Berkshelf.ui.mute { super }
18
18
  end
@@ -92,11 +92,11 @@ module Berkshelf
92
92
  # { 'cookbook' => { 'supermarket.chef.io' => #<Cookbook> } }
93
93
  def outdated(hash)
94
94
  hash.each do |name, info|
95
- info['remote'].each do |remote_source, remote_version|
95
+ info["remote"].each do |remote_source, remote_version|
96
96
  source = remote_source.uri.to_s
97
97
 
98
98
  cookbooks[name] ||= {}
99
- cookbooks[name][:local] = info['local'].to_s
99
+ cookbooks[name][:local] = info["local"].to_s
100
100
  cookbooks[name][:remote] ||= {}
101
101
  cookbooks[name][:remote][source] = remote_version.to_s
102
102
  end