summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2015-12-01 13:27:51 -0800
committerLamont Granquist <lamont@scriptkiddie.org>2015-12-01 13:27:51 -0800
commit38fbdf8f7e12338f6c4ec4ec07d5a6f6808a3008 (patch)
tree9e4b0975092bb7552f6e77f66129a342fdad20f4
parent51297afc41eccf653bededf29fea7ed356feb472 (diff)
parentd889330ff7192e14ef5b751faf5b996c0ca8d090 (diff)
downloadchef-38fbdf8f7e12338f6c4ec4ec07d5a6f6808a3008.tar.gz
Merge pull request #4183 from chef/lcg/extract-declare-resource-mixin
extract declare_resource to a mixin and extend API
-rw-r--r--CHANGELOG.md1
-rw-r--r--lib/chef/dsl/declare_resource.rb108
-rw-r--r--lib/chef/dsl/recipe.rb76
-rw-r--r--lib/chef/resource_builder.rb10
-rw-r--r--spec/unit/recipe_spec.rb48
5 files changed, 152 insertions, 91 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12ac806780..fc96279e16 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,7 @@
* [**Maxime Brugidou**](https://github.com/brugidou)
[pr#4052](https://github.com/chef/chef/pull/4052) Add make_child_entry in ChefFS CookbookSubdir
+* [pr#4183](https://github.com/chef/chef/pull/4183) extract declare_resource to a mixin and extend API
* [pr#4185](https://github.com/chef/chef/pull/4185) dpkg provider cleanup
* [pr#4165](https://github.com/chef/chef/pull/4165) Multipackage internal API improvements
* [pr#4081](https://github.com/chef/chef/pull/4081) RFC-037: add `chef_version` and `ohai_version` metadata
diff --git a/lib/chef/dsl/declare_resource.rb b/lib/chef/dsl/declare_resource.rb
new file mode 100644
index 0000000000..52b0cb715d
--- /dev/null
+++ b/lib/chef/dsl/declare_resource.rb
@@ -0,0 +1,108 @@
+#--
+# Author:: Adam Jacob (<adam@opscode.com>)
+# Author:: Christopher Walters (<cw@opscode.com>)
+# Copyright:: Copyright (c) 2008, 2009-2015 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/exceptions'
+
+class Chef
+ module DSL
+ module DeclareResource
+
+ #
+ # Instantiates a resource (via #build_resource), then adds it to the
+ # resource collection. Note that resource classes are looked up directly,
+ # so this will create the resource you intended even if the method name
+ # corresponding to that resource has been overridden.
+ #
+ # @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
+ # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
+ # @param created_at [String] The caller of the resource. Use `caller[0]`
+ # to get the caller of your function. Defaults to the caller of this
+ # function.
+ # @param resource_attrs_block A block that lets you set attributes of the
+ # resource (it is instance_eval'd on the resource instance).
+ #
+ # @return [Chef::Resource] The new resource.
+ #
+ # @example
+ # declare_resource(:file, '/x/y.txy', caller[0]) do
+ # action :delete
+ # end
+ # # Equivalent to
+ # file '/x/y.txt' do
+ # action :delete
+ # end
+ #
+ def declare_resource(type, name, created_at=nil, run_context: self.run_context, create_if_missing: false, &resource_attrs_block)
+ created_at ||= caller[0]
+
+ if create_if_missing
+ begin
+ resource = run_context.resource_collection.find(type => name)
+ return resource
+ rescue Chef::Exceptions::ResourceNotFound
+ end
+ end
+
+ resource = build_resource(type, name, created_at, &resource_attrs_block)
+
+ run_context.resource_collection.insert(resource, resource_type: type, instance_name: name)
+ resource
+ end
+
+ #
+ # Instantiate a resource of the given +type+ with the given +name+ and
+ # attributes as given in the +resource_attrs_block+.
+ #
+ # The resource is NOT added to the resource collection.
+ #
+ # @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
+ # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
+ # @param created_at [String] The caller of the resource. Use `caller[0]`
+ # to get the caller of your function. Defaults to the caller of this
+ # function.
+ # @param resource_attrs_block A block that lets you set attributes of the
+ # resource (it is instance_eval'd on the resource instance).
+ #
+ # @return [Chef::Resource] The new resource.
+ #
+ # @example
+ # build_resource(:file, '/x/y.txy', caller[0]) do
+ # action :delete
+ # end
+ #
+ def build_resource(type, name, created_at=nil, run_context: self.run_context, &resource_attrs_block)
+ created_at ||= caller[0]
+ Thread.exclusive do
+ require 'chef/resource_builder' unless defined?(Chef::ResourceBuilder)
+ end
+
+ Chef::ResourceBuilder.new(
+ type: type,
+ name: name,
+ created_at: created_at,
+ params: @params,
+ run_context: run_context,
+ cookbook_name: cookbook_name,
+ recipe_name: recipe_name,
+ enclosing_provider: self.is_a?(Chef::Provider) ? self : nil
+ ).build(&resource_attrs_block)
+ end
+ end
+ end
+end
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index 26c0ec6768..441fcbbd2c 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -1,7 +1,7 @@
#--
# Author:: Adam Jacob (<adam@opscode.com>)
# Author:: Christopher Walters (<cw@opscode.com>)
-# Copyright:: Copyright (c) 2008, 2009 Opscode, Inc.
+# Copyright:: Copyright (c) 2008, 2009-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,12 +17,12 @@
# limitations under the License.
#
-require 'chef/mixin/convert_to_class_name'
require 'chef/exceptions'
require 'chef/mixin/shell_out'
require 'chef/mixin/powershell_out'
require 'chef/dsl/resources'
require 'chef/dsl/definitions'
+require 'chef/dsl/declare_resource'
class Chef
module DSL
@@ -37,76 +37,7 @@ class Chef
include Chef::DSL::Resources
include Chef::DSL::Definitions
-
- #
- # Instantiates a resource (via #build_resource), then adds it to the
- # resource collection. Note that resource classes are looked up directly,
- # so this will create the resource you intended even if the method name
- # corresponding to that resource has been overridden.
- #
- # @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
- # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
- # @param created_at [String] The caller of the resource. Use `caller[0]`
- # to get the caller of your function. Defaults to the caller of this
- # function.
- # @param resource_attrs_block A block that lets you set attributes of the
- # resource (it is instance_eval'd on the resource instance).
- #
- # @return [Chef::Resource] The new resource.
- #
- # @example
- # declare_resource(:file, '/x/y.txy', caller[0]) do
- # action :delete
- # end
- # # Equivalent to
- # file '/x/y.txt' do
- # action :delete
- # end
- #
- def declare_resource(type, name, created_at=nil, &resource_attrs_block)
- created_at ||= caller[0]
-
- resource = build_resource(type, name, created_at, &resource_attrs_block)
-
- run_context.resource_collection.insert(resource, resource_type: type, instance_name: name)
- resource
- end
-
- #
- # Instantiate a resource of the given +type+ with the given +name+ and
- # attributes as given in the +resource_attrs_block+.
- #
- # The resource is NOT added to the resource collection.
- #
- # @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
- # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
- # @param created_at [String] The caller of the resource. Use `caller[0]`
- # to get the caller of your function. Defaults to the caller of this
- # function.
- # @param resource_attrs_block A block that lets you set attributes of the
- # resource (it is instance_eval'd on the resource instance).
- #
- # @return [Chef::Resource] The new resource.
- #
- # @example
- # build_resource(:file, '/x/y.txy', caller[0]) do
- # action :delete
- # end
- #
- def build_resource(type, name, created_at=nil, &resource_attrs_block)
- created_at ||= caller[0]
-
- Chef::ResourceBuilder.new(
- type: type,
- name: name,
- created_at: created_at,
- params: @params,
- run_context: run_context,
- cookbook_name: cookbook_name,
- recipe_name: recipe_name,
- enclosing_provider: self.is_a?(Chef::Provider) ? self : nil
- ).build(&resource_attrs_block)
- end
+ include Chef::DSL::DeclareResource
def resource_class_for(snake_case_name)
Chef::Resource.resource_for_node(snake_case_name, run_context.node)
@@ -196,7 +127,6 @@ class Chef
end
# Avoid circular references for things that are only used in instance methods
-require 'chef/resource_builder'
require 'chef/resource'
# **DEPRECATED**
diff --git a/lib/chef/resource_builder.rb b/lib/chef/resource_builder.rb
index 9e9f7047a4..72b3788cf0 100644
--- a/lib/chef/resource_builder.rb
+++ b/lib/chef/resource_builder.rb
@@ -1,6 +1,6 @@
#
# Author:: Lamont Granquist (<lamont@chef.io>)
-# Copyright:: Copyright (c) 2015 Opscode, Inc.
+# Copyright:: Copyright (c) 2015-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,10 +18,6 @@
# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb
-require 'chef/exceptions'
-require 'chef/resource'
-require 'chef/log'
-
class Chef
class ResourceBuilder
attr_reader :type
@@ -142,3 +138,7 @@ class Chef
end
end
+
+require 'chef/exceptions'
+require 'chef/resource'
+require 'chef/log'
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index b242f28e11..34f852e2ce 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -3,7 +3,7 @@
# Author:: Christopher Walters (<cw@opscode.com>)
# Author:: Tim Hinderliter (<tim@opscode.com>)
# Author:: Seth Chisamore (<schisamo@opscode.com>)
-# Copyright:: Copyright (c) 2008-2011 Opscode, Inc.
+# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,25 +24,19 @@ require 'chef/platform/resource_priority_map'
describe Chef::Recipe do
- let(:cookbook_repo) { File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) }
-
- let(:cookbook_loader) do
- loader = Chef::CookbookLoader.new(cookbook_repo)
- loader.load_cookbooks
- loader
+ let(:cookbook_collection) do
+ cookbook_repo = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks"))
+ cookbook_loader = Chef::CookbookLoader.new(cookbook_repo)
+ cookbook_loader.load_cookbooks
+ Chef::CookbookCollection.new(cookbook_loader)
end
- let(:cookbook_collection) { Chef::CookbookCollection.new(cookbook_loader) }
-
let(:node) do
Chef::Node.new
end
- let(:events) do
- Chef::EventDispatch::Dispatcher.new
- end
-
let(:run_context) do
+ events = Chef::EventDispatch::Dispatcher.new
Chef::RunContext.new(node, cookbook_collection, events)
end
@@ -305,6 +299,34 @@ describe Chef::Recipe do
zm_resource # force let binding evaluation
expect(run_context.resource_collection.resources(:zen_master => "klopp")).to eq(zm_resource)
end
+
+ it "will insert another resource if create_if_missing is not set (cloned resource as of Chef-12)" do
+ zm_resource
+ recipe.declare_resource(:zen_master, "klopp")
+ expect(run_context.resource_collection.count).to eql(2)
+ end
+
+ it "does not insert two resources if create_if_missing is used" do
+ zm_resource
+ recipe.declare_resource(:zen_master, "klopp", create_if_missing: true)
+ expect(run_context.resource_collection.count).to eql(1)
+ end
+
+ context "injecting a different run_context" do
+ let(:run_context2) do
+ events = Chef::EventDispatch::Dispatcher.new
+ Chef::RunContext.new(node, cookbook_collection, events)
+ end
+
+ it "should insert resources into the correct run_context" do
+ zm_resource
+ recipe.declare_resource(:zen_master, "klopp2", run_context: run_context2)
+ run_context2.resource_collection.lookup("zen_master[klopp2]")
+ expect {run_context2.resource_collection.lookup("zen_master[klopp]")}.to raise_error(Chef::Exceptions::ResourceNotFound)
+ expect {run_context.resource_collection.lookup("zen_master[klopp2]")}.to raise_error(Chef::Exceptions::ResourceNotFound)
+ run_context.resource_collection.lookup("zen_master[klopp]")
+ end
+ end
end
describe "creating a resource with short name" do