summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-11-06 10:39:41 -0800
committerJohn Keiser <john@johnkeiser.com>2015-11-06 10:40:16 -0800
commitc37e8934f995db7caa235544886dc648b2cb38aa (patch)
tree65e2dc79a26621f9ef66d727ba3588b4604c5cab
parentf474f98750fe70e0264bf80793e578b739c08206 (diff)
downloadchef-jk/recipe_block.tar.gz
IN PROGRESS IGNOREjk/recipe_block
-rw-r--r--lib/chef/dsl/cheffish_resources.rb0
-rw-r--r--lib/chef/dsl/resources.rb3
-rw-r--r--lib/chef/property/standard_types.rb43
-rw-r--r--lib/chef/property/standard_types/array_property.rb13
-rw-r--r--lib/chef/property/standard_types/proc_property.rb60
-rw-r--r--lib/chef/property/standard_types/set_property.rb13
-rw-r--r--lib/chef/resource.rb4
-rw-r--r--lib/chef/resource/recipe_block.rb80
-rw-r--r--spec/unit/property/standard_types_spec.rb35
9 files changed, 251 insertions, 0 deletions
diff --git a/lib/chef/dsl/cheffish_resources.rb b/lib/chef/dsl/cheffish_resources.rb
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/chef/dsl/cheffish_resources.rb
diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb
index 49588ed516..ef2487ebcc 100644
--- a/lib/chef/dsl/resources.rb
+++ b/lib/chef/dsl/resources.rb
@@ -7,6 +7,9 @@ class Chef
#
# @api private
module Resources
+ def self.add_lazy_resource_dsl(dsl_name, requires: nil, resource_class: nil, provider_class: nil)
+
+ end
def self.add_resource_dsl(dsl_name)
begin
module_eval(<<-EOM, __FILE__, __LINE__+1)
diff --git a/lib/chef/property/standard_types.rb b/lib/chef/property/standard_types.rb
new file mode 100644
index 0000000000..e43177b7a3
--- /dev/null
+++ b/lib/chef/property/standard_types.rb
@@ -0,0 +1,43 @@
+#
+# Author:: John Keiser (<jkeiser@chef.io)
+# Copyright:: Copyright (c) 2015 Opscode, 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/mixin/properties'
+require 'chef/property/standard_types/proc_property'
+
+class Chef
+ class Property
+ module StandardTypes
+ include Chef::Mixin::Properties
+ Boolean = property_type(is: [ true, false ], default: false)
+
+ #
+ # Treat `property :x, Proc, ...` the same as `property :x, ProcProperty, ...`
+ # so that you get the nicer property DSL letting you say x { ... }
+ # instead of just x proc { ... }
+ #
+ def property(name, type=NOT_PASSED, **options)
+ if type != NOT_PASSED && type.is_a?(Class)
+ if type <= Proc
+ type = ProcProperty
+ end
+ end
+ super
+ end
+ end
+ end
+end
diff --git a/lib/chef/property/standard_types/array_property.rb b/lib/chef/property/standard_types/array_property.rb
new file mode 100644
index 0000000000..a091888ead
--- /dev/null
+++ b/lib/chef/property/standard_types/array_property.rb
@@ -0,0 +1,13 @@
+class Chef
+ class Property
+ module StandardTypes
+ class ArrayProperty < Property
+ def initialize(**options)
+ options[:is] ||= Array
+ options[:coerce] ||= proc { |v| v.is_a?(Array) ? v : Array(v) }
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/property/standard_types/proc_property.rb b/lib/chef/property/standard_types/proc_property.rb
new file mode 100644
index 0000000000..09461d76ba
--- /dev/null
+++ b/lib/chef/property/standard_types/proc_property.rb
@@ -0,0 +1,60 @@
+#
+# Author:: John Keiser (<jkeiser@chef.io)
+# Copyright:: Copyright (c) 2015 Opscode, 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.
+#
+
+class Chef
+ class Property
+ module StandardTypes
+ class ProcProperty < Property
+ # "is" defaults to `Proc` (we validate that it is a Proc)
+ def initialize(is: Proc, **options)
+ super
+ end
+
+ # Allow the
+ def emit_dsl
+ # We don't create the getter/setter if it's a custom property; we will
+ # be using the existing getter/setter to manipulate it instead.
+ return if !instance_variable_name
+
+ # We prefer this form because the property name won't show up in the
+ # stack trace if you use `define_method`.
+ declared_in.class_eval <<-EOM, __FILE__, __LINE__+1
+ def #{name}(value=NOT_PASSED, &block)
+ raise ArgumentError, "Cannot specify both value and block when setting #{name}" if block && value != NOT_PASSED
+ value = block if block
+ self.class.properties[#{name.inspect}].call(self, value)
+ end
+ def #{name}=(value)
+ self.class.properties[#{name.inspect}].set(self, value)
+ end
+ EOM
+ rescue SyntaxError
+ # If the name is not a valid ruby name, we use define_method.
+ declared_in.define_method(name) do |value=NOT_PASSED|
+ raise ArgumentError, "Cannot specify both value and block when setting #{name}" if block && value != NOT_PASSED
+ value = block if block
+ self.class.properties[name].call(self, value)
+ end
+ declared_in.define_method("#{name}=") do |value|
+ self.class.properties[name].set(self, value)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/property/standard_types/set_property.rb b/lib/chef/property/standard_types/set_property.rb
new file mode 100644
index 0000000000..6e7606bc81
--- /dev/null
+++ b/lib/chef/property/standard_types/set_property.rb
@@ -0,0 +1,13 @@
+class Chef
+ class Property
+ module StandardTypes
+ class SetProperty < Property
+ def initialize(**options)
+ options[:is] ||= Set
+ options[:coerce] ||= proc { |v| v.is_a?(Set) ? v : Set.new(v) }
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 90453bd00e..fe2fcc6d9b 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -36,6 +36,7 @@ require 'chef/platform'
require 'chef/resource/resource_notification'
require 'chef/provider_resolver'
require 'chef/resource_resolver'
+require 'chef/property/standard_types'
require 'set'
require 'chef/mixin/deprecation'
@@ -64,6 +65,9 @@ class Chef
# Bring in `property` and `property_type`
include Chef::Mixin::Properties
+ # Bring in standard types like Boolean and ProcProperty
+ include Chef::Property::StandardTypes
+
#
# The name of this particular resource.
#
diff --git a/lib/chef/resource/recipe_block.rb b/lib/chef/resource/recipe_block.rb
new file mode 100644
index 0000000000..f823a97a06
--- /dev/null
+++ b/lib/chef/resource/recipe_block.rb
@@ -0,0 +1,80 @@
+#
+# Author:: John Keiser (<jkeiser@chef.io)
+# Copyright:: Copyright (c) 2015 Opscode, 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/resource'
+
+class Chef
+ class Resource
+ #
+ # A converge-time recipe.
+ #
+ # Resources inside the block behave exactly the same as resources
+ # in a Chef::Resource#action block.
+ #
+ # Example:
+ #
+ # file '/x.txt' do
+ # content 'hi'
+ # end
+ # recipe_block 'make a file with the length of /x.txt in it' do
+ # block do
+ # # Since we are in a recipe_block, the file '/x.txt' block has
+ # # already converged and we can do this calculation here!
+ # length_of_file = IO.read('/x.txt').length
+ # file '/x-length.txt' do
+ # content "Length: #{length_of_file}"
+ # end
+ # # However, if we tried to IO.read('/x-length.txt') here, it would
+ # # fail, because the entire block is first compiled and then converged.
+ # end
+ # end
+ #
+ class RecipeBlock < Chef::Resource
+ resource_name :recipe_block
+
+ #
+ # A ruby block containing the recipe that will be run.
+ #
+ # All recipe DSL is valid here too.
+ #
+ # @example Using a block argument
+ # recipe_block 'hi' do
+ # block do
+ # file '/x.txt'
+ # end
+ # end
+ #
+ # @example Passing the proc directly
+ # recipe_block 'hi' do
+ # x = proc { file '/x.txt '}
+ # block x
+ # end
+ #
+ property :block, ProcProperty
+
+ #
+ # Compiles and converges the block as a recipe. The resource will be
+ # marked updated (and notify) if any of the resources in the recipe update.
+ # Behavior is identical to Chef::Resource#action.
+ #
+ action :run do
+ instance_eval(&recipe_block)
+ end
+ end
+ end
+end
diff --git a/spec/unit/property/standard_types_spec.rb b/spec/unit/property/standard_types_spec.rb
new file mode 100644
index 0000000000..12e18b45d3
--- /dev/null
+++ b/spec/unit/property/standard_types_spec.rb
@@ -0,0 +1,35 @@
+require 'support/shared/integration/integration_helper'
+
+module StandardTypesTests
+
+ describe Chef::Property::StandardTypes do
+ include IntegrationSupport
+
+ describe "Boolean" do
+ Boolean
+ context "With a resource with a Boolean property" do
+ class BooleanResource < Chef::Resource
+ property :x, Boolean
+ end
+
+ let(:resource) { BooleanResource.new("blah") }
+
+ it "defaults to false" do
+ expect(resource.x).to eq false
+ end
+ it "accepts true" do
+ resource.x true
+ expect(resource.x).to eq true
+ end
+ it "accepts false" do
+ resource.x false
+ expect(resource.x).to eq false
+ end
+ it "does not accept 1" do
+ expect { resource.x 1 }.to raise Chef::Exceptions::ValidationError
+ end
+ end
+ end
+ end
+
+end