A Chef attribute can be seen as a variable that:
1) gets initialized to a default value in cookbooks/mycookbook/attributes/default.rb
Examples:
default[:mycookbook][:swapfilesize] = '10485760'
default[:mycookbook][:tornado_version] = '1.1'
default[:mycookbook][:haproxy_version] = '1.4.8'
default[:mycookbook][:nginx_version] = '0.8.20'
2) gets used in cookbook recipes such as cookbooks.mycookbook/recipes/default.rb or any other myrecipefile.rb in the recipes directory; the syntax for using the attribute's value is of the form #{node[:mycookbook][:attribute_name]}
Example of using the haproxy_version attribute in a recipe called haproxy.rb:
# install haproxy from source
haproxy = "haproxy-#{node[:mycookbook][:haproxy_version]}"
haproxy_pkg = "#{haproxy}.tar.gz"
downloads = [
"#{haproxy_pkg}",
]
downloads.each do |file|
remote_file "/tmp/#{file}" do
source "http://myserver.com/download/haproxy/#{file}"
end
end
....etc.
Example of using the swapfilesize attribute in the default recipe default.rb:
# create swap file if it doesn't exist
SWAPFILE=/data/swapfile1
if [ -e "$SWAPFILE" ]
then
exit 0
fi
dd if=/dev/zero of=$SWAPFILE bs=1024 count=#{node[:mycookbook][:swapfilesize]}
mkswap $SWAPFILE
swapon $SWAPFILE
echo "$SWAPFILE swap swap defaults 0 0" >> /etc/fstab
3) can be overridden at either the role or the node level (and some other more obscure levels that I haven't used in practice)
I prefer to override attributes at the role level, because I want those overridden values to apply to all nodes pertaining to that role.
For example, I have a role called appserver, which is defined in a file called appserver.rb in the roles directory:
# cat appserver.rb
name "appserver"
description "Installs required packages and applications for an app server"
run_list "recipe[mycookbook::appserver]", "recipe[mycookbook::haproxy]", "recipe[memcached]"
override_attributes "mycookbook" => { "swapfilesize" => "4194304" }, "memcached" => { "memory" => "4096" }
Here I override the default swapfilesize value (an attribute from the mycookbook cookbook) of 10 GB and set it to 4 GB. I also override the default memcached memory value (an attribute from the Opscode memcached cookbook) of 128 MB and set it
to 4 GB.
If however you want to override some attributes at the node level, you could do this in the chef.json file on the node if you wanted for example to set the swap size to 2 GB:
"run_list": [ "role[base]", "role[appserver]" ]
"mycookbook": { "swapfilesize": "2097152"}
Anothe question is when should you use Chef attributes? My own observation is that wherever I use hardcoded values in my recipes, it's almost always better to use an attribute instead, and set the default value of the attribute to that hardcoded value, which can be then overridden as needed.
1 comment:
Yes, attributes are one of the most important parts of Chef.
It is sometimes not clear where attributes should be defined. You can do that at a lot of levels: node.json, role default_attributes, role override_attributes, and there are more.
But once you work that out they are great!
Post a Comment