cheffish 15.0.0 → 15.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/Rakefile +1 -1
- data/lib/chef/resource/chef_acl.rb +13 -10
- data/lib/chef/resource/chef_client.rb +2 -2
- data/lib/chef/resource/chef_container.rb +2 -2
- data/lib/chef/resource/chef_data_bag.rb +2 -2
- data/lib/chef/resource/chef_data_bag_item.rb +11 -10
- data/lib/chef/resource/chef_environment.rb +1 -1
- data/lib/chef/resource/chef_group.rb +1 -1
- data/lib/chef/resource/chef_mirror.rb +6 -5
- data/lib/chef/resource/chef_node.rb +1 -1
- data/lib/chef/resource/chef_organization.rb +2 -2
- data/lib/chef/resource/chef_resolved_cookbooks.rb +5 -3
- data/lib/chef/resource/chef_role.rb +5 -1
- data/lib/chef/resource/chef_user.rb +2 -2
- data/lib/chef/resource/private_key.rb +10 -10
- data/lib/chef/resource/public_key.rb +4 -3
- data/lib/cheffish.rb +1 -0
- data/lib/cheffish/base_resource.rb +13 -11
- data/lib/cheffish/basic_chef_client.rb +2 -2
- data/lib/cheffish/chef_actor_base.rb +2 -1
- data/lib/cheffish/chef_run.rb +5 -6
- data/lib/cheffish/chef_run_listener.rb +1 -3
- data/lib/cheffish/key_formatter.rb +1 -9
- data/lib/cheffish/merged_config.rb +2 -2
- data/lib/cheffish/node_properties.rb +7 -3
- data/lib/cheffish/recipe_dsl.rb +2 -2
- data/lib/cheffish/rspec/chef_run_support.rb +1 -1
- data/lib/cheffish/rspec/matchers/have_updated.rb +5 -5
- data/lib/cheffish/rspec/recipe_run_wrapper.rb +1 -1
- data/lib/cheffish/rspec/repository_support.rb +1 -0
- data/lib/cheffish/version.rb +1 -1
- data/spec/functional/fingerprint_spec.rb +8 -6
- data/spec/integration/chef_acl_spec.rb +27 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 547830e01071a34cc583bbf5217ae5f55270c014c393e9a69301023a88717279
|
4
|
+
data.tar.gz: a29005438abb411a4b59bc7b1cf1782e36219e2bd951ec49c64273f9a7de6144
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6db5d7117bb249b37d894d3b3e776f7d3b5e8c87cb2895e156fbe4393031dbfdfdcff8a9133b4bb7e578f85440905a5acbd30426e7a8d81171ac3fd44f583936
|
7
|
+
data.tar.gz: 2216df827dc0635fdf0e3a340a80dbf267c8c51f58d7bde7c2a7deb28f0b3eeb24975bc88e3c44809c12189c05751a8624285d90a7472ace2bbb6b69dd99542d
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ require "uri"
|
|
7
7
|
class Chef
|
8
8
|
class Resource
|
9
9
|
class ChefAcl < Cheffish::BaseResource
|
10
|
-
|
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/*,
|
@@ -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(
|
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,7 +144,7 @@ class Chef
|
|
141
144
|
# Get the current ACL for the given path
|
142
145
|
def current_acl(acl_path)
|
143
146
|
@current_acls ||= {}
|
144
|
-
|
147
|
+
unless @current_acls.key?(acl_path)
|
145
148
|
@current_acls[acl_path] = begin
|
146
149
|
rest.get(rest_url(acl_path))
|
147
150
|
rescue Net::HTTPServerException => e
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
441
|
+
unless error
|
439
442
|
results = results.map { |result| ::File.join(path, result) }
|
440
443
|
end
|
441
444
|
end
|
@@ -466,7 +469,7 @@ class Chef
|
|
466
469
|
end
|
467
470
|
|
468
471
|
def rest_list(path)
|
469
|
-
|
472
|
+
# All our rest lists are hashes where the keys are the names
|
470
473
|
[ rest.get(rest_url(path)).keys, nil ]
|
471
474
|
rescue Net::HTTPServerException => e
|
472
475
|
if e.response.code == "405" || e.response.code == "404"
|
@@ -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
|
-
|
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:
|
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)
|
@@ -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
|
-
|
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
|
-
|
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
|
@@ -4,12 +4,12 @@ require_relative "../../cheffish/base_resource"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefDataBag < Cheffish::BaseResource
|
7
|
-
|
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
|
-
|
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
|
@@ -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
|
-
|
10
|
+
provides :chef_data_bag_item
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
13
|
super
|
@@ -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
|
-
|
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
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
9
|
+
provides :chef_environment
|
10
10
|
|
11
11
|
property :environment_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :description, String
|
@@ -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
|
-
|
9
|
+
provides :chef_group
|
10
10
|
|
11
11
|
property :group_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :users, ArrayType
|
@@ -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
|
-
|
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] =~
|
168
|
+
new_resource.chef_server[:chef_server_url] =~ %r{/organizations/} ? "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 "chef/chef_fs/data_handler/data_handler_base"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefOrganization < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_organization
|
10
10
|
|
11
11
|
property :organization_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :full_name, String
|
@@ -68,7 +68,7 @@ class Chef
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
new_resource.members.each do |user|
|
71
|
-
|
71
|
+
unless existing_members.include?(user)
|
72
72
|
converge_by "Add #{user} to organization #{new_resource.organization_name}" do
|
73
73
|
rest.post("#{rest.root_url}/organizations/#{new_resource.organization_name}/users/", { "username" => user })
|
74
74
|
end
|
@@ -4,7 +4,7 @@ require "chef_zero"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefResolvedCookbooks < Cheffish::BaseResource
|
7
|
-
|
7
|
+
provides :chef_resolved_cookbooks
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
super
|
@@ -43,7 +43,8 @@ class Chef
|
|
43
43
|
new_resource.berksfile.upload(
|
44
44
|
server_url: new_resource.chef_server[:chef_server_url],
|
45
45
|
client_name: new_resource.chef_server[:options][:client_name],
|
46
|
-
client_key: new_resource.chef_server[:options][:signing_key_filename]
|
46
|
+
client_key: new_resource.chef_server[:options][:signing_key_filename]
|
47
|
+
)
|
47
48
|
else
|
48
49
|
file = Tempfile.new("privatekey")
|
49
50
|
begin
|
@@ -53,7 +54,8 @@ class Chef
|
|
53
54
|
new_resource.berksfile.upload(
|
54
55
|
server_url: new_resource.chef_server[:chef_server_url],
|
55
56
|
client_name: new_resource.chef_server[:options][:client_name] || "me",
|
56
|
-
client_key: file.path
|
57
|
+
client_key: file.path
|
58
|
+
)
|
57
59
|
|
58
60
|
ensure
|
59
61
|
file.close
|
@@ -6,7 +6,7 @@ require "chef/chef_fs/data_handler/role_data_handler"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class ChefRole < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :chef_role
|
10
10
|
|
11
11
|
property :role_name, Cheffish::NAME_REGEX, name_property: true
|
12
12
|
property :description, String
|
@@ -62,6 +62,7 @@ class Chef
|
|
62
62
|
if recipes.size == 0
|
63
63
|
raise ArgumentError, "At least one recipe must be specified"
|
64
64
|
end
|
65
|
+
|
65
66
|
@run_list_modifiers ||= []
|
66
67
|
@run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
67
68
|
end
|
@@ -70,6 +71,7 @@ class Chef
|
|
70
71
|
if roles.size == 0
|
71
72
|
raise ArgumentError, "At least one role must be specified"
|
72
73
|
end
|
74
|
+
|
73
75
|
@run_list_modifiers ||= []
|
74
76
|
@run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
75
77
|
end
|
@@ -78,6 +80,7 @@ class Chef
|
|
78
80
|
if recipes.size == 0
|
79
81
|
raise ArgumentError, "At least one recipe must be specified"
|
80
82
|
end
|
83
|
+
|
81
84
|
@run_list_removers ||= []
|
82
85
|
@run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
83
86
|
end
|
@@ -86,6 +89,7 @@ class Chef
|
|
86
89
|
if roles.size == 0
|
87
90
|
raise ArgumentError, "At least one role must be specified"
|
88
91
|
end
|
92
|
+
|
89
93
|
@run_list_removers ||= []
|
90
94
|
@run_list_removers += roles.map { |recipe| Chef::RunList::RunListItem.new("role[#{role}]") }
|
91
95
|
end
|
@@ -4,7 +4,7 @@ require_relative "../../cheffish/chef_actor_base"
|
|
4
4
|
class Chef
|
5
5
|
class Resource
|
6
6
|
class ChefUser < Cheffish::ChefActorBase
|
7
|
-
|
7
|
+
provides :chef_user
|
8
8
|
|
9
9
|
# Client attributes
|
10
10
|
property :user_name, Cheffish::NAME_REGEX, name_property: true
|
@@ -25,7 +25,7 @@ class Chef
|
|
25
25
|
|
26
26
|
# Output public key (if so desired)
|
27
27
|
property :output_key_path, String
|
28
|
-
property :output_key_format,
|
28
|
+
property :output_key_format, %i{pem der openssh}, default: :openssh
|
29
29
|
|
30
30
|
# Proc that runs just before the resource executes. Called with (resource)
|
31
31
|
def before(&block)
|
@@ -6,18 +6,18 @@ require_relative "../../cheffish/key_formatter"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class PrivateKey < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :private_key
|
10
10
|
|
11
11
|
allowed_actions :create, :delete, :regenerate, :nothing
|
12
12
|
default_action :create
|
13
13
|
|
14
14
|
# Path to private key. Set to :none to create the key in memory and not on disk.
|
15
15
|
property :path, [ String, :none ], name_property: true
|
16
|
-
property :format,
|
17
|
-
property :type,
|
16
|
+
property :format, %i{pem der}, default: :pem
|
17
|
+
property :type, %i{rsa dsa}, default: :rsa # TODO support :ec
|
18
18
|
# These specify an optional public_key you can spit out if you want.
|
19
19
|
property :public_key_path, String
|
20
|
-
property :public_key_format,
|
20
|
+
property :public_key_format, %i{openssh pem der}, default: :openssh
|
21
21
|
# Specify this if you want to copy another private key but give it a different format / password
|
22
22
|
property :source_key
|
23
23
|
property :source_key_path, String
|
@@ -31,7 +31,7 @@ class Chef
|
|
31
31
|
|
32
32
|
# PEM-only
|
33
33
|
property :pass_phrase, String
|
34
|
-
property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map
|
34
|
+
property :cipher, String, equal_to: OpenSSL::Cipher.ciphers.map(&:downcase), default: "des-ede3-cbc", coerce: proc { |x| x.downcase }
|
35
35
|
|
36
36
|
# Set this to regenerate the key if it does not have the desired characteristics (like size, type, etc.)
|
37
37
|
property :regenerate_if_different, [TrueClass, FalseClass]
|
@@ -202,22 +202,22 @@ class Chef
|
|
202
202
|
def new_key_with_path
|
203
203
|
path = new_resource.path
|
204
204
|
if path.is_a?(Symbol)
|
205
|
-
|
205
|
+
[ nil, path ]
|
206
206
|
elsif Pathname.new(path).relative?
|
207
207
|
private_key, private_key_path = Cheffish.get_private_key_with_path(path, run_context.config)
|
208
208
|
if private_key
|
209
|
-
|
209
|
+
[ private_key, (private_key_path || :none) ]
|
210
210
|
elsif run_context.config[:private_key_write_path]
|
211
211
|
@should_create_directory = true
|
212
212
|
path = ::File.join(run_context.config[:private_key_write_path], path)
|
213
|
-
|
213
|
+
[ nil, path ]
|
214
214
|
else
|
215
215
|
raise "Could not find key #{path} and Chef::Config.private_key_write_path is not set."
|
216
216
|
end
|
217
217
|
elsif ::File.exist?(path)
|
218
|
-
|
218
|
+
[ IO.read(path), path ]
|
219
219
|
else
|
220
|
-
|
220
|
+
[ nil, path ]
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
@@ -6,13 +6,13 @@ require_relative "../../cheffish/key_formatter"
|
|
6
6
|
class Chef
|
7
7
|
class Resource
|
8
8
|
class PublicKey < Cheffish::BaseResource
|
9
|
-
|
9
|
+
provides :public_key
|
10
10
|
|
11
11
|
allowed_actions :create, :delete, :nothing
|
12
12
|
default_action :create
|
13
13
|
|
14
14
|
property :path, String, name_property: true
|
15
|
-
property :format,
|
15
|
+
property :format, %i{pem der openssh}, default: :openssh
|
16
16
|
|
17
17
|
property :source_key
|
18
18
|
property :source_key_path, String
|
@@ -24,9 +24,10 @@ class Chef
|
|
24
24
|
end
|
25
25
|
|
26
26
|
action :create do
|
27
|
-
|
27
|
+
unless new_source_key
|
28
28
|
raise "No source key specified"
|
29
29
|
end
|
30
|
+
|
30
31
|
desired_output = encode_public_key(new_source_key)
|
31
32
|
if Array(current_resource.action) == [ :delete ] || desired_output != IO.read(new_resource.path)
|
32
33
|
converge_by "write #{new_resource.format} public key #{new_resource.path} from #{new_source_key_publicity} key #{new_resource.source_key_path}" do
|
data/lib/cheffish.rb
CHANGED
@@ -98,6 +98,7 @@ module Cheffish
|
|
98
98
|
elsif config[:private_key_paths]
|
99
99
|
config[:private_key_paths].each do |private_key_path|
|
100
100
|
next unless File.exist?(private_key_path)
|
101
|
+
|
101
102
|
Dir.entries(private_key_path).sort.each do |key|
|
102
103
|
ext = File.extname(key)
|
103
104
|
if key == name || ext == "" || ext == ".pem"
|
@@ -91,7 +91,7 @@ module Cheffish
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def json_differences_internal(old_json, new_json, print_values, name, result)
|
94
|
-
if old_json.
|
94
|
+
if old_json.is_a?(Hash) && new_json.is_a?(Hash)
|
95
95
|
removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash }
|
96
96
|
new_json.each_pair do |new_key, new_value|
|
97
97
|
if old_json.key?(new_key)
|
@@ -101,18 +101,18 @@ module Cheffish
|
|
101
101
|
end
|
102
102
|
else
|
103
103
|
if print_values
|
104
|
-
result << " add #{name ==
|
104
|
+
result << " add #{name == "" ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}"
|
105
105
|
else
|
106
|
-
result << " add #{name ==
|
106
|
+
result << " add #{name == "" ? new_key : "#{name}.#{new_key}"}"
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
110
|
removed_keys.keys.each do |removed_key|
|
111
|
-
result << " remove #{name ==
|
111
|
+
result << " remove #{name == "" ? removed_key : "#{name}.#{removed_key}"}"
|
112
112
|
end
|
113
113
|
else
|
114
|
-
old_json = old_json.to_s if old_json.
|
115
|
-
new_json = new_json.to_s if new_json.
|
114
|
+
old_json = old_json.to_s if old_json.is_a?(Symbol)
|
115
|
+
new_json = new_json.to_s if new_json.is_a?(Symbol)
|
116
116
|
if old_json != new_json
|
117
117
|
if print_values
|
118
118
|
result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}"
|
@@ -134,8 +134,8 @@ module Cheffish
|
|
134
134
|
end
|
135
135
|
|
136
136
|
modifiers.each do |path, value|
|
137
|
-
path = [path]
|
138
|
-
path = path.map
|
137
|
+
path = [path] unless path.is_a?(Array)
|
138
|
+
path = path.map(&:to_s)
|
139
139
|
parent = 0.upto(path.size - 2).inject(json) do |hash, index|
|
140
140
|
if hash.nil?
|
141
141
|
nil
|
@@ -148,6 +148,7 @@ module Cheffish
|
|
148
148
|
if !parent.nil? && !parent.is_a?(Hash)
|
149
149
|
raise "Attempt to set #{path} to #{value} when #{path[0..-2]} is not a hash"
|
150
150
|
end
|
151
|
+
|
151
152
|
existing_value = parent ? parent[path[-1]] : nil
|
152
153
|
|
153
154
|
if value.is_a?(Proc)
|
@@ -158,7 +159,7 @@ module Cheffish
|
|
158
159
|
else
|
159
160
|
# Create parent if necessary, overwriting values
|
160
161
|
parent = path[0..-2].inject(json) do |hash, path_part|
|
161
|
-
hash[path_part] = {}
|
162
|
+
hash[path_part] = {} unless hash[path_part]
|
162
163
|
hash[path_part]
|
163
164
|
end
|
164
165
|
if path.size > 0
|
@@ -173,6 +174,7 @@ module Cheffish
|
|
173
174
|
|
174
175
|
def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list)
|
175
176
|
return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size)
|
177
|
+
|
176
178
|
delete_from_run_list ||= []
|
177
179
|
add_to_run_list ||= []
|
178
180
|
|
@@ -191,7 +193,7 @@ module Cheffish
|
|
191
193
|
# because found_desired will be less than add_to_run_list_index. The result will
|
192
194
|
# be X, A, B, Y, Z.
|
193
195
|
if found_desired >= add_to_run_list_index
|
194
|
-
result += add_to_run_list[add_to_run_list_index..found_desired].map
|
196
|
+
result += add_to_run_list[add_to_run_list_index..found_desired].map(&:to_s)
|
195
197
|
add_to_run_list_index = found_desired + 1
|
196
198
|
end
|
197
199
|
else
|
@@ -204,7 +206,7 @@ module Cheffish
|
|
204
206
|
end
|
205
207
|
|
206
208
|
# Copy any remaining desired items at the end
|
207
|
-
result += add_to_run_list[add_to_run_list_index..-1].map
|
209
|
+
result += add_to_run_list[add_to_run_list_index..-1].map(&:to_s)
|
208
210
|
result
|
209
211
|
end
|
210
212
|
|
@@ -14,7 +14,7 @@ module Cheffish
|
|
14
14
|
include Chef::DSL::Recipe
|
15
15
|
|
16
16
|
def initialize(node = nil, events = nil, **chef_config)
|
17
|
-
|
17
|
+
unless node
|
18
18
|
node = Chef::Node.new
|
19
19
|
node.name "basic_chef_client"
|
20
20
|
node.automatic[:platform] = "basic_chef_client"
|
@@ -31,7 +31,7 @@ module Cheffish
|
|
31
31
|
case events
|
32
32
|
when Array
|
33
33
|
events.each { |e| dispatcher.register(e) } if events
|
34
|
-
when !nil
|
34
|
+
when !nil # rubocop: disable Lint/LiteralAsCondition
|
35
35
|
dispatcher.register(events)
|
36
36
|
end
|
37
37
|
@run_context = Chef::RunContext.new(node, {}, dispatcher)
|
@@ -24,9 +24,10 @@ module Cheffish
|
|
24
24
|
end
|
25
25
|
else
|
26
26
|
# Create the actor if it's missing
|
27
|
-
|
27
|
+
unless new_public_key
|
28
28
|
raise "You must specify a public key to create a #{actor_type}! Use the private_key resource to create a key, and pass it in with source_key_path."
|
29
29
|
end
|
30
|
+
|
30
31
|
description = [ "create #{actor_type} #{new_resource.name} at #{actor_path}" ] + differences
|
31
32
|
converge_by description do
|
32
33
|
result = rest.post((actor_path).to_s, normalize_for_post(new_json))
|
data/lib/cheffish/chef_run.rb
CHANGED
@@ -34,15 +34,14 @@ module Cheffish
|
|
34
34
|
def client
|
35
35
|
@client ||= begin
|
36
36
|
chef_config = self.chef_config.dup
|
37
|
-
chef_config[:log_level] ||= :debug
|
38
|
-
chef_config[:verbose_logging] = false
|
37
|
+
chef_config[:log_level] ||= :debug unless chef_config.key?(:log_level)
|
38
|
+
chef_config[:verbose_logging] = false unless chef_config.key?(:verbose_logging)
|
39
39
|
chef_config[:stdout] = StringIOTee.new(chef_config[:stdout])
|
40
40
|
chef_config[:stderr] = StringIOTee.new(chef_config[:stderr])
|
41
41
|
chef_config[:log_location] = StringIOTee.new(chef_config[:log_location])
|
42
42
|
@client = ::Cheffish::BasicChefClient.new(nil,
|
43
43
|
[ event_sink, Chef::Formatters.new(:doc, chef_config[:stdout], chef_config[:stderr]) ],
|
44
|
-
chef_config
|
45
|
-
)
|
44
|
+
chef_config)
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
@@ -125,14 +124,14 @@ module Cheffish
|
|
125
124
|
message << "--- Chef Client Output ---\n"
|
126
125
|
message << "--- ---\n"
|
127
126
|
message << stdout
|
128
|
-
message << "\n"
|
127
|
+
message << "\n" unless stdout.end_with?("\n")
|
129
128
|
end
|
130
129
|
if stderr && !stderr.empty?
|
131
130
|
message << "--- ---\n"
|
132
131
|
message << "--- Chef Client Error Output ---\n"
|
133
132
|
message << "--- ---\n"
|
134
133
|
message << stderr
|
135
|
-
message << "\n"
|
134
|
+
message << "\n" unless stderr.end_with?("\n")
|
136
135
|
end
|
137
136
|
if logs && !logs.empty?
|
138
137
|
message << "--- ---\n"
|
@@ -55,15 +55,7 @@ module Cheffish
|
|
55
55
|
hexes = Digest::MD5.hexdigest(data)
|
56
56
|
hexes.scan(/../).join(":")
|
57
57
|
when :pkcs8sha1fingerprint
|
58
|
-
|
59
|
-
raise "PKCS8 SHA1 not supported in Ruby #{RUBY_VERSION}"
|
60
|
-
end
|
61
|
-
require "openssl_pkcs8"
|
62
|
-
pkcs8_pem = key.to_pem_pkcs8
|
63
|
-
pkcs8_base64 = pkcs8_pem.split("\n").reject { |l| l =~ /^-----/ }
|
64
|
-
pkcs8_data = Base64.decode64(pkcs8_base64.join)
|
65
|
-
hexes = Digest::SHA1.hexdigest(pkcs8_data)
|
66
|
-
hexes.scan(/../).join(":")
|
58
|
+
raise "PKCS8 SHA1 not supported by Ruby 2.0 and later"
|
67
59
|
else
|
68
60
|
raise "Unrecognized key format #{format}"
|
69
61
|
end
|
@@ -27,7 +27,7 @@ module Cheffish
|
|
27
27
|
result_configs = []
|
28
28
|
configs.each do |config|
|
29
29
|
value = config[name]
|
30
|
-
|
30
|
+
unless value.nil?
|
31
31
|
if value.respond_to?(:keys)
|
32
32
|
result_configs << value
|
33
33
|
elsif result_configs.size > 0
|
@@ -63,7 +63,7 @@ module Cheffish
|
|
63
63
|
alias_method :has_key?, :key?
|
64
64
|
|
65
65
|
def keys
|
66
|
-
configs.flat_map
|
66
|
+
configs.flat_map(&:keys).uniq
|
67
67
|
end
|
68
68
|
|
69
69
|
def values
|
@@ -39,7 +39,7 @@ module Cheffish
|
|
39
39
|
attribute "tags" do |existing_tags|
|
40
40
|
existing_tags ||= []
|
41
41
|
tags.each do |tag|
|
42
|
-
|
42
|
+
unless existing_tags.include?(tag.to_s)
|
43
43
|
existing_tags << tag.to_s
|
44
44
|
end
|
45
45
|
end
|
@@ -64,8 +64,8 @@ module Cheffish
|
|
64
64
|
if tags.size == 0
|
65
65
|
attribute("tags")
|
66
66
|
else
|
67
|
-
tags = tags[0] if tags.size == 1 && tags[0].
|
68
|
-
attribute("tags", tags.map
|
67
|
+
tags = tags[0] if tags.size == 1 && tags[0].is_a?(Array)
|
68
|
+
attribute("tags", tags.map(&:to_s))
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -80,6 +80,7 @@ module Cheffish
|
|
80
80
|
if recipes.size == 0
|
81
81
|
raise ArgumentError, "At least one recipe must be specified"
|
82
82
|
end
|
83
|
+
|
83
84
|
@run_list_modifiers ||= []
|
84
85
|
@run_list_modifiers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
85
86
|
end
|
@@ -88,6 +89,7 @@ module Cheffish
|
|
88
89
|
if roles.size == 0
|
89
90
|
raise ArgumentError, "At least one role must be specified"
|
90
91
|
end
|
92
|
+
|
91
93
|
@run_list_modifiers ||= []
|
92
94
|
@run_list_modifiers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
93
95
|
end
|
@@ -96,6 +98,7 @@ module Cheffish
|
|
96
98
|
if recipes.size == 0
|
97
99
|
raise ArgumentError, "At least one recipe must be specified"
|
98
100
|
end
|
101
|
+
|
99
102
|
@run_list_removers ||= []
|
100
103
|
@run_list_removers += recipes.map { |recipe| Chef::RunList::RunListItem.new("recipe[#{recipe}]") }
|
101
104
|
end
|
@@ -104,6 +107,7 @@ module Cheffish
|
|
104
107
|
if roles.size == 0
|
105
108
|
raise ArgumentError, "At least one role must be specified"
|
106
109
|
end
|
110
|
+
|
107
111
|
@run_list_removers ||= []
|
108
112
|
@run_list_removers += roles.map { |role| Chef::RunList::RunListItem.new("role[#{role}]") }
|
109
113
|
end
|
data/lib/cheffish/recipe_dsl.rb
CHANGED
@@ -52,7 +52,7 @@ class Chef
|
|
52
52
|
|
53
53
|
# Create the data store chef-zero will use
|
54
54
|
options[:data_store] ||= begin
|
55
|
-
|
55
|
+
unless options[:chef_repo_path]
|
56
56
|
raise "chef_repo_path must be specified to with_chef_local_server"
|
57
57
|
end
|
58
58
|
|
@@ -63,7 +63,7 @@ class Chef
|
|
63
63
|
symbol_key = "#{type}_path".to_sym
|
64
64
|
|
65
65
|
options[symbol_key] ||= begin
|
66
|
-
if options[:chef_repo_path].
|
66
|
+
if options[:chef_repo_path].is_a?(String)
|
67
67
|
Chef::Util::PathHelper.join(options[:chef_repo_path], "#{type}s")
|
68
68
|
else
|
69
69
|
options[:chef_repo_path].map { |path| Chef::Util::PathHelper.join(path, "#{type}s") }
|
@@ -5,16 +5,16 @@ RSpec::Matchers.define :have_updated do |resource_name, *expected_actions|
|
|
5
5
|
@recipe = recipe
|
6
6
|
actual = @recipe.event_sink.events
|
7
7
|
actual_actions = actual.select { |event, resource, action| event == :resource_updated && resource.to_s == resource_name }
|
8
|
-
|
8
|
+
.map { |event, resource, action| action }
|
9
9
|
expect(actual_actions).to eq(expected_actions)
|
10
10
|
end
|
11
11
|
|
12
12
|
failure_message do
|
13
13
|
actual = @recipe.event_sink.events
|
14
14
|
updates = actual.select { |event, resource, action| event == :resource_updated }.to_a
|
15
|
-
result = "expected that the chef_run would #{expected_actions.join(
|
15
|
+
result = "expected that the chef_run would #{expected_actions.join(",")} #{resource_name}."
|
16
16
|
if updates.size > 0
|
17
|
-
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(
|
17
|
+
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(", ")}"
|
18
18
|
else
|
19
19
|
result << " Nothing was updated."
|
20
20
|
end
|
@@ -24,9 +24,9 @@ RSpec::Matchers.define :have_updated do |resource_name, *expected_actions|
|
|
24
24
|
failure_message_when_negated do
|
25
25
|
actual = @recipe.event_sink.events
|
26
26
|
updates = actual.select { |event, resource, action| event == :resource_updated }.to_a
|
27
|
-
result = "expected that the chef_run would not #{expected_actions.join(
|
27
|
+
result = "expected that the chef_run would not #{expected_actions.join(",")} #{resource_name}."
|
28
28
|
if updates.size > 0
|
29
|
-
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(
|
29
|
+
result << " Actual updates were #{updates.map { |event, resource, action| "#{resource} => #{action.inspect}" }.join(", ")}"
|
30
30
|
else
|
31
31
|
result << " Nothing was updated."
|
32
32
|
end
|
@@ -12,6 +12,7 @@ module Cheffish
|
|
12
12
|
::RSpec.shared_context "with a chef repo" do
|
13
13
|
before :each do
|
14
14
|
raise "Can only create one directory per test" if @repository_dir
|
15
|
+
|
15
16
|
@repository_dir = Dir.mktmpdir("chef_repo")
|
16
17
|
Chef::Config.chef_repo_path = @repository_dir
|
17
18
|
%w{client cookbook data_bag environment node role user}.each do |object_name|
|
data/lib/cheffish/version.rb
CHANGED
@@ -39,24 +39,26 @@ describe "Cheffish fingerprint key formatter" do
|
|
39
39
|
|
40
40
|
context "when computing key fingperprints" do
|
41
41
|
|
42
|
-
it "
|
43
|
-
expect
|
44
|
-
"88:7e:3a:bd:26:9f:b5:c5:d8:ae:52:f9:df:0b:64:a4:5c:17:0a:87")
|
42
|
+
it "raises when passing a PKCS#8 SHA1 private key fingerprint" do
|
43
|
+
expect { key_to_format(sample_private_key, :pkcs8sha1fingerprint) }.to raise_error
|
45
44
|
end
|
46
45
|
|
47
46
|
it "computes the PKCS#1 MD5 public key fingerprint correctly" do
|
48
47
|
expect(key_to_format(sample_public_key, :pkcs1md5fingerprint)).to eq(
|
49
|
-
"1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20"
|
48
|
+
"1f:e8:da:c1:16:c3:72:7d:90:e2:b7:64:c4:b4:55:20"
|
49
|
+
)
|
50
50
|
end
|
51
51
|
|
52
52
|
it "computes the RFC4716 MD5 public key fingerprint correctly" do
|
53
53
|
expect(key_to_format(sample_public_key, :rfc4716md5fingerprint)).to eq(
|
54
|
-
"b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b"
|
54
|
+
"b0:13:4f:da:cf:8c:dc:a7:4a:1f:d2:3a:51:92:cf:6b"
|
55
|
+
)
|
55
56
|
end
|
56
57
|
|
57
58
|
it "defaults to the PKCS#1 MD5 public key fingerprint" do
|
58
59
|
expect(key_to_format(sample_public_key, :fingerprint)).to eq(
|
59
|
-
key_to_format(sample_public_key, :pkcs1md5fingerprint)
|
60
|
+
key_to_format(sample_public_key, :pkcs1md5fingerprint)
|
61
|
+
)
|
60
62
|
end
|
61
63
|
|
62
64
|
end
|
@@ -160,7 +160,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
160
160
|
it 'Converging chef_acl "nodes/x" with rights [ :read, :create, :update, :delete, :grant ] modifies all rights' do
|
161
161
|
expect_recipe do
|
162
162
|
chef_acl "nodes/x" do
|
163
|
-
rights
|
163
|
+
rights %i{create read update delete grant}, users: %w{u1 u2}, clients: %w{c1}, groups: %w{g1}
|
164
164
|
end
|
165
165
|
end.to be_updated
|
166
166
|
expect(get("nodes/x/_acl")).to partially_match(
|
@@ -229,11 +229,11 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
229
229
|
end
|
230
230
|
end.to be_updated
|
231
231
|
expect(get("nodes/x/_acl")).to partially_match(
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
232
|
+
"create" => { "actors" => exclude("foo") },
|
233
|
+
"read" => { "actors" => exclude("foo") },
|
234
|
+
"update" => { "actors" => exclude("foo") },
|
235
|
+
"delete" => { "actors" => exclude("foo") },
|
236
|
+
"grant" => { "actors" => exclude("foo") }
|
237
237
|
)
|
238
238
|
end
|
239
239
|
end
|
@@ -361,7 +361,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
361
361
|
end.to be_updated
|
362
362
|
%w{clients containers cookbooks data environments groups nodes roles}.each do |type|
|
363
363
|
expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
|
364
|
-
|
364
|
+
"read" => { "actors" => %w{u} }
|
365
|
+
)
|
365
366
|
end
|
366
367
|
end
|
367
368
|
end
|
@@ -408,7 +409,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
408
409
|
end.to be_updated
|
409
410
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
410
411
|
expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
|
411
|
-
|
412
|
+
"read" => { "actors" => %w{u} }
|
413
|
+
)
|
412
414
|
end
|
413
415
|
end
|
414
416
|
|
@@ -420,7 +422,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
420
422
|
end.to be_updated
|
421
423
|
%w{clients containers cookbooks data environments groups nodes roles}.each do |type|
|
422
424
|
expect(get("/organizations/foo/#{type}/x/_acl")).to partially_match(
|
423
|
-
|
425
|
+
"read" => { "actors" => %w{u} }
|
426
|
+
)
|
424
427
|
end
|
425
428
|
end
|
426
429
|
|
@@ -447,7 +450,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
447
450
|
chef_acl "/organizations/foo/cookbooks/x/1.0.0" do
|
448
451
|
rights :read, users: %w{u}
|
449
452
|
end
|
450
|
-
end.to raise_error(
|
453
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/cookbooks/x})
|
451
454
|
end
|
452
455
|
|
453
456
|
it "chef_acl '/organizations/foo/cookbooks/*/*' raises an error" do
|
@@ -456,7 +459,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
456
459
|
chef_acl "/organizations/foo/cookbooks/*/*" do
|
457
460
|
rights :read, users: %w{u}
|
458
461
|
end
|
459
|
-
end.to raise_error(
|
462
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/cookbooks/*})
|
460
463
|
end
|
461
464
|
|
462
465
|
it 'chef_acl "/organizations/foo/data/x/y" raises an error' do
|
@@ -464,7 +467,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
464
467
|
chef_acl "/organizations/foo/data/x/y" do
|
465
468
|
rights :read, users: %w{u}
|
466
469
|
end
|
467
|
-
end.to raise_error(
|
470
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/data/x})
|
468
471
|
end
|
469
472
|
|
470
473
|
it 'chef_acl "/organizations/foo/data/*/*" raises an error' do
|
@@ -473,7 +476,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
473
476
|
chef_acl "/organizations/foo/data/*/*" do
|
474
477
|
rights :read, users: %w{u}
|
475
478
|
end
|
476
|
-
end.to raise_error(
|
479
|
+
end.to raise_error(%r{ACLs cannot be set on children of /organizations/foo/data/*})
|
477
480
|
end
|
478
481
|
|
479
482
|
it 'chef_acl "/organizations/foo" changes the acl' do
|
@@ -609,7 +612,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
609
612
|
end.to be_updated
|
610
613
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
611
614
|
expect(get("#{type}/x/_acl")).to partially_match(
|
612
|
-
|
615
|
+
"read" => { "actors" => %w{u} }
|
616
|
+
)
|
613
617
|
end
|
614
618
|
end
|
615
619
|
|
@@ -621,7 +625,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
621
625
|
end.to be_updated
|
622
626
|
%w{clients containers cookbooks data environments groups nodes roles}.each do |type|
|
623
627
|
expect(get("#{type}/x/_acl")).to partially_match(
|
624
|
-
|
628
|
+
"read" => { "actors" => %w{u} }
|
629
|
+
)
|
625
630
|
end
|
626
631
|
end
|
627
632
|
|
@@ -633,7 +638,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
633
638
|
end.to be_updated
|
634
639
|
%w{admins billing-admins clients users x}.each do |n|
|
635
640
|
expect(get("groups/#{n}/_acl")).to partially_match(
|
636
|
-
|
641
|
+
"read" => { "actors" => %w{u} }
|
642
|
+
)
|
637
643
|
end
|
638
644
|
end
|
639
645
|
|
@@ -713,7 +719,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
713
719
|
end.to be_updated
|
714
720
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
715
721
|
expect(get("/organizations/foo/containers/#{type}/_acl")).to partially_match(
|
716
|
-
|
722
|
+
"read" => { "actors" => %w{u} }
|
723
|
+
)
|
717
724
|
end
|
718
725
|
end
|
719
726
|
|
@@ -768,7 +775,8 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
768
775
|
end.to be_updated
|
769
776
|
%w{clients containers cookbooks data environments groups nodes roles sandboxes}.each do |type|
|
770
777
|
expect(get("containers/#{type}/_acl")).to partially_match(
|
771
|
-
|
778
|
+
"read" => { "actors" => %w{u} }
|
779
|
+
)
|
772
780
|
end
|
773
781
|
end
|
774
782
|
end
|
@@ -820,7 +828,7 @@ if Gem::Version.new(ChefZero::VERSION) >= Gem::Version.new("3.1")
|
|
820
828
|
it 'chef_acl with remove_rights [ :create, :read ], "u", "c", "g" removes all three' do
|
821
829
|
expect_recipe do
|
822
830
|
chef_acl "nodes/x" do
|
823
|
-
remove_rights
|
831
|
+
remove_rights %i{create read}, users: %w{u}, clients: %w{c}, groups: %w{g}
|
824
832
|
end
|
825
833
|
end.to be_updated
|
826
834
|
expect(get("nodes/x/_acl")).to partially_match(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cheffish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 15.0.
|
4
|
+
version: 15.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-zero
|