- From: AJ Christensen <
>
- To: "
" <
>
- Subject: [chef] Re: Re: Re: template variables arguments and methods
- Date: Wed, 11 Mar 2015 11:52:08 +1300
Probably doesn't even need an RFC, just an issue/PR may suffice. Nice
sleuth work. I'd support it. I know of at least a few cases where
methods added to the Recipe via helper would benefit from this within
the provider's action blocks, resource bodies.
cheers,
--aj
On Wed, Mar 11, 2015 at 11:12 AM, Benjamin Bytheway
<
>
wrote:
>
I've done a bit of digging on this. Because of the way Chef is using
>
instance_eval, only local variables (and not methods) from recipes are
>
available to resource blocks.
>
>
For a more thorough discussion of how instance_eval works in this case, this
>
is pretty much the definitive article:
>
>
http://www.skorks.com/2013/03/a-closure-is-not-always-a-closure-in-ruby/
>
>
There is a caveat to this, however. The "correct" work is being done by chef
>
to ensure that provider methods are available to resource blocks.
>
>
In the recipe dsl, we have an explicit check to ensure that providers and
>
only providers are given this privilege:
>
>
enclosing_provider: self.is_a?(Chef::Provider) ? self : nil
>
>
https://github.com/chef/chef/blob/e1e0f850507da9cbf0e4247dcc92e6431a8cb1a1/lib/chef/dsl/recipe.rb#L143
>
>
And there is accompanying method_missing in resource to check if the
>
provider responds to that method and passes the call through if it does.
>
>
https://github.com/chef/chef/blob/2603e2153d6ab50179d2278025a51579edb9033f/lib/chef/resource.rb#L955
>
>
Is there a reason we couldn't generalize this, so that DRY recipes with
>
methods could be used? All that would have to happen is a little name
>
hygeine, changing enclosing_provider to something like enclosing_context and
>
changing the recipe dsl to:
>
>
enclosing_context: self
>
>
Another option is to add an enclosing_context instance variable to the
>
resource class, and then have the resource builder pass in the original
>
"self" that the resource block closure was created with. Something like:
>
>
resource.enclosing_context = block.binding.eval "self"
>
>
Then you just have method missing in the resource class check both the
>
enclosing_provider and enclosing_context for the method.
>
>
I have hit the need for recipe methods so many times, and cursed as I had to
>
implement things as local variables instead. It really would only take
>
changing 6-10 lines of code to have Chef support them.
>
>
Is this writing up an RFC/Patch for? Has it any chance of being accepted?
>
>
-Ben Bytheway
>
>
>
>
On Mon, Mar 9, 2015 at 4:45 PM, Brandon Richins
>
<
>
>
wrote:
>
>
>
> I have to correct my question. #3 doesn’t work either. All my @bar
>
> sections in my erb are blank when rendered.
>
>
>
> Why won’t methods defined on the recipe evaluate before passing control to
>
> the ERB?
>
>
>
> Brandon Richins
>
>
>
> From: Brandon Richins
>
> <
>
>
> Reply-To:
>
> "
"
>
>
>
> <
>
>
> Date: Monday, March 9, 2015 at 4:29 PM
>
> To:
>
> "
"
>
>
>
> <
>
>
> Subject: [chef] template variables arguments and methods
>
>
>
> I have a question about Chef templates, variables arguments, and methods.
>
> When using templates in a recipe, I sometimes want to use a method instead
>
> of a local variable as the value to variable key. ex. def baz { 'baz' } vs
>
> baz = 'baz'. When I try to use baz as a method in the template variables
>
> section, using the syntax of #1 and #2, Chef fails to converge the template
>
> and raises an undefined method error for baz. For #1 and #2 if baz is a
>
> local variable in the template it works fine. Today I discovered syntax #4
>
> which worked when baz is a method.
>
>
>
> I’m going to show my own ignorance about Ruby now. I understand { bar:
>
> 'b' } to be a Hash in Ruby. So I think #1 is passing a Hash to a
>
> “variables” method on a template object. For #2 I was guessing it was
>
> coercing the list of arguments into a Hash (kind of like varargs in Java).
>
> For #3 I was guessing it’s evaluating the outer {} as a block and the inner
>
> {} as a Hash. Can you confirm these assumptions?
>
>
>
> So why do #1 and #2 raise an undefined method error and #3 works. It
>
> seems the Chef/Template DSL is treating methods differently than local
>
> variables when it comes to templates.
>
>
>
> def baz
>
> 'baz'
>
> end
>
>
>
> 1) Parentheses then braces
>
> -----------------------------------
>
> template 'foo' do
>
> variables({
>
> bar: baz,
>
> a: 'b',
>
> })
>
> end
>
>
>
> 2) Parentheses and no braces
>
> -----------------------------------
>
> template 'foo' do
>
> variables(
>
> bar: baz,
>
> a: 'b',
>
> )
>
> end
>
>
>
> 4) Double braces
>
> -----------------------------------
>
> template 'foo' do
>
> variables{{
>
> bar: baz,
>
> a: 'b',
>
> }}
>
> end
>
>
>
> Thanks,
>
>
>
> Brandon Richins
>
>
Archive powered by MHonArc 2.6.16.