- variables vs direct attribute access


#1

Ohai chefs!

I just having a talk with a team member about why or why not use
"variables" with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing this.
Because if you can access attributes directly inside the template, and
attributes are compiled an resolved on compile time. ¿Why are you going to
want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!

Si necesitas una máquina para hacer algo y no la compras al final te darás
cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford

Alberto


#2

Variable could be something calculated or logically choosen. The idea is as with mvc models to keep logic away of the template as possible.

Exemple for a jee server you may calculate the heap value from Os type and available ram, it’s better to have it inside the recipe than the template.

This way you may set an arbitrary value for rendering (on test to limit the value) instead of cloning the template.

So IMHO not a fail, a valuable feature to use wisely to avoid complex logic in template when it makes sense

---- aL. a écrit ----

Ohai chefs!

I just having a talk with a team member about why or why not use “variables” with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing this. Because if you can access attributes directly inside the template, and attributes are compiled an resolved on compile time. ¿Why are you going to want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!


Si necesitas una máquina para hacer algo y no la compras al final te darás cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford

Alberto


#3

I don’t have any hard evidence about this, but I suspect that you may get better error messages outside the template.

-T

On Oct 31, 2014, at 5:20 AM, Tensibai Zhaoying tensibai@iabis.net wrote:

Variable could be something calculated or logically choosen. The idea is as with mvc models to keep logic away of the template as possible.

Exemple for a jee server you may calculate the heap value from Os type and available ram, it’s better to have it inside the recipe than the template.

This way you may set an arbitrary value for rendering (on test to limit the value) instead of cloning the template.

So IMHO not a fail, a valuable feature to use wisely to avoid complex logic in template when it makes sense

---- aL. a écrit ----

Ohai chefs!

I just having a talk with a team member about why or why not use “variables” with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing this. Because if you can access attributes directly inside the template, and attributes are compiled an resolved on compile time. ¿Why are you going to want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!

Si necesitas una máquina para hacer algo y no la compras al final te darás cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford
Alberto


#4

On Oct 31, 2014, at 9:47 AM, Tyler tball@getchef.com wrote:

I don’t have any hard evidence about this, but I suspect that you may get better error messages outside the template.

I think that used to be true in old versions of Chef, but not anymore — template errors now show locality.

As others pointed out, if you’re just printing node attributes in the template then it’s kind of a wash either way. But I try to avoid doing really complicated logic in templates, for the sole reason of readability. Interspersing control structures with <%- and %> ERB escaping makes my head hurt.

Also, yeah, there are software design arguments (separation of model/controller from view) too.

  • Julian

#5

you dont need lazy variable unless you have very specific requirements
(like the value of that variable depends on another computed attribute at
compile time) .
Both style allows nil value, and can be a failure point and there are
several ways to address that, like chefspec assertion etc. There’s an RFC
on template verification attribute (like guards) which might help in this.

regards
ranjib

On Fri, Oct 31, 2014 at 4:49 AM, aL. ocholetrasaleatorias@gmail.com wrote:

Ohai chefs!

I just having a talk with a team member about why or why not use
"variables" with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing this.
Because if you can access attributes directly inside the template, and
attributes are compiled an resolved on compile time. ¿Why are you going to
want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!

Si necesitas una máquina para hacer algo y no la compras al final te darás
cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford

Alberto


#6

A whole lot of the pain involved in attribute precedence levels could
be avoided if people would construct a variable in their recipes (or in
a library) that was composed of inputs with whatever precedence their
logic implied, and then pass that plain ruby variable into resources
like templates.

Running the node object through everything can be elegant and simple,
but as soon as you start to fight with attributes and go looking for
force_default, then you should really consider just rubbing some plain
ruby on the problem and also introducing multiple node attributes
rather than trying to make one node attribute do all the work.

On Fri Oct 31 04:49:46 2014, aL. wrote:

Ohai chefs!

I just having a talk with a team member about why or why not use
"variables" with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing
this. Because if you can access attributes directly inside the
template, and attributes are compiled an resolved on compile time.
¿Why are you going to want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!

