summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2017-03-22 14:26:34 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2017-03-30 11:52:24 -0700
commitd08274d635b046210faf07d7f598fee5b3c3effe (patch)
treeeae7c43c4263749d458c06f609b3c7ef2ef997c2
parent2151e4f1563441fdacc07c16eaaa4273bb88931d (diff)
downloadchef-d08274d635b046210faf07d7f598fee5b3c3effe.tar.gz
Chef-13: Support nameless resources and remove deprecated multi-arg resources
This makes nameless resources work in the DSL: ```ruby apt_update ``` It does it by giving it an empty-string name of "" It also drops support for multi-arg resources, that has been deprecated for some time: ```ruby some_resource "foo", "bar", "baz" ``` Note that multipackage package resources do not use multiple args, but a single argument which is an arry: ```ruby package [ "lsof", "strace", "tcpdump" ] ``` So this change does not affect that usage. Multi-arg has been deprecated for some time now and its not clear that it was ever used by anyone. Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r--lib/chef/dsl/resources.rb9
-rw-r--r--lib/chef/resource_collection/resource_set.rb17
-rw-r--r--spec/integration/recipes/notifies_spec.rb31
-rw-r--r--spec/integration/recipes/recipe_dsl_spec.rb16
-rw-r--r--spec/unit/dsl/resources_spec.rb2
-rw-r--r--spec/unit/recipe_spec.rb12
-rw-r--r--spec/unit/resource_collection/resource_set_spec.rb31
-rw-r--r--spec/unit/resource_spec.rb17
8 files changed, 107 insertions, 28 deletions
diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb
index 36ec018500..4baec22f2e 100644
--- a/lib/chef/dsl/resources.rb
+++ b/lib/chef/dsl/resources.rb
@@ -34,11 +34,10 @@ class Chef
def self.add_resource_dsl(dsl_name)
module_eval(<<-EOM, __FILE__, __LINE__ + 1)
- def #{dsl_name}(*args, &block)
- Chef.deprecated(:internal_api, "Cannot create resource #{dsl_name} with more than one argument. All arguments except the name (\#{args[0].inspect}) will be ignored. This will cause an error in Chef 13. Arguments: \#{args}") if args.size > 1
- declare_resource(#{dsl_name.inspect}, args[0], created_at: caller[0], &block)
- end
- EOM
+ def #{dsl_name}(arg = "", &block)
+ declare_resource(#{dsl_name.inspect}, arg, created_at: caller[0], &block)
+ end
+ EOM
end
def self.remove_resource_dsl(dsl_name)
diff --git a/lib/chef/resource_collection/resource_set.rb b/lib/chef/resource_collection/resource_set.rb
index 2c7c0a0b91..66ccc1ccb3 100644
--- a/lib/chef/resource_collection/resource_set.rb
+++ b/lib/chef/resource_collection/resource_set.rb
@@ -1,6 +1,6 @@
#
# Author:: Tyler Ball (<tball@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,7 +30,10 @@ class Chef
# Matches a single resource lookup specification,
# e.g., "service[nginx]"
- SINGLE_RESOURCE_MATCH = /^(.+)\[(.+)\]$/
+ SINGLE_RESOURCE_MATCH = /^(.+)\[(.*)\]$/
+
+ # Matches e.g. "apt_update" with no name
+ NAMELESS_RESOURCE_MATCH = /^([^\[\]\s]+)$/
def initialize
@resources_by_key = Hash.new
@@ -43,7 +46,7 @@ class Chef
def insert_as(resource, resource_type = nil, instance_name = nil)
is_chef_resource!(resource)
resource_type ||= resource.resource_name
- instance_name ||= resource.name
+ instance_name ||= resource.name || ""
key = create_key(resource_type, instance_name)
@resources_by_key[key] = resource
end
@@ -118,7 +121,7 @@ class Chef
case query_object
when Chef::Resource
true
- when SINGLE_RESOURCE_MATCH, MULTIPLE_RESOURCE_MATCH
+ when SINGLE_RESOURCE_MATCH, MULTIPLE_RESOURCE_MATCH, NAMELESS_RESOURCE_MATCH
true
when Hash
true
@@ -142,7 +145,7 @@ class Chef
private
- def create_key(resource_type, instance_name)
+ def create_key(resource_type, instance_name = "")
"#{resource_type}[#{instance_name}]"
end
@@ -171,6 +174,10 @@ class Chef
resource_type = $1
name = $2
results << lookup(create_key(resource_type, name))
+ when NAMELESS_RESOURCE_MATCH
+ resource_type = $1
+ name = ""
+ results << lookup(create_key(resource_type, name))
else
raise ArgumentError, "Bad string format #{arg}, you must have a string like resource_type[name]!"
end
diff --git a/spec/integration/recipes/notifies_spec.rb b/spec/integration/recipes/notifies_spec.rb
index 000f5e37bf..6f6a0f06b0 100644
--- a/spec/integration/recipes/notifies_spec.rb
+++ b/spec/integration/recipes/notifies_spec.rb
@@ -8,6 +8,37 @@ describe "notifications" do
let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) }
let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
+ when_the_repository "notifies a nameless resource" do
+ before do
+ directory "cookbooks/x" do
+ file "recipes/default.rb", <<-EOM
+ apt_update do
+ action :nothing
+ end
+ log "foo" do
+ notifies :nothing, 'apt_update', :delayed
+ end
+ log "bar" do
+ notifies :nothing, 'apt_update[]', :delayed
+ end
+ EOM
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ # our delayed notification should run at the end of the parent run_context after the baz resource
+ expect(result.stdout).to match(/\* apt_update\[\] action nothing \(skipped due to action :nothing\)\s+\* log\[foo\] action write\s+\* log\[bar\] action write\s+\* apt_update\[\] action nothing \(skipped due to action :nothing\)/)
+ result.error!
+ end
+ end
+
when_the_repository "notifies delayed one" do
before do
directory "cookbooks/x" do
diff --git a/spec/integration/recipes/recipe_dsl_spec.rb b/spec/integration/recipes/recipe_dsl_spec.rb
index a408bbb0d7..14cee0e1fd 100644
--- a/spec/integration/recipes/recipe_dsl_spec.rb
+++ b/spec/integration/recipes/recipe_dsl_spec.rb
@@ -59,20 +59,12 @@ describe "Recipe DSL methods" do
expect(BaseThingy.created_resource).to eq BaseThingy
end
- it "errors out when you call base_thingy do ... end in a recipe" do
- expect_converge do
- base_thingy { ; }
- end.to raise_error(ArgumentError, "You must supply a name when declaring a base_thingy resource")
- end
-
- it "emits a warning when you call base_thingy 'foo', 'bar' do ... end in a recipe" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ it "does not errors when you call base_thingy do ... end in a recipe" do
recipe = converge do
- base_thingy "foo", "bar" do
- end
+ base_thingy { ; }
end
- expect(recipe.logged_warnings).to match(/Cannot create resource base_thingy with more than one argument. All arguments except the name \("foo"\) will be ignored. This will cause an error in Chef 13. Arguments: \["foo", "bar"\]/)
- expect(BaseThingy.created_name).to eq "foo"
+ expect(recipe.logged_warnings).to eq ""
+ expect(BaseThingy.created_name).to eq ""
expect(BaseThingy.created_resource).to eq BaseThingy
end
diff --git a/spec/unit/dsl/resources_spec.rb b/spec/unit/dsl/resources_spec.rb
index dc05f8bcf4..5354505df8 100644
--- a/spec/unit/dsl/resources_spec.rb
+++ b/spec/unit/dsl/resources_spec.rb
@@ -80,6 +80,6 @@ describe Chef::DSL::Resources do
test_resource {}
end
end
- it { is_expected.to eq [[:test_resource, nil]] }
+ it { is_expected.to eq [[:test_resource, ""]] }
end
end
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index cb500da34a..8a2719120a 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -74,10 +74,14 @@ describe Chef::Recipe do
expect { recipe.not_home("not_home_resource") }.to raise_error(NameError)
end
- it "should require a name argument" do
- expect do
- recipe.cat
- end.to raise_error(ArgumentError)
+ it "does not require a name argument and looks up with empty brackets" do
+ recipe.zen_master
+ expect(run_context.resource_collection.lookup("zen_master[]").name).to eql("")
+ end
+
+ it "does not require a name argument and looks up with bare word" do
+ recipe.zen_master
+ expect(run_context.resource_collection.lookup("zen_master").name).to eql("")
end
it "should allow regular errors (not NameErrors) to pass unchanged" do
diff --git a/spec/unit/resource_collection/resource_set_spec.rb b/spec/unit/resource_collection/resource_set_spec.rb
index 20f6f70911..ecf3e2707f 100644
--- a/spec/unit/resource_collection/resource_set_spec.rb
+++ b/spec/unit/resource_collection/resource_set_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Tyler Ball (<tball@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -162,6 +162,35 @@ describe Chef::ResourceCollection::ResourceSet do
it "raises an error when attempting to find a resource that does not exist" do
expect { collection.find("script[nonesuch]") }.to raise_error(Chef::Exceptions::ResourceNotFound)
end
+
+ context "nameless resources" do
+ let(:zen_master_name) { "" }
+
+ it "looks up nameless resources with find without brackets" do
+ collection.insert_as(zen_master)
+ expect(collection.find("zen_master")).to eq(zen_master)
+ end
+
+ it "looks up nameless resources with find with empty brackets" do
+ collection.insert_as(zen_master)
+ expect(collection.find("zen_master[]")).to eq(zen_master)
+ end
+
+ it "looks up nameless resources with find with empty string hash key" do
+ collection.insert_as(zen_master)
+ expect(collection.find(zen_master: "")).to eq(zen_master)
+ end
+
+ it "looks up nameless resources with lookup with empty brackets" do
+ collection.insert_as(zen_master)
+ expect(collection.lookup("zen_master[]")).to eq(zen_master)
+ end
+
+ it "looks up nameless resources with lookup with the resource" do
+ collection.insert_as(zen_master)
+ expect(collection.lookup(zen_master)).to eq(zen_master)
+ end
+ end
end
describe "validate_lookup_spec!" do
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index a806c5d1d9..6285bad50a 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -284,6 +284,23 @@ describe Chef::Resource do
resource.notifies :reload, run_context.resource_collection.find(:zen_master => "coffee, tea")
expect(resource.delayed_notifications.detect { |e| e.resource.name == "coffee, tea" && e.action == :reload }).not_to be_nil
end
+
+ it "notifies a resource without a name via a string name with brackets" do
+ run_context.resource_collection << Chef::Resource::ZenMaster.new("")
+ resource.notifies :reload, "zen_master[]"
+ end
+
+ it "notifies a resource without a name via a string name without brackets" do
+ run_context.resource_collection << Chef::Resource::ZenMaster.new("")
+ resource.notifies :reload, "zen_master"
+ expect(resource.delayed_notifications.first.resource).to eql("zen_master")
+ end
+
+ it "notifies a resource without a name via a hash name with an empty string" do
+ run_context.resource_collection << Chef::Resource::ZenMaster.new("")
+ resource.notifies :reload, zen_master: ""
+ expect(resource.delayed_notifications.first.resource).to eql(zen_master: "")
+ end
end
describe "subscribes" do