Deep dive into Chef Attributes in one hour

Understand Chef Attributes

An attribute is nothing but a key-value pair which represents a specific detail about a node. Attributes are used by the chef-client to understand the current state of the node

  1. What the state of the node was at the end of the previous chef-client run
  2. What the state of the node should be at the end of the current chef-client run

Chef Attributes Locations

Attributes are defined and provided to the chef-client from the following locations:

  1. Nodes (collected by Ohai at the start of each chef-client run)
  2. Attribute files (in cookbooks)
  3. Recipes (in cookbooks)
  4. Environments
  5. Roles

How chef-client work with Chef Attributes?

During every chef-client run, the chef-client builds the attribute list using:

Data about the node collected by Ohai..

  • The node object that was saved to the Chef server at the end of the previous chef-client run
  • The rebuilt node object from the current chef-client run, after it is updated for changes to cookbooks (attribute files and/or recipes), roles, and/or environments, and updated for any changes to the state of the node itself

After the node object is rebuilt, all of the attributes are compared, and then the node is updated based on attribute precedence. At the end of every chef-client run, the node object that defines the current state of the node is uploaded to the Chef server so that it can be indexed for search. We can specify the attribute at node level while running chef-client. Those attributes are referred to as node attributes


How chef-client work with different kinds of attributes?

At the beginning of a chef-client run, all attributes except for normal attributes are reset. The chef-client rebuilds them using - Automatic attributes collected by Ohai at the beginning of the chef-client run and then

  1. Using default and override attributes that are specified in cookbooks or by roles and environments.
  2. All attributes are then merged and applied to the node according to attribute precedence. At the conclusion of the chef-client run, the attributes that were applied to the node are saved to the Chef server as part of the node object.

Types of Chef Attribute

The chef-client uses six types of attributes to determine the value that is applied to a node during the chef-client run. attributes types is being used only for setting predence.

  1. Attribute Type
  2. force_default
  3. normal
  4. override
  5. force_override
  6. automatic

The sources of Chef attribute?

The chef-client sources attribute values from up to five locations.

  1. Nodes (collected by Ohai at the start of each chef-client run)
  2. Attribute files (in cookbooks)
  3. Recipes (in cookbooks)
  4. Environments
  5. Roles

Example of Chef attribute precedence over other attributes

Nodes (collected by Ohai at the start of each chef-client run) also Referred as Automatic attributes. Automatic attributes are detected by Ohai and are then used by the chef-client to ensure that they are handled properly during every chef-client run. All attributes collected by Ohai are unmodifiable by the chef-client. The most commonly accessed automatic attributes are:

Attribute Description
node['platform'] The platform on which a node is running. This attribute helps determine which providers will be used.
node['platform_version'] The version of the platform. This attribute helps determine which providers will be used.
node['ipaddress'] The IP address for a node. If the node has a default route, this is the IPV4 address for the interface. If the node does not have a default route, the value for this attribute should be nil. The IP address for default route is the recommended default value.
node['macaddress'] The MAC address for a node, determined by the same interface that detects the node['ipaddress'].
node['fqdn'] The fully qualified domain name for a node. This is used as the name of a node unless otherwise set.
node['hostname'] The host name for the node.
node['domain'] The domain for the node.
node['recipes'] A list of recipes associated with a node (and part of that node’s run-list).
node['roles'] A list of roles associated with a node (and part of that node’s run-list).
node['ohai_time'] The time at which Ohai was last run. This attribute is not commonly used in recipes, but it is saved to the Chef server and can be accessed using the knife status subcommand.
To see which automatic attributes are collected by Ohai for a particular node, run the following command:

$ find  /opt/chefdk/embedded/lib/ruby/gems/*/gems/ohai-*/lib -name "*.rb" -print | xargs grep -R "provides" -h |sed 's/^\s*//g'|sed "s/\\\"/\'/g"|sort|uniq|grep "\sprovides"

$ cd /opt/chefdk/embedded/lib/ruby/gems/*/gems/ohai-*/lib

$ ohai
	

The sources of Chef attribute in Attribute files

An attribute file is located in the attributes/ sub-directory for a cookbook.

When a cookbook is run against a node, the attributes contained in all attribute files are evaluated in the context of the node object. For example,

The apache2 cookbook contains an attribute file called default.rb, which contains the following attributes:

default['apache']['dir']          = '/etc/apache2'
default['apache']['listen_ports'] = [ '80','443' ]
Node methods (when present) are used to set attribute values on a node. The following example defines the node object itself as part of the attribute:

node.default['apache']['dir']          = '/etc/apache2'
node.default['apache']['listen_ports'] = [ '80','443' ] 
Default attribute in /attributes/default.rb

default['apache']['dir'] = '/etc/apache2'
Normal attribute set as a cookbook attribute

set['apache']['dir'] = '/etc/apache2'
normal['apache']['dir'] = '/etc/apache2'  #set is an alias of normal.
Override attribute in /attributes/default.rb

override['apache']['dir'] = '/etc/apache2'

The sources of Chef attribute in Recipes (in cookbooks)

In Recipe we allways need to set the node attributes. We can specify the attribute at node level while running chef-client. Those attributes are referred to as node attributes. You must precede the attribute name with node. when you set an attribute directly in a recipe.

Default attribute in node object in recipe

node.default['apache']['dir'] = '/etc/apache2'
Normal attribute set in a recipe

node.normal['apache']['dir'] = '/etc/apache2'
Override attribute in a node object (from a recipe)

node.override['apache']['dir'] = '/etc/apache2'

The sources of Chef attribute in Environments

Default attribute in /environments/environment_name.rb

