cheffish 14.0.13 → 16.0.8

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -9
  3. data/Rakefile +1 -1
  4. data/cheffish.gemspec +3 -3
  5. data/lib/chef/resource/chef_acl.rb +17 -14
  6. data/lib/chef/resource/chef_client.rb +3 -3
  7. data/lib/chef/resource/chef_container.rb +4 -4
  8. data/lib/chef/resource/chef_data_bag.rb +3 -3
  9. data/lib/chef/resource/chef_data_bag_item.rb +13 -12
  10. data/lib/chef/resource/chef_environment.rb +2 -2
  11. data/lib/chef/resource/chef_group.rb +2 -2
  12. data/lib/chef/resource/chef_mirror.rb +6 -5
  13. data/lib/chef/resource/chef_node.rb +2 -2
  14. data/lib/chef/resource/chef_organization.rb +3 -3
  15. data/lib/chef/resource/chef_resolved_cookbooks.rb +5 -3
  16. data/lib/chef/resource/chef_role.rb +6 -2
  17. data/lib/chef/resource/chef_user.rb +2 -2
  18. data/lib/chef/resource/private_key.rb +11 -11
  19. data/lib/chef/resource/public_key.rb +5 -4
  20. data/lib/cheffish.rb +1 -0
  21. data/lib/cheffish/base_resource.rb +13 -11
  22. data/lib/cheffish/basic_chef_client.rb +4 -5
  23. data/lib/cheffish/chef_actor_base.rb +3 -2
  24. data/lib/cheffish/chef_run.rb +5 -6
  25. data/lib/cheffish/chef_run_listener.rb +1 -3
  26. data/lib/cheffish/key_formatter.rb +5 -13
  27. data/lib/cheffish/merged_config.rb +2 -2
  28. data/lib/cheffish/node_properties.rb +7 -3
  29. data/lib/cheffish/recipe_dsl.rb +2 -2
  30. data/lib/cheffish/rspec/chef_run_support.rb +2 -2
  31. data/lib/cheffish/rspec/matchers/have_updated.rb +5 -5
  32. data/lib/cheffish/rspec/recipe_run_wrapper.rb +2 -2
  33. data/lib/cheffish/rspec/repository_support.rb +1 -0
  34. data/lib/cheffish/version.rb +1 -1
  35. data/spec/functional/fingerprint_spec.rb +8 -6
  36. data/spec/integration/chef_acl_spec.rb +28 -20
  37. data/spec/integration/chef_group_spec.rb +2 -2
  38. data/spec/integration/chef_node_spec.rb +2 -2
  39. data/spec/integration/chef_role_spec.rb +2 -2
  40. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fa7eb898e80ca43f014fe27f3366f6275a3b6e2ebbc1be28eb49085d492dfb0
4
- data.tar.gz: b34eb3387c508db86d2aa31007462db83245f921cebe65e6e4a84203f5d49d97
3
+ metadata.gz: 2680862bc4ccaf4bb8516f6242dc1fe04afc77592d215ed897a7dcc4f925fa63
4
+ data.tar.gz: 710ca780d8975283f9a1e202e3055257af74238624a97ba3d6bc6c536d4f88aa
5
5
  SHA512:
6
- metadata.gz: 307bc86092ac438c549016bfdc11197208cdf632e7e27cae0a69bf671d6053ad420eb87fe377807c203d078818018df343eb3a960109eff9becae451de300165
7
- data.tar.gz: 0db75dca4ffd1ee075afcdceac2bb4b0f5d59a3685f51b022e62a8026bbf3316f262a5a650436602175aad60dd6c72ae3cd6084df2023e2df3bd745528c5d2ee
6
+ metadata.gz: b041113f8da4686453be3d9c84fa5dd205feb519fa5e2f3538252bedc18e4701f226452e24ca748d1905958039e8b4606b883b3e9c8ac05439f981b047ca5802
7
+ data.tar.gz: ab1425571b89f8fbe8bad89e4d4cdcbe617548c2adb2dd750242855810fbdb3bfcd350b99a66741aac785a2122f0deb4b8fbf280315b5e356577533ce1b7acec
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "master"
6
+ gem "chefstyle", "1.2.1"
7
7
  gem "rake"
