Chef – Configure Knife Admin

Install Ruby, Ruby gems, and Chef-client

Mac OSX

Install X-Code from Mac Appstore
Open Xcode and do the following :  Xcode >> Preferences >> Downloads >> Command Line Tools
$ cd /tmp
$ curl -O http://production.cf.rubygems.org/rubygems/rubygems-1.8.24.tgz
$ tar zxf rubygems-1.8.24.tgz
$ cd rubygems-1.8.24
$ ruby setup.rb –no-format-executable
$ sudo gem install chef

CentOS6

$ yum -y install ruby ruby-devel ruby-ri ruby-rdoc ruby-shadow gcc gcc-c++ automake autoconf make curl dmidecode git
$ cd /tmp
$ curl -O http://production.cf.rubygems.org/rubygems/rubygems-1.8.24.tgz
$ tar zxf rubygems-1.8.24.tgz
$ cd rubygems-1.8.24
$ ruby setup.rb –no-format-executable
$ sudo gem install chef

Ubuntu

$ apt-get install -y curl git ruby1.9.1 rubygems1.9.1 chef

Copy the validation.pem and webui.pem

This is the key that allow you to register your host as a client to the chef server
$ scp root@chef-server:/etc/chef/validation.pem  /etc/chef/validation.pem

This is the key that allows you to authenticate yourself as an admin user to the chef server
Chef requires an existing admin to authorize a new admin
$ scp root@chef-server:/etc/chef/webui.pem  /etc/chef/webui.pem

Run Knife Configure

$ knife configure -i
Example Output:

Overwrite /root/.chef/knife.rb? (Y/N) y
Please enter the chef server URL: [http://chef-server:4000] http://chef-server:4000
Please enter a clientname for the new client: [root] jtran
Please enter the existing admin clientname: [chef-webui]
Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem]
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef/validation.pem]
Please enter the path to a chef repository (or leave blank):
Creating initial API user...
Created client[jtran]
Configuration file written to /root/.chef/knife.rb

Verify Knife is working

$ knife client list
Example Output:

  jtran
  chef-webui
  chef-validator
Advertisements

Chef – Attribute overriding

Let’s pretend we have a cookbook named “wonka”

in ~/chef-repo/cookbooks/wonka/attributes/default.rb

default[:wonka][:gobstopper]  = "everlasting"
default[:wonka][:kazoozle]    = "alittle"

We want to override the value of [:wonka][:gobstopper] for a node named “oompaloompa01”

Without an override defined your json should look something like the following
You can issue:
$ knife node edit ooompaloopma01

{
  "run_list": [
    "recipe[chocolate_factory::default]"
  ],
  "chef_environment": "development",
  "name": "oompaloompa01",
  "normal": {
    "chef_environment": "development",
    "name": "oompaloopma01",
    "normal": {
      "tags": [

      ]
    },
    "tags": [

    ]
  }
}

Now let’s say you want to define default[:wonka][:gobstopper] = “allgone” with an override
Your json should look like the following

{
  "run_list": [
    "recipe[chocolate_factory::default]"
  ],
  "chef_environment": "development",
  "name": "oompaloompa01",
  "normal": {
    "chef_environment": "development",
    "name": "oompaloopma01",
    "wonka": {
      "gobstopper": [
        "allgone"
      ]
    },
    "normal": {
      "tags": [

      ]
    },
    "tags": [

    ]
  }
}

that should commit the override to that specific node.
you can check the values of a node’s attributes with the following command ( where the attribute group you want to look at is “wonka” )
$ knife node show oompaloompa01 -a wonka

Now just run chef-client on oompaloopa01 and you should see the override take effect.

Chef – Encrypted Data-bags example

Create your encrypt/decrypt “key”

$ openssl rand -base64 512 > ~/.chef/encrypted_data_bag_secret

Create a new “data bag” named “mysecrets”

$ knife data bag create mysecrets

Create a new json with information that you want encrypted.

This will be stored inside the “data bag” named “mysecrets”
This will use the “key” you created earlier to encrypt
We will store this as “marioworld”

$ knife data bag create mysecrets marioworld –secret-file ~/.chef/encrypted_data_bag_secret
* This will prompt open an editor to add items to json

{ "id": "marioworld",
"user": "luigi"
"pass": "yahoo"
}

Now Create a simple recipe and template file that will utilize this encrypted “data bag”

Create the Recipe

$ knife cookbook create databag-test
$ cd ~/chef-repo/cookbooks/recipes/
$ vi default.rb

#
# Cookbook Name:: databag-test
# Recipe:: default
#
# Copyright 2012, James Tran
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# This is where you will store a copy of your key on the chef-client
secret = Chef::EncryptedDataBagItem.load_secret("/etc/chef/encrypted_data_bag_secret")

# This decrypts the data bag contents of "mysecrets->marioworld" and uses the key defined at variable "secret"
luigi_keys = Chef::EncryptedDataBagItem.load("mysecrets", "marioworld", secret)

template "/tmp/databag" do
     variables(:mypass => luigi_keys['pass'],
               :myuser => luigi_keys['user'])
     owner "root"
     mode  "0644"
     source "databag_test.erb"
end

Create the Template

