Discussion:
How do I test an attribute value in an
ItsMikeE
2011-06-24 11:29:32 UTC
Permalink
Thanks for the responses.
As you can see I have not used Ruby before.

Still going round in circles.

My variables are set up in the format of [:recipename][:recipeoption] so that
it is always clear which recipe a variable belongs to.
I am now trying to use true and false instead of specific values (at least for
now).

I have tried all kinds of only_if tests. Some cause syntax errors when I run
rake install, some at run-time.
Some do not cause syntax errors but are not running as expected.

How do I specify an only_if such that

only_if value of [:recipename][:recipeoption] is true?
ItsMikeE
2011-06-24 14:55:36 UTC
Permalink
How do I specify an only_if such that

only_if value of [:recipename][:recipeoption] is true
or
only_if value of [:recipename][:recipeoption] == value

I keep getting TypeError: Symbol as array index
What does that mean?
Daniel DeLeo
2011-06-24 15:29:16 UTC
Permalink
Post by ItsMikeE
How do I specify an only_if such that
only_if value of [:recipename][:recipeoption] is true
or
only_if value of [:recipename][:recipeoption] == value
I keep getting TypeError: Symbol as array index
What does that mean?
Two things here. First is a convention with not_if and only_if. When you pass a code block to them, they execute the code and look at the result. Here are some simple cases:

only_if { true } # Always
not_if { false } # always
only_if { false } # never

When you pass anything else, Chef tries to convert it to a string, and run it as a command. These will have the same results as above:

only_if "/bin/true" # Always
not_if "/bin/false" # Always
only_if "/bin/false" # never

Second, in the code you posted, you're creating an Array
[:recipename]

With this array you can access the element by its position in the array:

[:recipename][0] #=> :recipename

but it makes no sense to use something other than an integer to access an element in the array.

If you're trying to use attributes you set in the attributes file, these are accessible via the `node` object in your recipes, so you probably wanted:

only_if { node[:some_value] }

HTH,
--
Dan DeLeo
ItsMikeE
2011-06-27 08:29:38 UTC
Permalink
Thanks for the response
That helps, but still leaves me with some questions

Looking at the wiki page on setting attributes

Default in ../cookbooks/../attributes/default.rb
Example Precedence #1
default["apache"]["dir"] = "/etc/apache2"

Override in .../roles/rolename.rb
Example Precedence #8
override_attributes({ "apache" => {"dir" => "/etc/apache2"}})

How do I reference the attribute inside a recipe?
I don't mind if it is in a case statement, and if statement or an only_if. I am
just trying to choose between one of two source files to overwrite one
destination file.

Again going back to the wiki I can see
if node.chef.attribute?("webui_enabled")
# set up webui stuff
end

How does that equate to the attributes that were set above?
Is it:
if node.apache.dir?
or
if node.chef.attribute?("apache""dir")
or
something else completely?


I don't really mind if it is in an only_if, or a case statement or an if test.
Tim Diggins
2011-06-27 08:52:15 UTC
Permalink
You can access node attributes in recipes using

node["apache"] # preferred
node[:apache] # as a symbol, deprecated
node.apache # as a method, deprecated


which works for sub-keys too:

node["apache"]["dir"]
node[:apache][:dir]
node.apache.dir


and test if there is such a attribute using

node.attribute?("apache")

and

node.apache.attribute?("dir")


QUESTION: I suppose that one is a bit deprecated (despite being from the
wiki) - should really be:

node["apache"].attribute?("dir")


*Ruby note:*
*In ruby predicate methods (which test whether something is true or not)
often (by convention) end in '?' (like File.exists?() for example))*

You might want to check out:
http://wiki.opscode.com/display/chef/Recipes#Recipes-AccessingNodeAttributes
and
http://wiki.opscode.com/display/chef/Attributes#Attributes-CookbookAttributeMethods

Another valuable page is
http://wiki.opscode.com/display/chef/Just+Enough+Ruby+for+Chef