default_attributes({ 'apache' => {'dir' => '/etc/apache2'}})
Override attribute in /environments/environment_name.rb

override_attributes({ 'apache' => {'dir' => '/etc/apache2'}})
Default attribute and Override attribute in Ruby file of chef environment

name 'dev'
description 'The development environment'
cookbook_versions  'couchdb' => '= 11.0.0'
default_attributes 'apache2' => { 'listen_ports' => [ '80', '443' ] }
Default attribute and Override attribute in JSON file of environment

{
  "name": "dev",
  "default_attributes": {
    "apache2": {
      "listen_ports": [
        "80",
        "443"
      ]
    }
  },
  "json_class": "Chef::Environment",
  "description": "",
  "cookbook_versions": {
    "couchdb": "= 11.0.0"
  },
  "chef_type": "environment"
}
Default attribute and Override attribute in JSON file of environment

{
  "name": "development",
  "description": "The master development branch",
  "cookbook_versions": {
    "nginx": "<= 1.1.0",
    "apt": "= 0.0.1"
  },
  "json_class": "Cheff:Environment",
  "chef_type": "environment",
  "default_attributes": {
  },
  "override_attributes": {
    "nginx": {
      "listen": [
        "80",
        "443"
      ]
    },
    "mysql": {
      "root_pass": "root"
    }
  }
}

The sources of Chef attribute in Roles

Default attribute in /roles/role_name.rb

default_attributes({ 'apache' => {'dir' => '/etc/apache2'}})
Override attribute in /roles/role_name.rb

override_attributes({ 'apache' => {'dir' => '/etc/apache2'}})
Default attribute and Override attribute in Ruby file of role

name "webserver"
description "The base role for systems that serve HTTP traffic"
run_list "recipe[apache2]", "recipe[apache2::mod_ssl]", "role[monitor]"
env_run_lists "prod" => ["recipe[apache2]"], "staging" => ["recipe[apache2::staging]"], "_default" => []
default_attributes "apache2" => { "listen_ports" => [ "80", "443" ] }
override_attributes "apache2" => { "max_children" => "50" }
Default attribute and Override attribute in Ruby file of role

name "web_server"
description "A role to configure our front-line web servers"
run_list "recipe[apt]", "recipe[nginx]"
env_run_lists "production" => ["recipe[nginx::config_prod]"], "testing" => ["recipe[nginx::config_test]"]
default_attributes "nginx" => { "log_location" => "/var/log/nginx.log" }
override_attributes "nginx" => { "gzip" => "on" }
Default attribute and Override attribute in JSON file of role

{
  "name": "webserver",
  "chef_type": "role",
  "json_class": "Chef::Role",
  "default_attributes": {
    "apache2": {
      "listen_ports": [
        "80",
        "443"
      ]
    }
  },
  "description": "The base role for systems that serve HTTP traffic",
  "run_list": [
    "recipe[apache2]",
    "recipe[apache2::mod_ssl]",
    "role[monitor]"
  ],
  "env_run_lists" : {
    "production" : [],
    "preprod" : [],
    "dev": [
      "role[base]",
      "recipe[apache]",
      "recipe[apache::copy_dev_configs]",
    ],
    "test": [
      "role[base]",
      "recipe[apache]"
    ]
  },
  "override_attributes": {
    "apache2": {
      "max_children": "50"
    }
  }
}
Default attribute and Override attribute in JSON file of role

{
  "name": "web_server",
  "description": "A role to configure our front-line web servers",
  "json_class": "Chef::Role",
  "default_attributes": {
    "nginx": {
      "log_location": "/var/log/nginx.log"
    }
  },
  "override_attributes": {
    "nginx": {
      "gzip": "on"
    }
  },
  "chef_type": "role",
  "run_list": [
    "recipe[apt]",
    "recipe[nginx]"
  ],
  "env_run_lists": {
    "production": [
      "recipe[nginx::config_prod]"
    ],
    "testing": [
      "recipe[nginx::config_test]"
    ]
  }
}

Example of Chef attribute precedence over other attributes

When a default attribute is set like this:

default['attribute'] = 'value'
any value set by a role or an environment will replace it. To prevent this value from being replaced, use the force_default attribute precedence:

force_default['attribute'] = 'I will crush you, role or environment attribute'
OR
default!['attribute'] = "The '!' means I win!"
When an override attribute is set like this:

override['attribute'] = 'value'
any value set by a role or an environment will replace it. To prevent this value from being replaced, use the force_override attribute precedence:

force_override['attribute'] = 'I will crush you, role or environment attribute'
OR
override!['attribute'] = "The '!' means I win!"

How to use Chef Attributes in Chef Recipe & Chef Templates?

How to use Chef Attributes in Chef Recipe?

EXAMPLE 1

log "Hello #{node['cheftutorial']['name']}" do
  level :info
end
EXAMPLE 2

[ "/srv/www/#{node['createdir']['shared_dir']}", "/srv/www/#{node['createdir']['config_dir']}" ].each do |path|
  directory path do
    mode node['createdir']['mode']
    owner node['createdir']['owner']
    group node['createdir']['group']
    recursive true
    action :create
  end
end
EXAMPLE 3

node.default['webserver']['age']= '33'
myname = node['webserver']['name']

file "/opt/infosys.txt" do
 content "Welcome to Infosys- From #{myname}"
end


file "/opt/infosys.txt" do
 content "Welcome to Infosys- #{node['webserver']['age']}"
end

How to use Chef Attributes in Chef Templates?

EXAMPLE 1

Avail Rajesh Kumar as trainer at 50% Discount
Puppet Online Training
Puppet Classroom TrainingEnroll Now