[chef] Re: Re: Re: template variables arguments and methods


Chronological Thread 
  • 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.

§