chef 17.3.48 → 17.4.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/application.rb +3 -1
- data/lib/chef/compliance/default_attributes.rb +5 -3
- data/lib/chef/compliance/runner.rb +15 -1
- data/lib/chef/dsl/secret.rb +3 -3
- data/lib/chef/exceptions.rb +0 -2
- data/lib/chef/formatters/error_mapper.rb +2 -2
- data/lib/chef/provider/execute.rb +1 -1
- data/lib/chef/provider/group/dscl.rb +1 -1
- data/lib/chef/provider/launchd.rb +6 -6
- data/lib/chef/provider/subversion.rb +4 -4
- data/lib/chef/provider/support/yum_repo.erb +1 -1
- data/lib/chef/provider/systemd_unit.rb +17 -16
- data/lib/chef/provider/user/mac.rb +3 -3
- data/lib/chef/provider/yum_repository.rb +27 -43
- data/lib/chef/provider/zypper_repository.rb +3 -3
- data/lib/chef/provider.rb +26 -1
- data/lib/chef/provider_resolver.rb +8 -2
- data/lib/chef/resource/homebrew_cask.rb +1 -1
- data/lib/chef/resource/inspec_waiver_file_entry.rb +2 -2
- data/lib/chef/resource/launchd.rb +3 -3
- data/lib/chef/resource/remote_file.rb +1 -1
- data/lib/chef/resource/rhsm_subscription.rb +5 -5
- data/lib/chef/resource/ruby_block.rb +100 -0
- data/lib/chef/resource/scm/subversion.rb +1 -1
- data/lib/chef/resource/sysctl.rb +2 -2
- data/lib/chef/resource/systemd_unit.rb +3 -3
- data/lib/chef/resource/yum_package.rb +1 -5
- data/lib/chef/resource.rb +14 -18
- data/lib/chef/resource_inspector.rb +6 -2
- data/lib/chef/secret_fetcher/aws_secrets_manager.rb +16 -4
- data/lib/chef/secret_fetcher/azure_key_vault.rb +31 -9
- data/lib/chef/secret_fetcher/base.rb +5 -1
- data/lib/chef/secret_fetcher.rb +5 -4
- data/lib/chef/version.rb +1 -1
- data/spec/integration/compliance/compliance_spec.rb +1 -0
- data/spec/integration/recipes/resource_action_spec.rb +2 -2
- data/spec/unit/compliance/runner_spec.rb +46 -2
- data/spec/unit/dsl/secret_spec.rb +8 -2
- data/spec/unit/provider_spec.rb +23 -0
- data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
- data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
- data/spec/unit/resource/systemd_unit_spec.rb +1 -1
- data/spec/unit/resource_spec.rb +19 -8
- data/spec/unit/secret_fetcher/aws_secrets_manager_spec.rb +70 -0
- data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +23 -16
- data/spec/unit/secret_fetcher_spec.rb +9 -9
- metadata +7 -6
@@ -8,23 +8,30 @@ class Chef
|
|
8
8
|
# In this initial iteration this authenticates via token obtained from the OAuth2 /token
|
9
9
|
# endpoint.
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# Validation of required configuration (vault name) is not performed until
|
12
|
+
# `fetch` time, to allow for embedding the vault name in with the secret
|
13
|
+
# name, such as "my_vault/secretkey1".
|
12
14
|
#
|
13
|
-
#
|
15
|
+
# @example
|
16
|
+
#
|
17
|
+
# fetcher = SecretFetcher.for_service(:azure_key_vault, { vault: "my_vault" }, run_context )
|
14
18
|
# fetcher.fetch("secretkey1", "v1")
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
#
|
22
|
+
# fetcher = SecretFetcher.for_service(:azure_key_vault, {}, run_context )
|
23
|
+
# fetcher.fetch("my_vault/secretkey1", "v1")
|
15
24
|
class AzureKeyVault < Base
|
16
|
-
def validate!
|
17
|
-
@vault = config[:vault]
|
18
|
-
if @vault.nil?
|
19
|
-
raise Chef::Exceptions::Secret::MissingVaultName.new("You must provide a vault name to service options as vault: 'vault_name'")
|
20
|
-
end
|
21
|
-
end
|
22
25
|
|
23
26
|
def do_fetch(name, version)
|
24
27
|
token = fetch_token
|
28
|
+
vault, name = resolve_vault_and_secret_name(name)
|
29
|
+
if vault.nil?
|
30
|
+
raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide a vault name to fetcher options as vault: 'vault_name' or in the secret name as 'vault_name/secret_name'")
|
31
|
+
end
|
25
32
|
|
26
33
|
# Note that `version` is optional after the final `/`. If nil/"", the latest secret version will be fetched.
|
27
|
-
secret_uri = URI.parse("https://#{
|
34
|
+
secret_uri = URI.parse("https://#{vault}.vault.azure.net/secrets/#{name}/#{version}?api-version=7.2")
|
28
35
|
http = Net::HTTP.new(secret_uri.host, secret_uri.port)
|
29
36
|
http.use_ssl = true
|
30
37
|
|
@@ -41,6 +48,21 @@ class Chef
|
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
51
|
+
# Determine the vault name and secret name from the provided name.
|
52
|
+
# If it is not in the provided name in the form "vault_name/secret_name"
|
53
|
+
# it will determine the vault name from `config[:vault]`.
|
54
|
+
# @param name [String] the secret name or vault and secret name in the form "vault_name/secret_name"
|
55
|
+
# @return Array[String, String] vault and secret name respectively
|
56
|
+
def resolve_vault_and_secret_name(name)
|
57
|
+
# We support a simplified approach where the vault name is not passed i
|
58
|
+
# into configuration, but
|
59
|
+
if name.include?("/")
|
60
|
+
name.split("/", 2)
|
61
|
+
else
|
62
|
+
[config[:vault], name]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
44
66
|
def fetch_token
|
45
67
|
token_uri = URI.parse("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net")
|
46
68
|
http = Net::HTTP.new(token_uri.host, token_uri.port)
|
@@ -25,13 +25,17 @@ class Chef
|
|
25
25
|
class SecretFetcher
|
26
26
|
class Base
|
27
27
|
attr_reader :config
|
28
|
+
# Note that this is only available in the context of a recipe.
|
29
|
+
# Since that's the only place it's intended to be used, that's probably OK.
|
30
|
+
attr_reader :run_context
|
28
31
|
|
29
32
|
# Initialize a new SecretFetcher::Base
|
30
33
|
#
|
31
34
|
# @param config [Hash] Configuration hash. Expected configuration keys and values
|
32
35
|
# will vary based on implementation, and are validated in `validate!`.
|
33
|
-
def initialize(config)
|
36
|
+
def initialize(config, run_context)
|
34
37
|
@config = config
|
38
|
+
@run_context = run_context
|
35
39
|
end
|
36
40
|
|
37
41
|
# Fetch the named secret by invoking implementation-specific [Chef::SecretFetcher::Base#do_fetch]
|
data/lib/chef/secret_fetcher.rb
CHANGED
@@ -30,17 +30,18 @@ class Chef
|
|
30
30
|
# @param service [Symbol] the identifier for the service that will support this request. Must be in
|
31
31
|
# SECRET_FETCHERS
|
32
32
|
# @param config [Hash] configuration that the secrets service requires
|
33
|
-
|
33
|
+
# @param run_context [Chef::RunContext] the run context this is being invoked from
|
34
|
+
def self.for_service(service, config, run_context)
|
34
35
|
fetcher = case service
|
35
36
|
when :example
|
36
37
|
require_relative "secret_fetcher/example"
|
37
|
-
Chef::SecretFetcher::Example.new(config)
|
38
|
+
Chef::SecretFetcher::Example.new(config, run_context)
|
38
39
|
when :aws_secrets_manager
|
39
40
|
require_relative "secret_fetcher/aws_secrets_manager"
|
40
|
-
Chef::SecretFetcher::AWSSecretsManager.new(config)
|
41
|
+
Chef::SecretFetcher::AWSSecretsManager.new(config, run_context)
|
41
42
|
when :azure_key_vault
|
42
43
|
require_relative "secret_fetcher/azure_key_vault"
|
43
|
-
Chef::SecretFetcher::AzureKeyVault.new(config)
|
44
|
+
Chef::SecretFetcher::AzureKeyVault.new(config, run_context)
|
44
45
|
when nil, ""
|
45
46
|
raise Chef::Exceptions::Secret::MissingFetcher.new(SECRET_FETCHERS)
|
46
47
|
else
|
data/lib/chef/version.rb
CHANGED
@@ -354,8 +354,8 @@ module ResourceActionSpec
|
|
354
354
|
end
|
355
355
|
|
356
356
|
it "allows overridden action to have a description separate from the action defined in the base resource" do
|
357
|
-
expect(ActionJackson.action_description(:test1)).to eql "Original description"
|
358
|
-
expect(ActionJackalope.action_description(:test1)).to eql "An old action with a new description"
|
357
|
+
expect(ActionJackson.new("ActionJackson", nil).action_description(:test1)).to eql "Original description"
|
358
|
+
expect(ActionJackalope.new("ActionJackalope", nil).action_description(:test1)).to eql "An old action with a new description"
|
359
359
|
end
|
360
360
|
|
361
361
|
it "non-overridden actions run and can access overridden and non-overridden variables (but not necessarily new ones)" do
|
@@ -202,6 +202,16 @@ describe Chef::Compliance::Runner do
|
|
202
202
|
expect { runner.load_and_validate! }.to raise_error(/^CMPL002:/)
|
203
203
|
end
|
204
204
|
|
205
|
+
it "raises CMPL004 if both the inputs and attributes node attributes are set" do
|
206
|
+
node.normal["audit"]["attributes"] = {
|
207
|
+
"tacos" => "lunch",
|
208
|
+
}
|
209
|
+
node.normal["audit"]["inputs"] = {
|
210
|
+
"tacos" => "lunch",
|
211
|
+
}
|
212
|
+
expect { runner.load_and_validate! }.to raise_error(/^CMPL011:/)
|
213
|
+
end
|
214
|
+
|
205
215
|
it "validates configured reporters" do
|
206
216
|
node.normal["audit"]["reporter"] = [ "chef-automate" ]
|
207
217
|
reporter_double = double("reporter", validate_config!: nil)
|
@@ -212,6 +222,40 @@ describe Chef::Compliance::Runner do
|
|
212
222
|
end
|
213
223
|
|
214
224
|
describe "#inspec_opts" do
|
225
|
+
it "pulls inputs from the attributes setting" do
|
226
|
+
node.normal["audit"]["attributes"] = {
|
227
|
+
"tacos" => "lunch",
|
228
|
+
}
|
229
|
+
|
230
|
+
inputs = runner.inspec_opts[:inputs]
|
231
|
+
|
232
|
+
expect(inputs["tacos"]).to eq("lunch")
|
233
|
+
end
|
234
|
+
|
235
|
+
it "pulls inputs from the inputs setting" do
|
236
|
+
node.normal["audit"]["inputs"] = {
|
237
|
+
"tacos" => "lunch",
|
238
|
+
}
|
239
|
+
|
240
|
+
inputs = runner.inspec_opts[:inputs]
|
241
|
+
|
242
|
+
expect(inputs["tacos"]).to eq("lunch")
|
243
|
+
end
|
244
|
+
|
245
|
+
it "favors inputs over attributes" do
|
246
|
+
node.normal["audit"]["attributes"] = {
|
247
|
+
"tacos" => "dinner",
|
248
|
+
}
|
249
|
+
|
250
|
+
node.normal["audit"]["inputs"] = {
|
251
|
+
"tacos" => "lunch",
|
252
|
+
}
|
253
|
+
|
254
|
+
inputs = runner.inspec_opts[:inputs]
|
255
|
+
|
256
|
+
expect(inputs["tacos"]).to eq("lunch")
|
257
|
+
end
|
258
|
+
|
215
259
|
it "does not include chef_node in inputs by default" do
|
216
260
|
node.normal["audit"]["attributes"] = {
|
217
261
|
"tacos" => "lunch",
|
@@ -221,7 +265,7 @@ describe Chef::Compliance::Runner do
|
|
221
265
|
inputs = runner.inspec_opts[:inputs]
|
222
266
|
|
223
267
|
expect(inputs["tacos"]).to eq("lunch")
|
224
|
-
expect(inputs.key?("chef_node")).to eq(
|
268
|
+
expect(inputs.key?("chef_node")).to eq(true)
|
225
269
|
end
|
226
270
|
|
227
271
|
it "includes chef_node in inputs with chef_node_attribute_enabled set" do
|
@@ -234,7 +278,7 @@ describe Chef::Compliance::Runner do
|
|
234
278
|
inputs = runner.inspec_opts[:inputs]
|
235
279
|
|
236
280
|
expect(inputs["tacos"]).to eq("lunch")
|
237
|
-
expect(inputs["chef_node"]["audit"]["reporter"]).to eq(
|
281
|
+
expect(inputs["chef_node"]["audit"]["reporter"]).to eq("cli")
|
238
282
|
expect(inputs["chef_node"]["chef_environment"]).to eq("_default")
|
239
283
|
end
|
240
284
|
end
|
@@ -21,6 +21,12 @@ require "chef/dsl/secret"
|
|
21
21
|
require "chef/secret_fetcher/base"
|
22
22
|
class SecretDSLTester
|
23
23
|
include Chef::DSL::Secret
|
24
|
+
# Because DSL is invoked in the context of a recipe,
|
25
|
+
# we expect run_context to always be available when SecretFetcher::Base
|
26
|
+
# requests it - making it safe to mock here
|
27
|
+
def run_context
|
28
|
+
nil
|
29
|
+
end
|
24
30
|
end
|
25
31
|
|
26
32
|
class SecretFetcherImpl < Chef::SecretFetcher::Base
|
@@ -36,8 +42,8 @@ describe Chef::DSL::Secret do
|
|
36
42
|
end
|
37
43
|
|
38
44
|
it "uses SecretFetcher.for_service to find the fetcher" do
|
39
|
-
substitute_fetcher = SecretFetcherImpl.new({})
|
40
|
-
expect(Chef::SecretFetcher).to receive(:for_service).with(:example, {}).and_return(substitute_fetcher)
|
45
|
+
substitute_fetcher = SecretFetcherImpl.new({}, nil)
|
46
|
+
expect(Chef::SecretFetcher).to receive(:for_service).with(:example, {}, nil).and_return(substitute_fetcher)
|
41
47
|
expect(substitute_fetcher).to receive(:fetch).with("key1", nil)
|
42
48
|
dsl.secret(name: "key1", service: :example, config: {})
|
43
49
|
end
|
data/spec/unit/provider_spec.rb
CHANGED
@@ -32,6 +32,21 @@ class NoWhyrunDemonstrator < Chef::Provider
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
class ActionDescriptionDemonstrator < Chef::Provider
|
36
|
+
def load_current_resource; end
|
37
|
+
|
38
|
+
action :foo, description: "foo described" do
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
action :foo2 do
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context "blah" do
|
49
|
+
end
|
35
50
|
class ConvergeActionDemonstrator < Chef::Provider
|
36
51
|
attr_reader :system_state_altered
|
37
52
|
|
@@ -98,6 +113,14 @@ describe Chef::Provider do
|
|
98
113
|
expect(@provider.action_nothing).to eql(true)
|
99
114
|
end
|
100
115
|
|
116
|
+
it "should return an action description for action_description when one is available" do
|
117
|
+
expect(ActionDescriptionDemonstrator.action_description(:foo)).to eq "foo described"
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should return nil for action_description when no description is available" do
|
121
|
+
expect(ActionDescriptionDemonstrator.action_description(:none)).to eq nil
|
122
|
+
end
|
123
|
+
|
101
124
|
it "evals embedded recipes with a pristine resource collection" do
|
102
125
|
@provider.run_context.instance_variable_set(:@resource_collection, "doesn't matter what this is")
|
103
126
|
temporary_collection = nil
|
@@ -19,22 +19,40 @@ require "spec_helper"
|
|
19
19
|
|
20
20
|
describe Chef::Resource::HomebrewCask do
|
21
21
|
|
22
|
-
|
22
|
+
context "name with under bar" do
|
23
|
+
let(:resource) { Chef::Resource::HomebrewCask.new("fakey_fakerton") }
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
it "has a resource name of :homebrew_cask" do
|
26
|
+
expect(resource.resource_name).to eql(:homebrew_cask)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "the cask_name property is the name_property" do
|
30
|
+
expect(resource.cask_name).to eql("fakey_fakerton")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "sets the default action as :install" do
|
34
|
+
expect(resource.action).to eql([:install])
|
35
|
+
end
|
27
36
|
|
28
|
-
|
29
|
-
|
37
|
+
it "supports :install, :remove actions" do
|
38
|
+
expect { resource.action :install }.not_to raise_error
|
39
|
+
expect { resource.action :remove }.not_to raise_error
|
40
|
+
end
|
30
41
|
end
|
31
42
|
|
32
|
-
|
33
|
-
|
43
|
+
context "name with high fun" do
|
44
|
+
let(:resource) { Chef::Resource::HomebrewCask.new("fakey-fakerton") }
|
45
|
+
|
46
|
+
it "the cask_name property is the name_property" do
|
47
|
+
expect(resource.cask_name).to eql("fakey-fakerton")
|
48
|
+
end
|
34
49
|
end
|
35
50
|
|
36
|
-
|
37
|
-
|
38
|
-
|
51
|
+
context "name with at mark" do
|
52
|
+
let(:resource) { Chef::Resource::HomebrewCask.new("fakey-fakerton@10") }
|
53
|
+
|
54
|
+
it "the cask_name property is the name_property" do
|
55
|
+
expect(resource.cask_name).to eql("fakey-fakerton@10")
|
56
|
+
end
|
39
57
|
end
|
40
58
|
end
|
@@ -18,15 +18,24 @@
|
|
18
18
|
require "spec_helper"
|
19
19
|
|
20
20
|
describe Chef::Resource::RhsmSubscription do
|
21
|
-
let(:
|
22
|
-
let(:
|
21
|
+
let(:event_dispatch) { Chef::EventDispatch::Dispatcher.new }
|
22
|
+
let(:node) { Chef::Node.new }
|
23
|
+
let(:run_context) { Chef::RunContext.new(node, {}, event_dispatch) }
|
24
|
+
|
25
|
+
let(:pool_id) { "8a8dd78c766232550226b46e59404aba" }
|
26
|
+
let(:resource) { Chef::Resource::RhsmSubscription.new(pool_id, run_context) }
|
27
|
+
let(:provider) { resource.provider_for_action(Array(resource.action).first) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(resource).to receive(:provider_for_action).with(:attach).and_return(provider)
|
31
|
+
end
|
23
32
|
|
24
33
|
it "has a resource name of :rhsm_subscription" do
|
25
34
|
expect(resource.resource_name).to eql(:rhsm_subscription)
|
26
35
|
end
|
27
36
|
|
28
37
|
it "the pool_id property is the name_property" do
|
29
|
-
expect(resource.pool_id).to eql(
|
38
|
+
expect(resource.pool_id).to eql(pool_id)
|
30
39
|
end
|
31
40
|
|
32
41
|
it "sets the default action as :attach" do
|
@@ -38,6 +47,44 @@ describe Chef::Resource::RhsmSubscription do
|
|
38
47
|
expect { resource.action :remove }.not_to raise_error
|
39
48
|
end
|
40
49
|
|
50
|
+
describe "#action_attach" do
|
51
|
+
let(:yum_package_double) { instance_double("Chef::Resource::YumPackage") }
|
52
|
+
let(:so_double) { instance_double("Mixlib::ShellOut", stdout: "Successfully attached a subscription for: My Subscription", exitstatus: 0, error?: false) }
|
53
|
+
|
54
|
+
before do
|
55
|
+
allow(provider).to receive(:shell_out!).with("subscription-manager attach --pool=#{resource.pool_id}").and_return(so_double)
|
56
|
+
allow(provider).to receive(:build_resource).with(:package, "rhsm_subscription-#{pool_id}-flush_cache").and_return(yum_package_double)
|
57
|
+
allow(yum_package_double).to receive(:run_action).with(:flush_cache)
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when already attached to pool" do
|
61
|
+
before do
|
62
|
+
allow(provider).to receive(:subscription_attached?).with(resource.pool_id).and_return(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "does not attach to pool" do
|
66
|
+
expect(provider).not_to receive(:shell_out!)
|
67
|
+
resource.run_action(:attach)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when not attached to pool" do
|
72
|
+
before do
|
73
|
+
allow(provider).to receive(:subscription_attached?).with(resource.pool_id).and_return(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "attaches to pool" do
|
77
|
+
expect(provider).to receive(:shell_out!).with("subscription-manager attach --pool=#{resource.pool_id}")
|
78
|
+
resource.run_action(:attach)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "flushes package provider cache" do
|
82
|
+
expect(yum_package_double).to receive(:run_action).with(:flush_cache)
|
83
|
+
resource.run_action(:attach)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
41
88
|
describe "#subscription_attached?" do
|
42
89
|
let(:cmd) { double("cmd") }
|
43
90
|
let(:output) { "Pool ID: pool123" }
|
@@ -20,7 +20,7 @@ require "spec_helper"
|
|
20
20
|
|
21
21
|
describe Chef::Resource::SystemdUnit do
|
22
22
|
let(:resource) { Chef::Resource::SystemdUnit.new("sysstat-collect.timer") }
|
23
|
-
let(:unit_content_string) { "[Unit]\nDescription
|
23
|
+
let(:unit_content_string) { "[Unit]\nDescription=Run system activity accounting tool every 10 minutes\nDocumentation=foo\nDocumentation=bar\n\n[Timer]\nOnCalendar=*:00/10\n\n[Install]\nWantedBy=sysstat.service\n" }
|
24
24
|
let(:unit_content_hash) do
|
25
25
|
{
|
26
26
|
"Unit" => {
|
data/spec/unit/resource_spec.rb
CHANGED
@@ -1172,21 +1172,23 @@ describe Chef::Resource do
|
|
1172
1172
|
action :base_action3, description: "unmodified base action 3 desc" do; end
|
1173
1173
|
end
|
1174
1174
|
|
1175
|
+
let(:resource_inst) { TestResource.new("TestResource", nil) }
|
1176
|
+
|
1175
1177
|
it "returns nil when no description was provided for the action" do
|
1176
|
-
expect(
|
1178
|
+
expect(resource_inst.action_description(:base_action0)).to eql(nil)
|
1177
1179
|
end
|
1178
1180
|
|
1179
1181
|
context "when action definition is a string" do
|
1180
1182
|
it "returns the description whether a symbol or string is used to look it up" do
|
1181
|
-
expect(
|
1182
|
-
expect(
|
1183
|
+
expect(resource_inst.action_description("string_action")).to eql("a string test")
|
1184
|
+
expect(resource_inst.action_description(:string_action)).to eql("a string test")
|
1183
1185
|
end
|
1184
1186
|
end
|
1185
1187
|
|
1186
1188
|
context "when action definition is a symbol" do
|
1187
1189
|
it "returns the description whether a symbol or string is used to look up" do
|
1188
|
-
expect(
|
1189
|
-
expect(
|
1190
|
+
expect(resource_inst.action_description("symbol_action")).to eql("a symbol test")
|
1191
|
+
expect(resource_inst.action_description(:symbol_action)).to eql("a symbol test")
|
1190
1192
|
end
|
1191
1193
|
end
|
1192
1194
|
|
@@ -1196,14 +1198,23 @@ describe Chef::Resource do
|
|
1196
1198
|
action :base_action3 do; end
|
1197
1199
|
end
|
1198
1200
|
|
1201
|
+
class TestResourceChild2 < TestResource
|
1202
|
+
# We should never see this description
|
1203
|
+
action :base_action2, description: "if you see this in an error, TestResourceChild was polluted with this description" do; end
|
1204
|
+
end
|
1205
|
+
let(:resource_inst) { TestResourceChild.new("TestResource", nil) }
|
1206
|
+
|
1199
1207
|
it "returns original description when a described action is not overridden in child resource" do
|
1200
|
-
expect(
|
1208
|
+
expect(resource_inst.action_description(:base_action1)).to eq "unmodified base action 1 desc"
|
1201
1209
|
end
|
1202
1210
|
it "returns original description when the child resource overrides an inherited action but NOT its description" do
|
1203
|
-
expect(
|
1211
|
+
expect(resource_inst.action_description(:base_action3)).to eq "unmodified base action 3 desc"
|
1212
|
+
end
|
1213
|
+
it "returns new description when the child resource overrides an inherited action and its description" do
|
1214
|
+
expect(resource_inst.action_description(:base_action2)).to eq "modified base action 2 desc"
|
1204
1215
|
end
|
1205
1216
|
it "returns new description when the child resource overrides an inherited action and its description" do
|
1206
|
-
expect(
|
1217
|
+
expect(resource_inst.action_description(:base_action2)).to eq "modified base action 2 desc"
|
1207
1218
|
end
|
1208
1219
|
end
|
1209
1220
|
end
|