Si necesitas una máquina para hacer algo y no la compras al final te
darás cuenta de que has pagado lo mismo y no tienes la máquina.–Henry
Ford

Alberto


#7

This topic came up in the #chef irc channel the other day. I said some
words. Initial question here:

https://botbot.me/freenode/chef/2014-10-27/?msg=24305421&page=6

Conversation is mixed with some other threads a bit, but ends after about
30 minutes.

Hope this helps
Joshua

On Fri, Oct 31, 2014 at 5:49 AM, aL. ocholetrasaleatorias@gmail.com wrote:

Ohai chefs!

I just having a talk with a team member about why or why not use
"variables" with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing this.
Because if you can access attributes directly inside the template, and
attributes are compiled an resolved on compile time. ¿Why are you going to
want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!

Si necesitas una máquina para hacer algo y no la compras al final te darás
cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford

Alberto


Joshua Timberman, Chef.


#8

Here’s a concrete example of what I’m talking about from the chef-solo
cookbooks that are used internal to the chef-server:

This example still uses the node object to gather inputs for most
cases, which will get rendered into the hash and passed to the
template. It avoids fiddling with the node object directly in the
template so that the recipe has more control over injecting values into
the template without having to deal with attribute precedence. It
carves out a limited namespace from the node attributes which concerns
the cookbook, which is probably a best practice and will save typing
inside of the template itself. There is also a concrete example here
of the recipe completely overriding the
node[‘private_chef’][‘opscode-expander’][‘reindexer’] variable and
forcing it to false (a good example of avoiding hurting your brain with
default/override/force_override/force_default attribute precedence
level issues and just asserting that the code in the cookbook always
wins because of $RUBY).

So, I’d consider at least variables(node[‘my_cookbook’].to_hash) to be
the most future-proof way to access node attributes from templates. If
you start hard coding node attributes in templates then at some point
if you need the recipe code to massage the node attributes for some
reason then you’re either stuck dealing with learning about
force_default and garbage precedence level issues to try to get the
node attribute ‘right’, or you potentially have to rewrite the template
in order to inject correctly massaged values.

And I can’t reiterate too much over the power of avoiding attributes
once you are in recipe code and just using $RUBY. You can override
automatic node attributes with pure ruby (the highest precedence
level), you can combine attributes and do computed attributes however
you like. You can have attributes and search results and whatever
other inputs and determine whatever precedence for combining them and
then render those and it will do exactly what your code specifies. If
you tie yourself to injecting real node attributes into resources then
to manipulate those from recipe code you are stuck manipulating node
attributes from recipes, which typically ends in tears.

On Fri Oct 31 10:15:15 2014, Lamont Granquist wrote:

A whole lot of the pain involved in attribute precedence levels could
be avoided if people would construct a variable in their recipes (or
in a library) that was composed of inputs with whatever precedence
their logic implied, and then pass that plain ruby variable into
resources like templates.

Running the node object through everything can be elegant and simple,
but as soon as you start to fight with attributes and go looking for
force_default, then you should really consider just rubbing some plain
ruby on the problem and also introducing multiple node attributes
rather than trying to make one node attribute do all the work.

On Fri Oct 31 04:49:46 2014, aL. wrote:

Ohai chefs!

I just having a talk with a team member about why or why not use
"variables" with lazy or not on template resources.

I dont know what is the right way or the “bad practice” way of doing
this. Because if you can access attributes directly inside the
template, and attributes are compiled an resolved on compile time.
¿Why are you going to want to use variables params on templates?

Could be that varibles were just another fail point on the chain, right?

Thanks a lot!!!

Si necesitas una máquina para hacer algo y no la compras al final te
darás cuenta de que has pagado lo mismo y no tienes la máquina.–Henry
Ford

Alberto


#9

Thankyou all guys for your explanations!

My brain was on holidays that day, when i wrote the question, but in some
way your answers bring some light to the issue!

Putting it all together:

  • Avoid logic on template as possible.
  • Use variables on template resources when you need logic/pre-proccessing.
    Putting logic on recipe’s side.
  • If you give node attribute values directly or computed to the template,
    through variables. Better do it with lazy, so other cookbooks can override
    those attributes later on the runlist.

