Chef

Table Of Contents

Custom Lightweight Resources

A LWRP is a part of a cookbook that is used to extend the chef-client in a way that allows custom actions to be defined, and then used in recipes in much the same way as any platform resource. A LWRP has two principal components:

  • A lightweight resource that defines a set of actions and attributes
  • A lightweight provider that tells the chef-client how to handle each action, what to do if certain conditions are met, and so on

In addition, most lightweight providers are built using platform resources and some lightweight providers are built using custom Ruby code

Once created, a LWRP becomes a Ruby class within the organization. During each chef-client run, the chef-client will read the lightweight resources from recipes and process them alongside all of the other resources. When it is time to configure the node, the chef-client will use the corresponding lightweight provider to determine the steps required to bring the system into the desired state.

Where the lightweight resource represents a piece of the system, its current state, and the action that is needed to move it to the desired state, a lightweight provider defines the steps that are required to bring that piece of the system from its current state to the desired state. A LWRP behaves similar to platform resources and providers:

  • A lightweight resource is a key part of a recipe
  • A lightweight resource defines the actions that can be taken
  • During a chef-client run, each lightweight resource is identified, and then associated with a lightweight provider
  • A lightweight provider does the work to complete the action requested by the lightweight resource

The following sections describe the structure, syntax, and options available for both lightweight resources and lightweight providers:

Topic Description
Lightweight Resources A lightweight resource defines custom actions and attributes.
Lightweight Providers w/Chef Resources Many lightweight providers are built using only platform resources, such as file, cookbook_file, template, and so on. These types of resources use recipes to tell the chef-client when to use platform resources during a chef-client run.
Lightweight Providers w/Custom Ruby Some lightweight providers are built using custom Ruby code.

Warning

It is recommended to not mix platform resources with custom resources in the same lightweight provider. This helps ensure the proper processing of platform resources that have been embedded into the resource collection during the chef-client run.

File Locations

Lightweight resources and providers are loaded from files that are saved in the following cookbook sub-directories:

Directory Description
providers/ The sub-directory in which lightweight providers are located.
resources/ The sub-directory in which lightweight resources are located.

The naming patterns of lightweight resources and providers are determined by the name of the cookbook and by the name of the files in the resources/ and providers/ sub-directories. For example, if a cookbook named example was downloaded to the chef-repo, it would be located at /cookbooks/example/. If that cookbook contained two resources and two providers, the following files would be part of the resources/ directory:

Files Resource Name Generated Class
default.rb example Chef::Resource::Example
custom.rb example_custom Chef::Resource::ExampleCustom

And the following files would be part of the providers/ directory:

Files Provider Name Generated Class
default.rb example Chef::Provider::Example
custom.rb custom Chef::Provider::ExampleCustom

Platform vs. Lightweight

The following example uses the file resource to show the difference between it and what it would look like if it were a lightweight resource.

require 'chef/resource'

class Chef
  class Resource
    class File < Chef::Resource

      def initialize(name, collection=nil, node=nil)
        super(name, collection, node)
        @resource_name = :file
        @path = name
        @backup = 5
        @action = "create"
        @allowed_actions.push(:create, :delete, :touch, :create_if_missing)
      end

      def backup(arg=nil)
        set_or_return(
          :backup,
          arg,
          :kind_of => [ Integer, FalseClass ]
        )
      end

      def checksum(arg=nil)
        set_or_return(
          :checksum,
          arg,
          :regex => /^[a-zA-Z0-9]{64}$/
        )
      end

      def group(arg=nil)
        set_or_return(
          :group,
          arg,
          :regex => [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ]
        )
      end

      def mode(arg=nil)
        set_or_return(
          :mode,
          arg,
          :regex => /^0?\d{3,4}$/
        )
      end

      def owner(arg=nil)
        set_or_return(
          :owner,
          arg,
          :regex => [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ]
        )
      end

      def path(arg=nil)
        set_or_return(
          :path,
          arg,
          :kind_of => String
        )
      end

    end
  end
end

The preceding code is simple, traditional Ruby. A number of getter/setter methods are created and inputs are validated against criteria, like regular expressions, strings, true/false, and so on. The lightweight resource looks like this:

actions :create, :delete, :touch, :create_if_missing

attribute :backup,   :kind_of => [ Integer, FalseClass ]
attribute :group,    :regex => [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ]
attribute :mode,     :regex => /^0?\d{3,4}$/
attribute :owner,    :regex => [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ]
attribute :path,     :kind_of => String
attribute :checksum, :regex => /^[a-zA-Z0-9]{64}$/

What this shows are the similarities and differences between resources and lightweight resources. The lightweight resources are easier to write and understand, plus they can offer much the same (if not identical) functionality as the more complex platform resources.

Chef-maintained

Chef maintains a collection of cookbooks that define some common scenarios and provides resources to support them. These cookbooks are located at https://github.com/opscode-cookbooks. To use these resources within recipes, first download the cookbook. Then add those resources to recipes.

Some of the most popular Chef-maintained cookbooks are listed below:

Cookbook Description
apt The apt cookbook is used to configure Apt and Apt services, for managing Apt repositories and preferences.
aws The aws cookbook is used to manage resources that are running in Amazon Web Services.
bluepill The bluepill cookbook is used to install Blue Pill, and then use it to manage services.
chef_handler The chef_handler cookbook is used to distribute and enable exception and report handlers.
cron Use to install cron and start the crond service.
daemontools The daemontools cookbook is used to install and configure daemontools so that it can be used to manage UNIX services.
djbdns The djbdns cookbook is used to install djbdns and use it to configure DNS services.
dmg The dmg cookbook is used to create a DMG package for use with Mac OS X.
dynect The dynect cookbook is used to manage DNS records using the DynECT REST API.
firewall The firewall cookbook is used to manage firewalls and their associated firewall rulesets.
freebsd The freebsd cookbook is used to manage port options for FreeBSD.
gunicorn Gunicorn is a web service gateway interface server for UNIX that is a pre-fork worker model from the Ruby Unicorn project. The gunicorn cookbook is used to install and configure Gunicorn.
homebrew The homebrew cookbook is used to install and configure Homebrew for use as the package manager for Mac OS X.
iis The iis cookbook is used to install and configure Internet Information Services (IIS).
lvm Use to install the lvm2 package, and then manage LVM.
maven The maven cookbook is used to install and configure Apache Maven.
openssh The openssh cookbook is used to install OpenSSH.
omnibus Use to prepare a machine to be an Omnibus builder.
php The php cookbook is used to install and configure PHP and PHP modules.
postfix Use to install and configure postfix for client or outbound relayhost.
powershell Use to run Windows PowerShell. See the powershell_script resource (built into the chef-client) for more information about improved ways to run Windows PowerShell when using Chef.
rabbit mq The rabbitmq cookbook is used to install and configure RabbitMQ.
squid Use to configure squid as a caching proxy.
sudo The sudo cookbook is used to install sudo and configure /etc/sudoers.
transmission The transmission cookbook is used to install and configure the Transmission BitTorrent client.
webpi The webpi cookbook is used to run the Microsoft Web Platform Installer (WebPI).
windows The windows cookbook is used to configure auto run, batch, reboot, enable built-in operating system packages, configure Microsoft Windows packages, reboot machines, and more.
yum The yum cookbook is used to manage the contents of the yum.conf configuration file for global Yum configurations and for individual Yum repositories.