Accumulators
This is an advanced topic. You should have already written a Custom Resource and be familiar with:
- The built-in Chef Infra
templateresource - Cookbook execution
with_run_context
Overview
An accumulator is a programming pattern that gathers multiple values together.
In the context of Custom Resources, the accumulator pattern collects a set of properties from Custom Resources, and then applies the collection to a resource.
The steps for setting up an accumulator pattern are:
- Declare a resource
- Edit the resource
- Add both resources to the :root
run_context - Delay the actions on the resources
Example Accumulator: Samba
Samba Linux tool systems for supporting sharing resources in a network with Windows systems. Samba uses a single file for configuration. To share more than one directory using this configuration file, you need to write multiple samba_share resources.
The accumulator pattern lets you split out each configuration section into its own resource.
samba_share 'first_share' do comment 'exported share 1' path '/srv/export' guest_ok true printable false write_list ['test_user_1'] create_mask '0644' directory_mask '0775' options 'inherit permissions' => 'yes' end samba_share 'second_share' do comment 'exported share 2' path '/srv/export_2' guest_ok false printable false write_list ['test_user_2'] create_mask '0644' directory_mask '0775' create_directory false end Example
The following example shows how to:
- Setup the template resource
- Set the
actionto:nothing - Set the
delayed_actionto:create. - Add the template resource to the
rootrun context, which allows thesamba_shareresource to find it. - Use
edit_resourceto find the template - Use
edit_resourceto add new variables to the existing collection
Note: This uses the ||= Ruby method to add a new Hash if one doesn’t exist already.
# action for the samba_server custom resource action :create do package 'samba' # We need to force both the server template and the # share templates into the root context to find each other with_run_context :root do template new_resource.config_file do source 'smb.conf.erb' owner 'root' group 'root' mode '0644' cookbook 'samba' variables(samba_options: new_resource.options) action :nothing delayed_action :create end end end # action for the samba_share custom resource action :add do with_run_context :root do edit_resource(:template, new_resource.config_file) do |new_resource| variables[:shares] ||= {} variables[:shares][new_resource.share_name] ||= {} variables[:shares][new_resource.share_name]['comment'] = new_resource.comment variables[:shares][new_resource.share_name]['path'] = new_resource.path end end end