What do you guys think about my summary here?
should i put this on a “Best Practices” Chef’s manual? hehe?

Regards!


#10

On 11/1/14, 4:48 PM, aL. wrote:

Thankyou all guys for your explanations!

My brain was on holidays that day, when i wrote the question, but in
some way your answers bring some light to the issue!

Putting it all together:

  • Avoid logic on template as possible.
  • Use variables on template resources when you need
    logic/pre-proccessing. Putting logic on recipe’s side.
  • If you give node attribute values directly or computed to the
    template, through variables. Better do it with lazy, so other
    cookbooks can override those attributes later on the runlist.
    generally, no. if you want to override an attribute later in the
    run_list you want to override it in the attributes files. the node
    attributes which are used for input should be finalized when you’re done
    parsing attributes files. that is the job of the stages in the
    chef-client converge which prior to recipe code – assembling the input
    state of the node object. the recipes should consume that object and
    shouldn’t need to mutate it.

#11

What if you need to modify an attribute only when including a recipe?

i.e. I have a third_party.rb recipe on my company_openssh cookbook that
enables third_party system group to login via ssh, this is done by adding
that grop to the [openssh][‘allowed_groups’] attribute. I cant do this on
attribute files because that way, the group access is always allowed.

i.e. I I want to open 443 on my node firewall only when i enable the
http_ssl, by including that recipe on a segurewebserer role

May be im doing somethin wrong, but i think that there are situations where
you only need some attributes loaded only when a recipe is being applied.
Not all those attributes being loaded when you include the “default” recipe
on the node runlist. Or when you need to do some complex logic to calculate
the attribute value.

Hope i’m explaining my ideas rigth!!


Si necesitas una máquina para hacer algo y no la compras al final te darás
cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford

Alberto

On Sun, Nov 2, 2014 at 3:05 AM, Lamont Granquist lamont@opscode.com wrote:

On 11/1/14, 4:48 PM, aL. wrote:

Thankyou all guys for your explanations!

My brain was on holidays that day, when i wrote the question, but in some
way your answers bring some light to the issue!

Putting it all together:

  • Avoid logic on template as possible.
  • Use variables on template resources when you need
    logic/pre-proccessing. Putting logic on recipe’s side.
  • If you give node attribute values directly or computed to the
    template, through variables. Better do it with lazy, so other cookbooks can
    override those attributes later on the runlist.

generally, no. if you want to override an attribute later in the
run_list you want to override it in the attributes files. the node
attributes which are used for input should be finalized when you’re done
parsing attributes files. that is the job of the stages in the chef-client
converge which prior to recipe code – assembling the input state of the
node object. the recipes should consume that object and shouldn’t need to
mutate it.


#12

Another place you’ll want to use variables is when you don’t want the data
you’re putting into the template to be saved in the node attributes after
the converge. For example, data from an encrypted data bag shouldn’t be
stored on the node. In that case, only variables will do.

On Mon, Nov 3, 2014 at 3:32 AM, aL. ocholetrasaleatorias@gmail.com wrote:

What if you need to modify an attribute only when including a recipe?

i.e. I have a third_party.rb recipe on my company_openssh cookbook that
enables third_party system group to login via ssh, this is done by adding
that grop to the [openssh][‘allowed_groups’] attribute. I cant do this on
attribute files because that way, the group access is always allowed.

i.e. I I want to open 443 on my node firewall only when i enable the
http_ssl, by including that recipe on a segurewebserer role

May be im doing somethin wrong, but i think that there are situations
where you only need some attributes loaded only when a recipe is being
applied. Not all those attributes being loaded when you include the
"default" recipe on the node runlist. Or when you need to do some complex
logic to calculate the attribute value.

Hope i’m explaining my ideas rigth!!


Si necesitas una máquina para hacer algo y no la compras al final te darás
cuenta de que has pagado lo mismo y no tienes la máquina.–Henry Ford

Alberto

On Sun, Nov 2, 2014 at 3:05 AM, Lamont Granquist lamont@opscode.com
wrote:

On 11/1/14, 4:48 PM, aL. wrote:

Thankyou all guys for your explanations!

