DevOps Classroom Series – 01/Dec/2019


  • Attributes are user variables
  • Attributes can be defined at multiple places
    • Recipe
    • Attribute File
    • Roles
    • Environments
  • Attributes also have types
    • default
    • force_default
    • normal
    • overrride
    • force_override
    • automatic

Scenario: Lamp

  • As of now we have lamp stack cookbook with one recipe for ubuntu and one recipe for redhat.
  • Lets try to write one recipe for both.
  • Lets generate the attribute
chef generate attribute --help
chef generate attribute . default
  • In the default.rb file generated in attributes folder, add the following
default[<cookbookname>][<variable-name>] = <variable-value>
default['apachewithphp']['package_name'] = 'apache2'
  • default.rb with all the attributes defined will be as shown below
if node['platform'] == 'ubuntu'
    # package name for apache server for ubuntu machines
    default['apachewithphp']['package_name'] = 'apache2'

    # php packages for ubuntu machines
    default['apachewithphp']['php_packages'] = ["php", "libapache2-mod-php",  "php-mysql", "php-cli"]

    # package name for apache server for redhat machines
    default['apachewithphp']['package_name'] = 'centos'

    # php packages for ubuntu machines
    default['apachewithphp']['php_packages'] = ["php",  "php-mysql"]

  • Using the attribute defined in attributes file can be acheived by using node object. syntax is
# attribute definition
default[<cookbookname>][<variable-name>] = <variable-value>

#attribute usage
  • If we apply the above attributes then recipe will be as shown below
# Cookbook:: .
# Recipe:: phpapache
# Copyright:: 2019, The Authors, All Rights Reserved.

if node['platform'] == 'ubuntu'
    apt_update 'update pacakges' do
        ignore_failure true
        action :update

package_name = node['apachewithphp']['package_name']

package package_name do
    action :install
    notifies :enable, "service[#{package_name}]"

php_packages = node['apachewithphp']['php_packages']

php_packages.each do |package_name|
  package package_name do
      action :install

#remote_file '/var/www/html/info.php' do
#    source ''
#    action :create
#    notifies :restart, "service[#{mypackage}]"

cookbook_file '/var/www/html/info.php' do
    source 'info.php'
    action :create
    notifies :restart, "service[#{mypackage}]"

service package_name do
    action :nothing

  • Lets apply only_if gaurd as mentioned over here
  • Also look at not_if over here
  • Lets add the logic to fail the recipe execution if it is executed on unsupported platforms. The following code is added to default.rb in recipes folder.

if node['platform'] == 'ubuntu' or node['platform'] == 'centos'
    include_recipe 'apachewithphp::phpapache'
    raise 'This cookbook is supported only on ubuntu and centos'
  • Try testing this cookbook by changing kitchen.yaml file for ubuntu and centos flavloure
  • Now change the version in the metadata.rb file and upload the cookbook using berks upload.

Making Cookbooks Reusable

  • There will be lot of cookbooks already written, rather than rewriting cookbooks, it easy to reuse.
  • Ways of reusing cookbooks
    • Reusing recipes
    • Making your cookbooks reusable by writing custom resources.
  • Supermarket:
    • Community cookbooks with reusable recipes or reusable custom resources.

Chef Supermarket

  • Lets create a cookbook to install java and postgresql on ubuntu machine and centos using chef supermarket cookbooks.
  • Lets create a cookbook called supermarketdemo
  • Now lets find a supermarket cookbook for postgres. Result is over here
  • To use this cookbook we need to define dependency. Dependency is defined in metadata.rb file using the following syntax
depends '<cookbookname>', '<symbol> <version>'
  • Symbols in versions define restrictions on versions
    • <
    • >
    • <=
    • =
    • ~>
  • berks install command will download all the dependencies of your cookbook defined in metadata.rb
  • Now lets try to install postgres server by reading the documentation of cookbook, the way is as following. use the custom resource.
postgresql_server_install 'Setup my PostgreSQL 9.6 server' do
    password 'MyP4ssw0rd'
    port 5433
    action :create

  • Try to execute this cookbook located at here

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About continuous learner

devops & cloud enthusiastic learner