8
8
  gem "rspec", "~> 3.0"
9
9
  end
@@ -14,8 +14,8 @@ if ENV["GEMFILE_MOD"]
14
14
  instance_eval(ENV["GEMFILE_MOD"])
15
15
  else
16
16
  group :development do
17
- gem "chef", "~> 14"
18
- gem "ohai", "~> 14"
17
+ gem "chef", "~> 16"
18
+ gem "ohai", "~> 16"
19
19
  end
20
20
  end
21
21
 
@@ -31,9 +31,3 @@ group :debug do
31
31
  gem "pry-stack_explorer"
32
32
  gem "rb-readline"
33
33
  end
34
-
35
- instance_eval(ENV["GEMFILE_MOD"]) if ENV["GEMFILE_MOD"]
36
-
37
- # If you want to load debugging tools into the bundle exec sandbox,
38
- # add these additional dependencies into Gemfile.local
39
- eval_gemfile(__FILE__ + ".local") if File.exist?(__FILE__ + ".local")
data/Rakefile CHANGED
@@ -39,4 +39,4 @@ task :console do
39
39
  IRB.start
40
40
  end
41
41
 
42
- task default: [:style, :spec]
42
+ task default: %i{style spec}
@@ -6,15 +6,15 @@ Gem::Specification.new do |s|
6
6
  s.version = Cheffish::VERSION
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.license = "Apache-2.0"
9
- s.summary = "A set of Chef resources for configuring Chef."
9
+ s.summary = "A set of Chef resources for configuring Chef Infra."
10
10
  s.description = s.summary
11
11
  s.author = "Chef Software Inc."
12
12
  s.email = "oss@chef.io"
13
13
  s.homepage = "https://github.com/chef/cheffish"
14
14
 
15
- s.required_ruby_version = ">= 2.4.0"
15
+ s.required_ruby_version = ">= 2.6.0"
16
16
 
17
- s.add_dependency "chef-zero", "~> 14.0"
17
+ s.add_dependency "chef-zero", ">= 14.0"
18
18
  s.add_dependency "net-ssh"
19
19
 
20
20
  s.bindir = "bin"
@@ -2,12 +2,12 @@ require_relative "../../cheffish"
2
2
  require_relative "../../cheffish/base_resource"
3
3
  require "chef/chef_fs/data_handler/acl_data_handler"
4
4
  require "chef/chef_fs/parallelizer"
5
- require "uri"
5
+ require "uri" unless defined?(URI)
6
6
 
7
7
  class Chef
8
8
  class Resource
9
9
  class ChefAcl < Cheffish::BaseResource
10
- resource_name :chef_acl
10
+ provides :chef_acl
11
11
 
12
12
  # Path of the thing being secured, e.g. nodes, nodes/*, nodes/mynode,
13
13
  # */*, **, roles/base, data/secrets, cookbooks/apache2, /users/*,
@@ -75,7 +75,7 @@ class Chef
75
75
  end
76
76
  end
77
77
 
78
- action_class.class_eval do
78
+ action_class do
79
79
  # Update the ACL if necessary.
80
80
  def create_acl(path)
81
81
  changed = false
@@ -99,6 +99,7 @@ class Chef
99
99
  # NOTE: if superusers exist, this should turn into a warning.
100
100
  raise "chef_acl attempted to remove all actors from GRANT! I'm sorry Dave, I can't let you remove access to an object with no hope of recovery."
101
101
  end
102
+
102
103
  modify[differences] ||= {}
103
104
  modify[differences][permission] = desired_json
104
105
  end
@@ -107,7 +108,7 @@ class Chef
107
108
  if modify.size > 0
