cheffish 14.0.13 → 16.0.8

Sign up to get free protection for your applications and to get access to all the features.
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