Effortless Config
Effortless Config
Effortless Config is the pattern for managing your Chef Infra workloads. It uses Chef Habitat and Chef Policyfiles to build an artifact that contains the cookbooks and their dependencies alongside the scripts necessary to run them on your systems.
Effortless Environment Set-up
- Install Chef Workstation
- Install Chef Habitat
- Configure Chef Habitat on your workstation by running
hab setup
Patterns
Chef Repo Cookbook Pattern
This pattern uses the chef-repo to store and organize everything you need to define your infrastructure with Chef Infra, including:
- Cookbooks (including recipes, attributes, custom resources, libraries, and templates)
- Data bags
- Policyfiles
The Chef Effortless GitHub repository has an example chef-repo for you to explore.
To use this pattern, navigate to the chef-repo directory that you want to use:
cd chef-repo
Create a
habitat
directory from the command line with:mkdir habitat
Make a plan file
Make a
plan.ps1
for a cookbook that targets Microsoft Windows systems and aplan.sh
for a cookbook that targets Linux systems. You can have both aplan.ps1
and aplan.sh
in thehabitat
directory for cookbooks that target both systems. Create a Linux plan:touch plan.sh
Add information about the cookbook to the plan
Add this information to the
plan.sh
file:pkg_name=<my_policyfile> pkg_origin=<my_origin> pkg_version="0.1.0" pkg_maintainer="My Name and Email" pkg_license=("Apache-2.0") pkg_scaffolding="chef/scaffolding-chef-infra" pkg_svc_user=("root") scaffold_policy_name="<my_policyfile>"
If you do not have a
policyfiles
directory in your chef-repo, create one:mkdir policyfiles
Generate a Policyfile:
chef generate policyfile policyfiles/my_policyfile
Example of a policyfile.rb
:
# Policyfile.rb - Describe how Chef Infra should build your system.
#
# For more information on the Policyfile feature, visit
# https://docs.chef.io/policyfile.html
name "base"
# Where to find external cookbooks
default_source :supermarket
default_source :chef_repo, "../"
# run_list: run these recipes in the order specified.
run_list [
"patching::default",
"hardening::default"
]
# attributes: set attributes from your cookbooks
default['hardening'] = {}
default['patching'] = {}
Build the package:
Run the following command to build the package:
hab pkg build .
Edit the
kitchen.yml
file to look similar to this:--- driver: name: vagrant synced_folders: - ["./results", "/tmp/results"] provisioner: name: shell verifier: name: inspec platforms: - name: centos-7.6 suites: - name: base provisioner: arguments: ["<my_origin>", "<my_package_name>"] verifier: inspec_tests: test/integration/base
Create a
bootstrap.sh
script and include:#!/bin/bash export HAB_LICENSE="accept-no-persist" export CHEF_LICENSE="accept-no-persist" if [ ! -e "/bin/hab" ]; then curl https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.sh | sudo bash fi if grep "^hab:" /etc/passwd > /dev/null; then echo "Hab user exists" else useradd hab && true fi if grep "^hab:" /etc/group > /dev/null; then echo "Hab group exists" else groupadd hab && true fi pkg_origin=$1 pkg_name=$2 echo "Starting $pkg_origin/$pkg_name" latest_hart_file=$(ls -la /tmp/results/$pkg_origin-$pkg_name* | tail -n 1 | cut -d " " -f 9) echo "Latest hart file is $latest_hart_file" echo "Installing $latest_hart_file" hab pkg install $latest_hart_file echo "Determining pkg_prefix for $latest_hart_file" pkg_prefix=$(find /hab/pkgs/$pkg_origin/$pkg_name -maxdepth 2 -mindepth 2 | sort | tail -n 1) echo "Found $pkg_prefix" echo "Running chef for $pkg_origin/$pkg_name" cd $pkg_prefix hab pkg exec $pkg_origin/$pkg_name chef-client -z -c $pkg_prefix/config/bootstrap-config.rb
Run Test Kitchen to ensure the cookbook works
Use this command to spin up a CentOS 7 virtual machine (VM) locally and run the cookbook using the latest Chef Infra Client:
kitchen converge base-centos
If you experience errors in this Chef run, you may need to supply attributes or make modifications to your Policyfile, so that your cookbook can run using the latest Chef Infra Client.
When ready, delete the VM instance by running:
kitchen destroy
Upload the Policyfile pkg to Chef Habitat builder by running the following commands:
source results/lastbuild.env hab pkg upload results/$pkg_artifact
To run the Policyfile on a system, install Chef Habitat services and run:
hab svc load <my_origin>/<my_policyfile_name>
Policyfile Cookbook Pattern
This pattern builds a Chef Habitat artifact for the Policyfile cookbook. You can find an example Policyfile cookbook in the Chef Effortless GitHub repository.
To use this pattern, navigate to the cookbook you want to use:
cd chef-repo/cookbooks/my_cookbook
Create a
habitat
directory from the command line with:mkdir habitat
Make a plan file
Use a
plan.ps1
for a cookbook targeting Windows. Use aplan.sh
for a cookbook targeting Linux. If the cookbook targets both Windows and Linux, you can have both aplan.ps1
and aplan.sh
in thehabitat
directory. Create a plan in Linux with the following command:touch plan.sh
Add some information about the cookbook to the plan
plan.sh
pkg_name=<Name of my_cookbook artifact> pkg_origin=<my_origin> pkg_version="<Cookbook version>" pkg_maintainer="<My Name>" pkg_license=("<License for my_cookbook example Apache-2.0>") pkg_scaffolding="chef/scaffolding-chef-infra" scaffold_policy_name="Policyfile" scaffold_policyfile_path="$PLAN_CONTEXT/../" # habitat/../Policyfile.rb
Make a Policyfile in the
cookbook
directoryExample of a
policyfile.rb
file:# Policyfile.rb - Describe how you want Chef to build your system. # # For more information on the Policyfile feature, visit # https://docs.chef.io/policyfile.html # A name that describes what the system you're building with Chef does. name '<my_cookbook_name>' # Where to find external cookbooks: default_source :supermarket # run_list: chef-client will run these recipes in the order specified. run_list '<my_cookbook_name>::default' # Specify a custom source for a single cookbook: cookbook '<my_cookbook_name>', path: '.'
Build the package:
hab pkg build <my_cookbook>
Edit the
kitchen.yml
file to look similar to this:--- driver: name: vagrant synced_folders: - ["./results", "/tmp/results"] provisioner: name: shell verifier: name: inspec platforms: - name: centos-7.6 suites: - name: base provisioner: arguments: ["<my_origin>", "<my_cookbook>"] verifier: inspec_tests: test/integration/base
Create a
bootstrap.sh
script and include:#!/bin/bash export HAB_LICENSE="accept-no-persist" export CHEF_LICENSE="accept-no-persist" if [ ! -e "/bin/hab" ]; then curl https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.sh | sudo bash fi if grep "^hab:" /etc/passwd > /dev/null; then echo "Hab user exists" else useradd hab && true fi if grep "^hab:" /etc/group > /dev/null; then echo "Hab group exists" else groupadd hab && true fi pkg_origin=$1 pkg_name=$2 echo "Starting $pkg_origin/$pkg_name" latest_hart_file=$(ls -la /tmp/results/$pkg_origin-$pkg_name* | tail -n 1 | cut -d " " -f 9) echo "Latest hart file is $latest_hart_file" echo "Installing $latest_hart_file" hab pkg install $latest_hart_file echo "Determining pkg_prefix for $latest_hart_file" pkg_prefix=$(find /hab/pkgs/$pkg_origin/$pkg_name -maxdepth 2 -mindepth 2 | sort | tail -n 1) echo "Found $pkg_prefix" echo "Running chef for $pkg_origin/$pkg_name" cd $pkg_prefix hab pkg exec $pkg_origin/$pkg_name chef-client -z -c $pkg_prefix/config/bootstrap-config.rb
Run Test Kitchen to ensure the cookbook works on Linux
Use this command to spin up a CentOS 7 virtual machine (VM) locally and run the cookbook using the latest Chef Infra Client:
kitchen converge base-centos
If you experience errors in this Chef run, you may need to supply attributes or make modifications to your Policyfile, so that your cookbook can run using the latest Chef Infra Client.
When ready, delete the VM instance by running:
kitchen destroy
Upload the habitat pkg to Chef Habitat builder by running the following commands:
source results/lastbuild.env hab pkg upload results/$pkg_artifact
To run the cookbook on a system, install Chef Habitat services and run:
hab svc load my_origin/my_cookbook