108
109
  changed = true
109
110
  description = [ "update acl #{path} at #{rest_url(path)}" ] + modify.flat_map do |diffs, permissions|
110
- diffs.map { |diff| " #{permissions.keys.join(', ')}:#{diff}" }
111
+ diffs.map { |diff| " #{permissions.keys.join(", ")}:#{diff}" }
111
112
  end
112
113
  converge_by description do
113
114
  modify.values.each do |permissions|
@@ -127,11 +128,13 @@ class Chef
127
128
  children, _error = list(path, "*")
128
129
  Chef::ChefFS::Parallelizer.parallel_do(children) do |child|
129
130
  next if child.split("/")[-1] == "containers"
131
+
130
132
  create_acl(child)
131
133
  end
132
134
  # containers mess up our descent, so we do them last
133
135
  Chef::ChefFS::Parallelizer.parallel_do(children) do |child|
134
136
  next if child.split("/")[-1] != "containers"
137
+
135
138
  create_acl(child)
136
139
  end
137
140
 
@@ -141,10 +144,10 @@ class Chef
141
144
  # Get the current ACL for the given path
142
145
  def current_acl(acl_path)
143
146
  @current_acls ||= {}
144
- if !@current_acls.key?(acl_path)
147
+ unless @current_acls.key?(acl_path)
145
148
  @current_acls[acl_path] = begin
146
149
  rest.get(rest_url(acl_path))
147
- rescue Net::HTTPServerException => e
150
+ rescue Net::HTTPClientException => e
148
151
  unless e.response.code == "404" && new_resource.path.split("/").any? { |p| p == "*" }
149
152
  raise
150
153
  end
@@ -252,8 +255,7 @@ class Chef
252
255
  end
253
256
  end
254
257
 
255
- def load_current_resource
256
- end
258
+ def load_current_resource; end
257
259
 
258
260
  #
259
261
  # Matches chef_acl paths like nodes, nodes/*.
@@ -270,7 +272,7 @@ class Chef
270
272
  def match_paths(path)
271
273
  # Turn multiple slashes into one
272
274
  # nodes//x -> nodes/x
273
- path = path.gsub(/[\/]+/, "/")
275
+ path = path.gsub(%r{[/]+}, "/")
274
276
  # If it's absolute, start the matching with /. If it's relative, start with '' (relative root).
275
277
  if path[0] == "/"
276
278
  matches = [ "/" ]
@@ -305,6 +307,7 @@ class Chef
305
307
  if parts[0..index - 1].all? { |p| p != "*" }
306
308
  raise error
307
309
  end
310
+
308
311
  []
309
312
  else
310
313
  found
@@ -421,21 +424,21 @@ class Chef
421
424
  when 1
422
425
  # /organizations/*, /users/*, roles/*, nodes/*, etc.
423
426
  results, error = rest_list(path)
424
- if !error
427
+ unless error
425
428
  results = results.map { |result| ::File.join(path, result) }
426
429
  end
427
430
 
428
431
  when 2
429
432
  # /organizations/NAME/*
430
433
  results, error = rest_list(::File.join(path, "containers"))
431
- if !error
434
+ unless error
432
435
  results = results.map { |result| ::File.join(path, result) }
433
436
  end
434
437
 
435
438
  when 3
436
439
  # /organizations/NAME/TYPE/*
437
440
  results, error = rest_list(path)
438
- if !error
441
+ unless error
439
442
  results = results.map { |result| ::File.join(path, result) }
440
443
  end
441
444
  end
@@ -466,9 +469,9 @@ class Chef
466
469
  end
467
470
 
468
471
  def rest_list(path)
469
- # All our rest lists are hashes where the keys are the names
472
+ # All our rest lists are hashes where the keys are the names
470
473
  [ rest.get(rest_url(path)).keys, nil ]
471
- rescue Net::HTTPServerException => e
474
+ rescue Net::HTTPClientException => e
472
475
  if e.response.code == "405" || e.response.code == "404"
