How Do You Create a Recipe or Cookbook to Make a Configuration Change on a Chef Client?

Problem scenario
You have a desired configuration that you want implemented with Chef.  You want a command to execute and a file to transfer via a Chef recipe or cookbook.  You have installed Chef server on one server (see this posting if you want to do this) and Chef client on another (see this posting for installing Chef client).  You want to use Chef for the first time doing something as an example.  How do you get Chef to do two configuration management tasks?

Hybrid cloud implementations are common.  This solution has been tested to work with a Chef Server in AWS with Chef client nodes in AWS and in Azure.  

You have Chef server and Chef client already installed on separate servers.  Make sure knife is installed on the Chef server if it is a standalone deployment.  (The knife command does not need to be on a Chef client node.  The knife command does not need to be on the Chef server if you have a workstation with knife.)  Use this to test: "man knife" (with no quotes).  If you see a man page, knife has probably been configured properly and you can skip down to the Procedures section.  Otherwise, go to one of the the Ubuntu or CentOS/RHEL/Fedora sections below.

Ubuntu Prerequisite
If knife is not installed and you are using Ubuntu with a standalone deployment of Chef, run these commands from the Chef server:

sudo apt-get -y update

sudo apt -y install chef

Respond to the prompt for the "URL of Chef Server" with the FQDN of the Chef server.  Go to the "Configure knife" section below.

CentOS/RHEL/Fedora Prerequisite
If knife is not installed and you are using CentOS/RHEL 7.x/Fedora with a standalone deployment of Chef, run these commands from the Chef server:

sudo yum -y update

curl > /tmp/chefdk-2.3.4-1.el7.x86_64.rpm

sudo yum -y localinstall /tmp/chefdk-2.3.4-1.el7.x86_64.rpm

If you are using RHEL 8.x, run these commands from the Chef server:

sudo yum -y update
curl > /tmp/chefdk-4.8.23-1.el7.x86_64.rpm
sudo yum -y localinstall /tmp/chefdk-4.8.23-1.el7.x86_64.rpm

Configure knife Prerequisite

a)  Run this:  knife configure

b)  You will be prompted for a series of questions.  For the first one, accept the default (just press enter) unless you have a preference:  "Where should I put the config file? [/path/to/.chef/knife.rb]"

c)  For the second prompt, "Please enter the chef server URL:", respond with one string with no spaces.   Enter "https://" and then the chef server FQDN, and finally this string "organizations/companynickname/" for the URL with no port number and no quotes.  Replace "companynickname" with the company nickname you provided with the org-create command when you set up the Chef server.  For example:

https://<FQDN of Chef server>/organizations/companynickname/

d)  For the third one, "Please enter an existing username or clientname for the API:" enter "contint" with no quotes where "contint" was entered when you set up Chef with this command:

sudo chef-server-ctl user-create contint Continual Integration 'abcd1234' --filename /home/jdoe/contint.pem

e)  For the fourth one, "Please enter the validation clientname:", enter "contint-validator" with no quotes or whichever name you want.

f)  For the fifth prompt, "Please enter the location of the validation key:", enter "/etc/chef/contint-validator.pem" with no quotes where "contint-validator.pem" is the name you want the file to be.  Alternative path locations (from /etc/chef/) could work as well.  This is just an example.

g)  For the sixth prompt, "Please enter the path to a chef repository (or leave blank):", enter "/home/jdoe" with no quotes or a location of your preference.  Your Linux user account should have the ability to create directories and write to files in this location.

h)  1. Note the output like this:

    "You must place your client key in:
      /home/jdoe/.chef/jdoe.pem "

    2.  The source of this file was created when you ran a command this (when setting up Chef server):

    sudo chef-server-ctl user-create contint Continual Integration 'abcd1234' --filename /home/jdoe/contint.pem

    The file specified after the "--filename" flag is the source.

    3.  Copy the source file referred to in step h.2 above to the destination as referred to in step h.1.

i)  If you used directions on this site to configure Chef server, you will have already done this step (and its three sub-steps below).
    1.  Note the output that appeared with step g above like this:

    You must place your validation key in:

     2.    Find the file that was created when you set up Chef server.  Assuming the file was named "contint-validator.pem" find it with this command:  sudo find / -name contint-validator.pem

    For background information, this type of command would create such a file:
    sudo chef-server-ctl org-create companynickname 'Continual Integration' --association_user contint --filename contint-validator.pem

    3.  If necessary copy the file from where it was created on the Chef server to the location the output says to.  For example, if the contint-validator.pem file is in /home/jdoe/, copy it to /etc/chef/ (per the output as illustrated in step i.1). 

j)  Run this command: knife ssl fetch

1.  From the workstation with knife or the standalone Chef server, run one of the commands below associated with your distribution of Linux (where coolexample is the name of the cookbook you want to create):

# For Ubuntu distributions, run this command:
knife cookbook create coolexample

# For CentOS/RHEL/Fedora distributions of Linux, run this command:
chef generate cookbook coolexample

  •  You will need to be in a directory wherein you have permissions to create subdirectories to run either of the above commands.  Some /etc/chef may not work if you are not root.
  • The home directory of the user may be where you run the above commands.  This is an example for a proof-of-concept.  Your needs may vary; you may want to create your own directory structure.
  • The cookbook_path stanza in the soon-to-be created file named knife.rb will be configured to the directory where the cookbooks will be.  Remember the path where you run one of the above commands.

2.  On the Chef server make sure /etc/chef/client.pem exists.  This file should be a copy of the private key generated from the GUI operation when setting up the client.  (There are other potential locations and names for this file.)

3.  a)  Change directories to the "recipes" directory in the cookbook directory that was just created.  You could run this to find it: sudo find / -name coolexample
     b)  cd /path/found/above

4.  Run this command:  cd recipes

5.  Modify default.rb in this "recipes" directory.  Add theses lines to default.rb (to demonstrate command execution and file transferring in a recipe):

execute "A bash command will run" do
  command "date > /tmp/c.txt"

cookbook_file "/tmp/goodfun.txt" do
  source "fun.txt"
  mode "0644"

6.  Run these four commands:

cd ..
mkdir files # so "files" is a sibling of "recipes" in the cookbook named "coolexample"
cd files
echo "testing" > fun.txt

7.  Run these two commands (and follow the step below):

export EDITOR=vi
knife node edit <FQDN of chef client server>
  # This command opens the vi text editor.

You will want to go to the run_list section and make it look like these three lines of code (the parentheses portion is for your information and not code):

  "run_list": [

(Subsequent recipes can be listed provided that the preceding recipe has a comma after it.)*

8.  Run this command:

knife cookbook upload --all

9.  Go to the Chef client node.  From this server run this command:

sudo chef-client -S https://<FQDN of Chef Server>/organizations/companynickname

You are done.

*  To ensure every time you log in you have a text editor exported to an environment variable, thus enabling the "knife node" command, do the following.  (You will not have to worry about running the export command again.)

Run one of the following:

vi ~/.bashrc or vi ~/.bash_profile

(The text is large because the tilde is important.)  Add this single stanza in the file: 
export EDITOR=$(which vi)

Save the changes.

Leave a comment

Your email address will not be published. Required fields are marked *