A Policyfile is a single document associated with nodes, cookbooks, and settings uploaded to the Chef server that helps manage role, environment, and community cookbook data. When nodes perform a Chef client run, they use recipes that are specified in
the Policyfile run list.
Policyfile makes it easier to test and promote code safely with a more straightforward interface. It improves the user experience and resolves real-world problems that workflows built around Chef often face. Below, are
few advantages of using Policyfiles in Chef.
- Focus the workflow on the entire system
- Safer development workflows
- Less expensive computation
- Code visibility
- Role mutability
- Cookbook mutability
Setting up your Environment
Whether you're working on a Windows, macOS or Linux workstation, the best way to get started with Policyfiles is to install Chef Workstation, a collection of tools that enable you to create, test and run Chef code.
The most common way of working with cookbooks is to upload error-free recipes to the Chef Infra Server using $ knife cookbook upload <cookbook-name>
But the better alternative is to use Policyfiles. Policyfiles bundle multiple cookbooks
and turn profiles into immutable artefacts that can be assigned using Policy Names and Policy Groups. Both these approaches will upload your cookbook, including the recipe files, and make them available for your nodes to download and use.
If you are familiar with Chef Server roles, run lists, and environments, then:
policy_name = role/run list
policy_group = environment
When you create the cookbook with the Chef generator command, $ chef generate cookbook <my_cookbook_name> -k dokken
, a Policyfile.rb file will be created automatically inside the cookbook folder.
Syntax of a Policyfile.rb
Example
# Policyfile.rb - Describe how you want Chef Infra Client to build your system.
# A name describes what the system you're building with Chef does.
name '<my_cookbook_name>'
# Where to find external cookbooks:
default_source
:chef_repo, "~/chef-repo/cookbooks" do |s|
s.preferred_for "my_cookbook_name"
end
default_source :supermarket
default_source :chef_server,
'https://ec2-3-82-51-41.compute-1.amazonaws.com/organizations/lab’
#
run_list: chef-client will run these recipes in the order specified.
run_list 'my_cookbook_name::default'
Notice in this example that you have defined three default_source entries. The chef_repo
entry will check the local path for cookbook content, the second checks supermarket.chef.io
, and the chef_server
checks personal
Chef Infra Server content.
The run_list
entry (or entries) describes the cookbook and the path in Chef notation. Here, my_cookbook_name::default
is pointing to ~/chef-repo/cookbooks/my_cookbook_name/recipes/default.rb
. You can add more than
one run_list item and create profiles that tie several different cookbooks into a single, immutable Policyfile.
When your policyfile is complete, run $ cookstyle –a
in your cookbook directory to double-check the syntax.
$ cd ~/chef-repo/cookbooks/my_cookbook/
$ cookstyle –a
With Policyfiles, you can bundle your cookbooks and compliance profiles and upload them to your Chef server together.
With Policyfile.rb, run chef fetches dependencies to generate a Policyfile.lock.json
. Since you haven’t specified any dependencies in this example yet, you need not fetch anything, but will need the lockfile to be developed before
proceeding.
$ chef install Policyfile.rb
Each time you create or update the lock, Chef will automatically generate a revision_id
based on the content. These values are used to automatically version your policies so that different revisions of a policy can be applied to different
sets of servers.
"revision_id": "42df6gth3cyuaccd29538ae972896992b",
Chef push command bundles up everything and sends it to your Chef server.
$ chef push default Policyfile.lock.json
The push command allows you to set and create Policy Groups. You can create policy groups for different purposes such as build, test and prod, and then associate your cookbooks and profiles with those groups. This approach replaces Chef Roles and Environments.
The revision id that is generated as part of your lockfile will be the single identifier for the policy. So, in order to see which policy is active you can simply run the following command:
$ chef show-policy webserver
Webserver
===========
* prod: 7854a856a6
Here you have the first ten characters of your revision id which indicate the version of policy that is currently active for the Prod group.
With your recipes and inspec.yml in place and your Policyfile.rb set, you can now test your cookbook and compliance controls with Test Kitchen or bootstrap some nodes and apply your cookbook and profile to raw machines.
Some important commands to work with Policyfiles:
$ chef generate policyfile
is a command to generate the file that is used with Policyfile.
$ chef show-policy POLICY_NAME POLICY_GROUP (option)
is a command to display revisions for every Policyfile.rb file that is on the Chef Infra server.
$ chef clean-policy-cookbooks
is a command to delete cookbooks that are not used by Policyfile files. Cookbooks are considered unused when they are not referenced by any policy revisions on the Chef server.
$ chef clean-policy-revisions
is a command to delete orphaned policy revisions to Policyfile files from the Chef server. An orphaned policy revision is not associated with any policy group and therefore is not in active use by any node.
$ chef delete-policy POLICY_NAME (options)
is a command to delete all revisions of the named policy that exist on the Chef server.
Conclusion
We encourage the Chef Community to adopt Policyfiles since they are easier to learn than the legacy workflow, give you better control over change management, and are more flexible for security-conscious implementations.