473
476
  parts = path.split("/").select { |p| p != "" }.to_a
474
477
 
@@ -4,7 +4,7 @@ require_relative "../../cheffish/chef_actor_base"
4
4
  class Chef
5
5
  class Resource
6
6
  class ChefClient < Cheffish::ChefActorBase
7
- resource_name :chef_client
7
+ provides :chef_client
8
8
 
9
9
  # Client attributes
10
10
  property :chef_client_name, Cheffish::NAME_REGEX, name_property: true
@@ -18,7 +18,7 @@ class Chef
18
18
 
19
19
  # Output public key (if so desired)
20
20
  property :output_key_path, String
21
- property :output_key_format, Symbol, default: :openssh, equal_to: [ :pem, :der, :openssh ]
21
+ property :output_key_format, Symbol, default: :openssh, equal_to: %i{pem der openssh}
22
22
 
23
23
  # Proc that runs just before the resource executes. Called with (resource)
24
24
  def before(&block)
@@ -38,7 +38,7 @@ class Chef
38
38
  delete_actor
39
39
  end
40
40
 
41
- action_class.class_eval do
41
+ action_class do
42
42
  def actor_type
43
43
  "client"
44
44
  end
@@ -5,12 +5,12 @@ require "chef/chef_fs/data_handler/container_data_handler"
5
5
  class Chef
6
6
  class Resource
7
7
  class ChefContainer < Cheffish::BaseResource
8
- resource_name :chef_container
8
+ provides :chef_container
9
9
 
10
10
  property :chef_container_name, Cheffish::NAME_REGEX, name_property: true
11
11
 
12
12
  action :create do
13
- if !@current_exists
13
+ unless @current_exists
14
14
  converge_by "create container #{new_resource.chef_container_name} at #{rest.url}" do
15
15
  rest.post("containers", normalize_for_post(new_json))
16
16
  end
@@ -25,10 +25,10 @@ class Chef
25
25
  end
26
26
  end
27
27
 
28
- action_class.class_eval do
28
+ action_class do
29
29
  def load_current_resource
30
30
  @current_exists = rest.get("containers/#{new_resource.chef_container_name}")
31
- rescue Net::HTTPServerException => e
31
+ rescue Net::HTTPClientException => e
32
32
  if e.response.code == "404"
33
33
  @current_exists = false
34
34
  else
@@ -4,12 +4,12 @@ require_relative "../../cheffish/base_resource"
4
4
  class Chef
5
5
  class Resource
6
6
  class ChefDataBag < Cheffish::BaseResource
7
- resource_name :chef_data_bag
7
+ provides :chef_data_bag
8
8
 
9
9
  property :data_bag_name, Cheffish::NAME_REGEX, name_property: true
10
10
 
11
11
  action :create do
12
- if !current_resource_exists?
12
+ unless current_resource_exists?
13
13
  converge_by "create data bag #{new_resource.data_bag_name} at #{rest.url}" do
14
14
  rest.post("data", { "name" => new_resource.data_bag_name })
15
15
  end
@@ -27,7 +27,7 @@ class Chef
27
27
  action_class.class_eval do
28
28
  def load_current_resource
29
29
  @current_resource = json_to_resource(rest.get("data/#{new_resource.data_bag_name}"))
30
- rescue Net::HTTPServerException => e
30
+ rescue Net::HTTPClientException => e
31
31
  if e.response.code == "404"
32
32
  @current_resource = not_found_resource
33
33
  else
@@ -7,7 +7,7 @@ require "chef/encrypted_data_bag_item"
7
7
  class Chef
8
8
  class Resource
9
9
  class ChefDataBagItem < Cheffish::BaseResource
10
- resource_name :chef_data_bag_item
10
+ provides :chef_data_bag_item
11
11
 
12
12
  def initialize(*args)
13
13
  super
@@ -103,7 +103,7 @@ class Chef
103
103
  resource = Chef::Resource::ChefDataBagItem.new(new_resource.name, run_context)