Tim
Post by ItsMikeE
Thanks for the response
That helps, but still leaves me with some questions
Looking at the wiki page on setting attributes
Default in ../cookbooks/../attributes/default.rb
Example Precedence #1
default["apache"]["dir"] = "/etc/apache2"
Override in .../roles/rolename.rb
Example Precedence #8
override_attributes({ "apache" => {"dir" => "/etc/apache2"}})
How do I reference the attribute inside a recipe?
I don't mind if it is in a case statement, and if statement or an only_if. I am
just trying to choose between one of two source files to overwrite one
destination file.
Again going back to the wiki I can see
if node.chef.attribute?("webui_enabled")
# set up webui stuff
end
How does that equate to the attributes that were set above?
if node.apache.dir?
or
if node.chef.attribute?("apache""dir")
or
something else completely?
I don't really mind if it is in an only_if, or a case statement or an if test.
Денис Барышев
2011-06-27 09:00:08 UTC
Permalink
Hello Tim!

Where did you get that accessing attributes with symbol notation is
deprecated? Could you please tell.
Post by Tim Diggins
You can access node attributes in recipes using
node["apache"] # preferred
node[:apache] # as a symbol, deprecated
node.apache # as a method, deprecated
node["apache"]["dir"]
node[:apache][:dir]
node.apache.dir
and test if there is such a attribute using
node.attribute?("apache")
and
node.apache.attribute?("dir")
QUESTION: I suppose that one is a bit deprecated (despite being from the
node["apache"].attribute?("dir")
*Ruby note:*
*In ruby predicate methods (which test whether something is true or not)
often (by convention) end in '?' (like File.exists?() for example))*
http://wiki.opscode.com/display/chef/Recipes#Recipes-AccessingNodeAttributes
and
http://wiki.opscode.com/display/chef/Attributes#Attributes-CookbookAttributeMethods
Another valuable page is
http://wiki.opscode.com/display/chef/Just+Enough+Ruby+for+Chef
Tim
Post by ItsMikeE
Thanks for the response
That helps, but still leaves me with some questions
Looking at the wiki page on setting attributes
Default in ../cookbooks/../attributes/default.rb
Example Precedence #1
default["apache"]["dir"] = "/etc/apache2"
Override in .../roles/rolename.rb
Example Precedence #8
override_attributes({ "apache" => {"dir" => "/etc/apache2"}})
How do I reference the attribute inside a recipe?
I don't mind if it is in a case statement, and if statement or an only_if. I am
just trying to choose between one of two source files to overwrite one
destination file.
Again going back to the wiki I can see
if node.chef.attribute?("webui_enabled")
# set up webui stuff
end
How does that equate to the attributes that were set above?
if node.apache.dir?
or
if node.chef.attribute?("apache""dir")
or
something else completely?
I don't really mind if it is in an only_if, or a case statement or an if test.
Tim Diggins
2011-06-27 09:09:28 UTC
Permalink
Hi Denis -
Post by Денис Барышев
Hello Tim!
Where did you get that accessing attributes with symbol notation is
deprecated? Could you please tell.
Opscode training course (unless I misunderstood... maybe someone from
opscode or a core committer can weigh in here

However I'm not sure it's "deprecated pending removal" more "deprecated
because it's confusing" (and can get hard (or impossible?) to represent in
symbol literal notation).
Daniel DeLeo
2011-06-27 15:25:17 UTC
Permalink
Post by Tim Diggins
Hi Denis -
Post by Денис Барышев
Hello Tim!
Where did you get that accessing attributes with symbol notation is deprecated? Could you please tell.
Opscode training course (unless I misunderstood... maybe someone from opscode or a core committer can weigh in here
However I'm not sure it's "deprecated pending removal" more "deprecated because it's confusing" (and can get hard (or impossible?) to represent in symbol literal notation).
Right, there are no plans to remove it. If you know your way around symbols in ruby, feel free to use it. As you said, the tricky part is expressing something like "foo-bar" as a symbol literal. This can be done, but for someone who is new to both Chef and Ruby, it's easier to stick with strings, which I believe is why we make this recommendation in the training classes.
--
Dan DeLeo
Aaron Peterson
2011-06-27 18:08:44 UTC
Permalink
Post by Daniel DeLeo
Post by Tim Diggins
Hi Denis -
Post by Денис Барышев
Hello Tim!
Where did you get that accessing attributes with symbol notation is deprecated? Could you please tell.
Opscode training course (unless I misunderstood... maybe someone from opscode or a core committer can weigh in here
However I'm not sure it's "deprecated pending removal" more "deprecated because it's confusing" (and can get hard (or impossible?) to represent in symbol literal notation).
Right, there are no plans to remove it. If you know your way around symbols in ruby, feel free to use it. As you said, the tricky part is expressing something like "foo-bar" as a symbol literal. This can be done, but for someone who is new to both Chef and Ruby, it's easier to stick with strings, which I believe is why we make this recommendation in the training classes.
Yes - having been part of that conversation that's totally it. It's
easier to say "quote it" than explain special cases, name space
overlap (and method_missing), character constraints, and escaping. By
the time you actually might care to use symbols stylistically or
whatever, you can learn to wield them safely on your own.

If we do use the actual term "deprecated" somewhere, point it out to
us, as we shouldn't.
--
Aaron Peterson <***@opscode.com>
Opscode Technical Evangelist
Mark J. Reed
2011-06-27 13:12:28 UTC
Permalink
Post by ItsMikeE
Thanks for the response
That helps, but still leaves me with some questions
Looking at the wiki page on setting attributes
[...]
Post by ItsMikeE
How do I reference the attribute inside a recipe?
Yes, there are lots of ways to *set* attributes, that override each other
depending on the precedence rules on the wiki. But the end result is that
all of those attributes end up as fields on the "node" object. No matter
how the attribute gets set, you access it via node.

Cookbook:

default[:my_cookbook][:my_attribute] = "default"

Role:

override[:my_cookbook][:my_attribute] = "overridden"

Checking in recipe:

case node[:my_cookbook][:my_attribute]
when "default" then puts "Still default!"
when "overridden" then puts "Here there be roles!"
end

One thing to note is that the node object is not a normal Ruby Hash, but
rather special object that has some magic around accessing its fields.
Specifically, these three expressions all return the same value:

node[:my_cookbook]
node['my_cookbook']
node.my_cookbook

The recommended notation is the middle one, since symbols can be offputting
to the uninitiated and method calls run the risk of conflicting with actual
methods on the object.

Again going back to the wiki I can see
Post by ItsMikeE
if node.chef.attribute?("webui_enabled")
# set up webui stuff
end
How does that equate to the attributes that were set above?
The above code is checking whether or not any attribute file or role or
recipe or anything else has set [:chef][:webui_enabled] on the node.
node.chef (same as node['chef'] or node[:chef]) returns the entire subhash
of attributes defined as [:chef][:something, and the .attribute? call
returns true if the hash it's called on contains the named attribute. The
method returns true if the attribute has a value, even if that value itself
is false, which is the reason you would use it instead of just "if
node.chef.webui_enabled" or similar.
Post by ItsMikeE
if node.apache.dir?
or
if node.chef.attribute?("apache""dir")
or
something else completely?
If you set the attribute with something[:apache][:dir], then the equivalent
of the above example would be this:


if node.apache.attribute?("dir") then
...
end

--
Mark J. Reed <***@gmail.com>
Mark J. Reed
2011-06-27 13:16:31 UTC
Permalink
Post by Mark J. Reed
override[:my_cookbook][:my_attribute] = "overridden"
Well, that's still attributes file syntax; in an actual role definition,
that would look more like this:

{
"name": "use-my-cookbook",
"chef_type": "role",
"override_attributes": {
"my_cookbook": {
"my_attribute": "overridden"
}
},
"run_list": [
"my_cookbook"
]
}
--
Mark J. Reed <***@gmail.com>
ItsMikeE
2011-06-27 08:52:51 UTC
Permalink
Or am I going about this all wrong?

Should I be using templates? or some other construction?

Going back to the original situation
I have 2 ntp.client files, one for my primary site, one for DR.
How would you experienced chef users create a recipe to distribute these files?
Sascha Bates
2011-06-27 12:42:05 UTC
Permalink
https://gist.github.com/1048781

We have 3 data centers and have configured all of our services for each.
I've posted a recipe set with a template, recipe and data bag. I've made an
ntp data bag with three items, one for each data center. The recipe
searches the data bags using a node attribute called location (which we set
with an ohai plugin but which also can be set with a role, etc). The recipe
populates the host file with the ntp servers using a host resource and then
the template.
Post by ItsMikeE
Or am I going about this all wrong?
Should I be using templates? or some other construction?
Going back to the original situation
I have 2 ntp.client files, one for my primary site, one for DR.
How would you experienced chef users create a recipe to distribute these files?
ItsMikeE
2011-06-27 13:32:52 UTC
Permalink
Thanks all those who contributed.
I now have a version that works.
Now I can start looking at the best way to approach things, so that they are
understandable and maintainable.

Promises to be an interesting journey
Loading...