Saturday, August 5, 2017

Inspecting files on your Chef Server with knife

 Knife is the command-line interface for the chef server,It uses the Restful API  exposed by the chef server to do its work and helps  you to interact  with the chef server.


Sometimes,you may want to peek into files  stored on your chef server.You might not be sure about an implementation detail of the specific cookbook version currently installed on your chef server and need to look it up.Knife can help you out by letting you show  various  aspects of life stored on your Chef server.


Install the iptables community cookbook by executing the following command


local@workstation:~ $ knife cookbook site install iptables

Installing iptables to /Users/mma/work/chef-repo/cookbooks

When you execute the command, we get the error.

ERROR: IOError cannot open or read  ..../chef-repo/cookbooks/iptables/metadata.rb !

Note:If you get the preceding error, your cookbook only has a metadata.json file.Make sure that you delete it and create  a valid metadata.rb, file instead.

Upload the iptables cookbook on your chef server by executing the following command:

local@workstation:~ $   knife cookbook upload iptables  --include-dependencies 
 uploading iptables
 uploading combat_resources
 uploading  2 cookbooks


Lets find out how knife can help you to look in to the cookbook stored in your chef server?


1)  First, you want to find out the current version  of the cookbook  your interested in.In  our case, we are interested  in the iptables cookbook:


local@workstation:~ $   knife cookbook show iptables 
iptables  3.0.0.0.14.1 

2) Then, you can look up the definitions  of the iptables cookbook , using the version number that you found in the previous step.


local@workstation:~ $  knife cookbook show iptables  0.14.1  definitions
                 checksum
                  name
                  path
                  specificity
                  url:    https://s3-external-1.amazonaws.com:443/opscode-platform



3)  Now,you can even  show the contents of the iptables_rule.rb  definition file  as stored on the server:

   
local@workstation:~ $  knife cookbook show iptables  0.14.1  definitions  iptables_rule.rb 

# Cookbook_Name::iptables
#  Definition::iptables_rule
#
#
define :iptables_rule,  :enable => true,  :source => nil,  :variables =>  {},  :cookbook => nil do


How it works


The knife cookbook show subcommand helps you what exactly is stored  on the Chef Server.It lets you drill down in to specific sections of your cookbook and see the exact contents of the files stored in your Chef Server.



You can pass patterns  to the knife show command  to tell it exactly what you want to see.
Showing the attributes defined by the cookbook can be done as follows:




local@workstation:~ $  knife show cookbooks/iptables/attributes/*
cookbooks/iptables/attributes/default.rb

#
# Cookbook  Name::iptables
#  Attribute:: default
Truncated  OUTPUT

To  find  some more  examples  on knife show , visit https://docs.chef.io/knife_show.html

Defining Cookbook Dependencies 

Quite often, you might  want to use features  of other cookbooks in your cookbooks. For example, if you want to make sure that all packages  required for compiling software written in  c are installed, you want to include the build essential cookbook, which does just that.
The  Chef Server  needs to know  about such dependencies  in your cookbooks. You declare them in a cookbook's metadata.

Make sure you have a cookbook named  my_cookbook  and the run_list  of your node includes my_cookbook, as described  in the creating and using cookbook.

How to do it


Edit the  metadata  of your cookbook in the file  cookbooks/my_cookbook/metadata.rb  to add a dependency  to the build-essential cookbook:


local@workstation:~/chef-repo $ subl cookbooks/my_cookbook/metadata.rb

...

depends 'build-essential', ' >= 7.0.3'


How it works

If you want to use a feature  of another cookbook inside  your cookbook, you will need to include the other cookbook in your recipe using the include_recipe  directive:

include_recipe 'build-essential'


To  Tell the Chef Server  that your cookbook  requires the  build-essential cookbook, you need to declare that dependency in the metadata.rb file.If you uploaded  all the dependencies  to your chef server either using the  knife cookbook  upload  my_cookbook  --include-dependencies  or berks install  and berks upload, as described  in the Managing  cookbook  dependencies with Berkshelf 
recipe, the chef server will then send all the required cookbooks to the node.

The depends function call tells the Chef Server that your cookbook  depends on a version greater than or equal to 7.0.3  of the build-essential cookbook

You may use  any of these version constraints with depends calls:

<  (less than)
<=  (less than or equal to)
=  (equal to)
>=  (greater than or equal to)
~> (approximate greater that)
>  (greater that)



Note:

If you include another recipe  inside  your recipe,withour declaring the cookbook dependency in your metadata.rb file,   FOODCRITIC will warn you:


local@workstation:~/chef-repo $    foodcritic cookbook/my_cookbook

FC007:  Ensure recipe dependencies  are reflected  in cookbook metadata:
cookbooks/my_cookbook/recipes/default.rb:9

This  is where  Berkshelf  comes into play. It works like Bundler for ruby gems,managing cookbook dependencies for you. Berkshelf downloads all the dependencies you defined  recursively  and helps you to upload all cookbooks to your Chef server.


Instead of polluting your chef repository, it stores all the cookbooks in a central location.You just commit your Berkshelf  dependency file (called  Berksfile)  to your repository  every colleague  or build server can download and install all those dependent cookbooks based on it.

Lets see how to use  Berkshelf  to manage dependencies  of your cookbook.


Make sure you have a cookbook named  my_cookbook  and run_list of your node includes my_cookbook  as described in the  Creating and using cookbook.


How to do it?

Berkshelf helps you to keep those utility cookbooks out of your chef repository.this makes it much easier  to maintain  the important cookbooks.

Lets see how to write a cookbook  by running  a bunch of utility  recipes and manage the required cookbooks with Berkshelf :

1) Edit  your cookbook's metadata 


local@workstation:~/chef-repo  $ subl  cookbooks/my_cookbook/metadata.rb

.....

depends  "chef-client"
depends  "apt"
depends  "ntp"


2) Edit your cookbook's default recipe

local@workstation:~/chef-repo  $   subl  cookbooks/my_cookbook/recipes/default.rb

.....

include_recipe "chef-client"
include_recipe  "apt"
include_recipe  "ntp"


3) Run Berkshelf  to install all the required cookbooks:

    local@workstation:~/chef-repo  $ cd cookbooks/my_cookbook
    local@workstation:~/chef-repo/cookbooks/my_cookbook $ berks install 
    Resolving cookbook dependencies
    Fetching 'my_cookbook'  from source at .
    Fetching cookbook index  from https://supermarket.chef.io
    Installing apt  (4.0.2)

 4)  Upload all the cookbooks on the chef server
       local@workstation:~/chef-repo/cookbooks/my_cookbook $   berks upload 
       Using my_cookbook  (0.1.0)
        Truncated  output

How it works ? 


Berkshelf comes with  the Chef  DK

We edit our cookbook  and tell it use  a few basic cookbooks

Instead of making us manually install all the cookbooks using  knife cookbook site install,Chef  generates  a Berksfile,besides the metadata.rb file.

The Berksfile is simple .It tells Berkshelf to use the Chef supermarket as the default source for all the cookbooks:

source "https://supermarket.chef.io"
  
       
    And the Berksfile tells Berkshelf  to read the metadata.rb file to find all the required cookbooks.This is the simplest way when working inside a single cookbook, please see the below to see more advanced usage of Berksfile.

After telling Berkshelf where to find all the required cookbook names, we use it to install all those cookbooks:

       berks install 




Note:Berkshelf stores cookbooks in  ~/.berkshelf/cookbooks, by default.This keeps your chef repository clutter free (means confusion/disorder state free).Instead of having to manage all the required cookbooks inside your own chef repository,Berkshelf takes care of them.You simply need to check in Berksfile  with your cookbook  and everyone using your cookbook can download all the required cookbooks using Berkshelf.

To make sure the that there's no mixup  with different cookbooks versions when sharing your cookbook,Berkshelf creates a file called Berksfile.lock alongside Berksfile.

Note:

 Don't commit the Berksfile.lock to the version control .If you use berks generate it will automatically populate the .gitignore  for you.Otherwise you need  to add Berksfile.lock  to your  .gitignore  manually.


Here you will find exact versions  of all the cookbooks that Berkshelf installed:

Dependencies 
my_cookbook
path: .
metadata true

GRAPH
apt (4.0.2)
compact_resource (>=12.10)
chef-client (6.0.0)
cron (>=1.7.0)
logrotate (>=1.9.0)
windows (>=1.42.0)
..
..
..

Berkshelf will only use the exact versions specified  in the Berksfile.lock file,if it finds this file.

Finally we use the Berkshelf to upload all the required cookbooks to the Chef server.

berks upload

Berkshelf integrate with the vagrant:


Berkshelf integrates tightly with Vagrant via the vagrant-berkshelf plugin.You can setup the Berkshelf and Vagrant in such a way that Berkshelf  installs and uploads all the required cookbooks on your chef server whenever you execute  vagrantup or vagrant provision.You will save all the work  of running berks  install and berks upload manually before creating you node with the vagrant.

How you can integrate  Berkshelf and vagrant ?


1)local@workstation:~/chef-repo  $  vagrant plugin install vagrant-berkshelf
Installing the  'vagrant-berkshelf'  plugin.This can take a few minutes
Installed the plugin 'vagrant-berkshelf (5.0.0)'!


2)Then you have to say the vagrant to make use of the plugin.You do this by enabling the plugin in Vagrantfile :

local@workstation:~/chef-repo  $ subl (sublime) Vagrantfile
config.berkshelf.enabled = true

3)Then you need a Berksfile in the root directory of your chef repository  to tell Berkshelf  which cookbooks  to install  on each vagrant run:

local@workstation:~/chef-repo  $ sublBerksfile
source 'https://supermarket.chef.io'
cookbook  'my_cookbook',path: 'cookbook/my_cookbook'

4) Eventually you can start your VM using vagrant.Berkshelf  will first download  and then install the cookbooks in the Berkshelf  and upload them to the Chef server.Only after all the cookbooks are made available on the Chef server by Berkshelf will vagrant go on:

local@workstation:~/chef-repo  $  vagrant up 
Bringing machine server  with virtual box provider

==> default:  Updating  Vagrant's Berkshelf...
==> default:   Resolving cookbook dependencies
==> default:   'Fetching  'my_cookbook' from  source at  cookbooks/my_cookbook
==> default:   'Fetching cookbook index  from https://supermarket.chef.io.....

5) This way using Berkshelf  together with  Vagrant  saves a lot of manual steps  and gets faster cycle times for your cookbook development.If your using your manual vagrant setup  instead of Test kitchen 

References:

http://berkshelf.com/
https://github.com/berkshelf/berkshelf
Vagrant Berkshelf  plugin source code  at
https://github.com/berkshelf/vagrant-berkshelf






















No comments:

Post a Comment