104
104
  resource.raw_data json
105
105
  @current_resource = resource
106
- rescue Net::HTTPServerException => e
106
+ rescue Net::HTTPClientException => e
107
107
  if e.response.code == "404"
108
108
  @current_resource = not_found_resource
109
109
  else
@@ -112,7 +112,7 @@ class Chef
112
112
  end
113
113
 
114
114
  # Determine if data bag is encrypted and if so, what its version is
115
- _first_real_key, first_real_value = (current_resource.raw_data || {}).select { |key, value| key != "id" && !value.nil? }.first
115
+ _first_real_key, first_real_value = (current_resource.raw_data || {}).find { |key, value| key != "id" && !value.nil? }
116
116
  if first_real_value
117
117
  if first_real_value.is_a?(Hash) &&
118
118
  first_real_value["version"].is_a?(Integer) &&
@@ -137,7 +137,7 @@ class Chef
137
137
 
138
138
  # If the current secret doesn't work, look through the specified old secrets
139
139
 
140
- if !current_resource.secret
140
+ unless current_resource.secret
141
141
  old_secrets = []
142
142
  if new_resource.old_secret
143
143
  old_secrets += Array(new_resource.old_secret)
@@ -148,17 +148,17 @@ class Chef
148
148
  end
149
149
  end
150
150
  old_secrets.each do |secret|
151
- begin
152
- Chef::EncryptedDataBagItem::Decryptor.for(first_real_value, secret).for_decrypted_item
153
- current_resource.secret secret
154
- rescue Chef::EncryptedDataBagItem::DecryptionFailure
155
- decrypt_error = $!
156
- end
151
+
152
+ Chef::EncryptedDataBagItem::Decryptor.for(first_real_value, secret).for_decrypted_item
153
+ current_resource.secret secret
154
+ rescue Chef::EncryptedDataBagItem::DecryptionFailure
155
+ decrypt_error = $!
156
+
157
157
  end
158
158
 
159
159
  # If we couldn't figure out the secret, emit a warning (this isn't a fatal flaw unless we
160
160
  # need to reuse one of the values from the data bag)
161
- if !current_resource.secret
161
+ unless current_resource.secret
162
162
  if decrypt_error
163
163
  Chef::Log.warn "Existing data bag is encrypted, but could not decrypt: #{decrypt_error.message}."
164
164
  else
@@ -280,9 +280,10 @@ class Chef
280
280
  elsif current_resource.encrypt
281
281
  # Encryption is different and we can't read the old values. Only allow the change
282
282
  # if we're overwriting the data bag item
283
- if !new_resource.complete
283
+ unless new_resource.complete
284
284
  raise "Cannot encrypt #{new_resource.name} due to failure to decrypt existing resource. Set 'complete true' to overwrite or add the old secret as old_secret / old_secret_path."
285
285
  end
286
+
286
287
  _differences = [ "overwrite data bag item (cannot decrypt old data bag item)"]
287
288
  differences = (new_resource.raw_data.keys & current_resource.raw_data.keys).map { |key| "overwrite #{key}" }
288
289
  differences += (new_resource.raw_data.keys - current_resource.raw_data.keys).map { |key| "add #{key}" }
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/environment_data_handler"
6
6
  class Chef
7
7
  class Resource
8
8
  class ChefEnvironment < Cheffish::BaseResource
9
- resource_name :chef_environment
9
+ provides :chef_environment
10
10
 
11
11
  property :environment_name, Cheffish::NAME_REGEX, name_property: true
12
12
  property :description, String
@@ -84,7 +84,7 @@ class Chef
84
84
  action_class.class_eval do
85
85
  def load_current_resource
86
86
  @current_resource = json_to_resource(rest.get("environments/#{new_resource.environment_name}"))
87
- rescue Net::HTTPServerException => e
87
+ rescue Net::HTTPClientException => e
88
88
  if e.response.code == "404"