My brain was on holidays that day, when i wrote the question, but in
some way your answers bring some light to the issue!

Putting it all together:

  • Avoid logic on template as possible.
  • Use variables on template resources when you need
    logic/pre-proccessing. Putting logic on recipe’s side.
  • If you give node attribute values directly or computed to the
    template, through variables. Better do it with lazy, so other cookbooks can
    override those attributes later on the runlist.

generally, no. if you want to override an attribute later in the
run_list you want to override it in the attributes files. the node
attributes which are used for input should be finalized when you’re done
parsing attributes files. that is the job of the stages in the chef-client
converge which prior to recipe code – assembling the input state of the
node object. the recipes should consume that object and shouldn’t need to
mutate it.


Justin Dossey
Practice Owner
New Context Services, Inc


#13

Sorry, responding to Alberto, seem to have deleted that e-mail that I
meant to save to respond to later…

So right now you’re calling company_openssh::third_party out of the
run_list? In that case what you’ve got a role, and you should have a
role like role_third_party_access which sets the node attribute. If you
don’t like roles, then you need a role cookbook and put
role_third_party_access::default (which may be empty) and have an
attribute file that sets the attribute. When you go with role cookbooks
you need to have one role per cookbook, burying your roles inside of
other cookbooks is bad practice (which does mean lots of role cookbooks,
which does mean lots of git repos if you’re doing
one-git-repo-per-cookbook, which is the tradeoff that you make with role
cookbooks). If none of that works and you’re doing something more
complicated than setting up a role and have nasty conditional logic
around the include_recipe (which I’d argue is still code smell and you
need to ask yourself why you’re doing that), then you should pass state
between cookbook using the node.run_state.

On 11/4/14, 10:04 AM, Justin Dossey wrote:

Another place you’ll want to use variables is when you don’t want the
data you’re putting into the template to be saved in the node
attributes after the converge. For example, data from an encrypted
data bag shouldn’t be stored on the node. In that case, only
variables will do.

On Mon, Nov 3, 2014 at 3:32 AM, aL. <ocholetrasaleatorias@gmail.com
mailto:ocholetrasaleatorias@gmail.com> wrote:

What if you need to modify an attribute only when including a recipe?

i.e. I have a third_party.rb recipe on my company_openssh cookbook
that enables third_party system group to login via ssh, this is
done by adding that grop to the [openssh]['allowed_groups']
attribute. I cant do this on attribute files because that way, the
group access is always allowed.

i.e. I I want to open 443 on my node firewall only when i enable
the http_ssl, by including that recipe on a segurewebserer role

May be im doing somethin wrong, but i think that there are
situations where you only need some attributes loaded only when a
recipe is being applied. Not all those attributes being loaded
when you include the "default" recipe on the node runlist. Or when
you need to do some complex logic to calculate the attribute value.

Hope i'm explaining my ideas rigth!!

--
Si necesitas una máquina para hacer algo y no la compras al final
te darás cuenta de que has pagado lo mismo y no tienes la
máquina.--Henry Ford

Alberto

On Sun, Nov 2, 2014 at 3:05 AM, Lamont Granquist
<lamont@opscode.com <mailto:lamont@opscode.com>> wrote:

    On 11/1/14, 4:48 PM, aL. wrote:

        Thankyou all guys for your explanations!

        My brain was on holidays that day, when i wrote the
        question, but in some way your answers bring some light to
        the issue!

        Putting it all together:

         - Avoid logic on template as possible.
         - Use variables on template resources when you need
        logic/pre-proccessing. Putting logic on recipe's side.
         - If you give node attribute values directly or computed
        to the template, through variables. Better do it with
        lazy, so other cookbooks can override those attributes
        later on the runlist.

    generally, no.    if you want to override an attribute later
    in the run_list you want to override it in the attributes
    files.   the node attributes which are used for input should
    be finalized when you're done parsing attributes files.  that
    is the job of the stages in the chef-client converge which
    prior to recipe code -- assembling the input state of the node
    object. the recipes should consume that object and shouldn't
    need to mutate it.


Justin Dossey
Practice Owner
New Context Services, Inc