$ cd ~/chef-repo/cookbooks/databag-test/templates
$ vi databag_test.erb

Username: <%= @myuser %>
Password: <%= @mypass %>

Copy your “key” to the node

$ scp ~/.chef/encrypted_data_bag_secret root@somenode:/etc/chef/

Add the recipe to a node and run chef-client

$ knife node run_list add somenode “recipe[databag-test]”
$ knife ssh “name:somenode” -x root “chef-client”

Verify the contents of the new file created at /tmp/databag

$ knife ssh “name:somenode” -x root “cat /tmp/databag”

Username: luigi
Password: yahoo

Chef – Useful knife commands

Bootstrap

Bootstrap a chef-client system:
* This will login to 192.168.5.111 and login as jtran and run “chef-client” command with sudo and apply the recipe[ntp]
* you will be prompted for a password otherwise pass flag -P <PASSWORD>
$ knife bootstrap 192.168.5.111 -x jtran –sudo -r ‘recipe[ntp]’
Boostrap with a template file ( each OS needs their own bootstrap script )
$ knife bootstrap 192.168.5.111 -x jtran –sudo -r ‘recipe[ntp]’ –template-file ~/chef-repo/bootstrap/precise.rb
Bootstrap with proxy
$ knife bootstrap 192.168.5.111 –bootstrap-proxy http://proxyhost:3128 -x jtran –sudo  -r ‘recipe[ntp]’

Common Error:
Knife bootstrap: ERROR: TypeError: can’t convert false into String
This happens when knife can’t find the .chef directory in it’s current working directory, you should also be able to move to your ~/chef-repo directory to get around this error.

SSH

For help type:
knife ssh –help

-a = attribute that’s not FQDN ( example is ipaddress )
-x = username to login with
-P = password
-E = environment

This will ssh with the attribute: ipaddress ( default is to use hostname ) with user “root” and password “none” and execute for all system with role “webserver”
$ knife ssh -a ipaddress -x root -P none ‘role:webserver’ ‘uptime’

This is an example of a wildcard match for hosts in the chef-server database
$ knife ssh -a ipaddress -x root -P none ‘name:host1*’ ‘uptime’
‘name:host1*’  = query names that match host1*
‘uptime’ = command to run

The following would run chef client on all of your nodes
$ knife ssh ‘name:*’ ‘sudo chef-client’

The following would run chef client on all the nodes with the role “webapp”
$ knife ssh ‘role:webapp’ ‘sudo chef-client’

ssh to single node:
$ knife ssh ‘name:webserver01’ ‘sudo chef-client’

Run chef client on all nodes with role  “webapp” in environment “dev”
$ knife ssh -E dev ‘role:webapp’ ‘sudo chef-client’

Node Information

Get all the attributes of a node
$ knife node show nodename -a node

Get all the attributes of a certain attribute group
* example is you have attributes in your attributes/default.rb like default[:whynot][:zoidberg] = “woopwoop”
$ knife node show nodename -a whynot

Ruby – :Symbols and “Strings”

I’m no ruby expert.
Actually i only know enough to write a bit of chef recipes.
If you read enough chef recipes you’ll notice a syntax like the following occur often

default[:mario][:powerup] = "mushroom"

and sometimes you’ll see it as

default["luigi"]["powerup"] = "fireflower"

So what’s the difference?

SYMBOL

A symbol is immutable. This means you’re not reassigning values to it later. It stays as is, like a hillbilly in a trailer home.
:bowser

STRING

A string is mutable. This means you can keep changing the value of it on the fly. Like a gigolo in a bad economy.
“bowser”
 

All of this information was stolen from another extremely useful and thorough blog at: www.robertsosinski.com
He’s exponentially better at explaining this than i am.

Chef – Simple Cookbook Example

* this assumes your cookbook home is ~/chef-repo/cookbooks

$ knife create cookbook mytomcat
$ vi ~/chef-repo/cookbooks/mytomcat/recipes/default.rb

#
# Cookbook Name:: mytomcat
# Recipe:: default

#
# Copyright 2012, James Tran
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

 # This allows chef to create users and their passwords
gem_package "ruby-shadow" do
  action :install
end

# Create a unix group
group "webadmin" do
     gid 100001
end

# To create an encrypted password use the following:
# openssl passwd -1 "theplaintextpassword"

# Create a unix user
user "webadmin" do
     comment "Web Administrator"
     uid 10001
     gid "web"
     home "/home/webadmin"
     shell "/bin/bash"
     password "$1$2QYepl2p$.7ckFmevVtpBZpokJCuSd."
end

# Create a directory
directory "/opt/apps/" do
     owner "webadmin"
     group "web"
     mode "0755"
     action :create
     recursive true
end

# Run a bash shell -  download and extract tomcat
bash "install_tomcat" do
     user "root"
     cwd "/opt/apps"
     code <<-EOH
       wget http://mirrors.ibiblio.org/apache/tomcat/tomcat-7/v7.0.27/bin/apache-tomcat-7.0.27.tar.gz
       tar -xzf apache-tomcat-7.0.27.tar.gz
       chown -R webadmin:webadmin /opt/apps
     EOH
     not_if "test -d /opt/apps/apache-tomcat-7.0.27"
end