89
89
  @current_resource = not_found_resource
90
90
  else
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/group_data_handler"
6
6
  class Chef
7
7
  class Resource
8
8
  class ChefGroup < Cheffish::BaseResource
9
- resource_name :chef_group
9
+ provides :chef_group
10
10
 
11
11
  property :group_name, Cheffish::NAME_REGEX, name_property: true
12
12
  property :users, ArrayType
@@ -45,7 +45,7 @@ class Chef
45
45
  action_class.class_eval do
46
46
  def load_current_resource
47
47
  @current_resource = json_to_resource(rest.get("groups/#{new_resource.group_name}"))
48
- rescue Net::HTTPServerException => e
48
+ rescue Net::HTTPClientException => e
49
49
  if e.response.code == "404"
50
50
  @current_resource = not_found_resource
51
51
  else
@@ -9,7 +9,7 @@ require "chef/chef_fs/file_system/repository/chef_repository_file_system_root_di
9
9
  class Chef
10
10
  class Resource
11
11
  class ChefMirror < Cheffish::BaseResource
12
- resource_name :chef_mirror
12
+ provides :chef_mirror
13
13
 
14
14
  # Path of the data to mirror, e.g. nodes, nodes/*, nodes/mynode,
15
15
  # */*, **, roles/base, data/secrets, cookbooks/apache2, etc.
@@ -95,6 +95,7 @@ class Chef
95
95
  if new_resource.concurrency <= 0
96
96
  raise "chef_mirror.concurrency must be above 0! Was set to #{new_resource.concurrency}"
97
97
  end
98
+
98
99
  # Honor concurrency
99
100
  Chef::ChefFS::Parallelizer.threads = new_resource.concurrency - 1
100
101
 
@@ -103,13 +104,14 @@ class Chef
103
104
  if new_resource.path[0] == "/"
104
105
  raise "Absolute paths in chef_mirror not yet supported."
105
106
  end
107
+
106
108
  # Copy!
107
109
  path = Chef::ChefFS::FilePattern.new("/#{new_resource.path}")
108
110
  ui = CopyListener.new(self)
109
111
  error = Chef::ChefFS::FileSystem.copy_to(path, src_root, dest_root, nil, options, ui, proc { |p| p.path })
110
112
 
111
113
  if error
112
- raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join('')}"
114
+ raise "Errors while copying:#{ui.errors.map { |e| "#{e}\n" }.join("")}"
113
115
  end
114
116
  end
115
117
 
@@ -163,7 +165,7 @@ class Chef
163
165
  end
164
166
 
165
167
  def repo_mode
166
- new_resource.chef_server[:chef_server_url] =~ /\/organizations\// ? "hosted_everything" : "everything"
168
+ %r{/organizations/}.match?(new_resource.chef_server[:chef_server_url]) ? "hosted_everything" : "everything"
167
169
  end
168
170
 
169
171
  def options
@@ -179,8 +181,7 @@ class Chef
179
181
  result
180
182
  end
181
183
 
182
- def load_current_resource
183
- end
184
+ def load_current_resource; end
184
185
 
185
186
  class CopyListener
186
187
  def initialize(mirror)
@@ -6,7 +6,7 @@ require_relative "../../cheffish/node_properties"
6
6
  class Chef
7
7
  class Resource
8
8
  class ChefNode < Cheffish::BaseResource
9
- resource_name :chef_node
9
+ provides :chef_node
10
10
 
11
11
  include Cheffish::NodeProperties
12
12
 
@@ -39,7 +39,7 @@ class Chef
39
39
  action_class.class_eval do
40
40
  def load_current_resource
41
41
  @current_resource = json_to_resource(rest.get("nodes/#{new_resource.name}"))
42
- rescue Net::HTTPServerException => e
42
+ rescue Net::HTTPClientException => e
43
43
  if e.response.code == "404"
44
44
  @current_resource = not_found_resource
45
45
  else