chef include recipes override attributes - attributes

When you include a recipe in another recipe how to do you override the attributes.
It looks the include recipe used the default attributes not the attributes of the recipe when it was run previously in the run_list.

When you are creating a wrapper cookbook, it is common to override attributes.
Suppose, you have my_web_server cookbook with my_web_server/recipes/default.rb like this:
include_recipe "apache2"
And you would like to override attribute default_site_enabled from apache2 cookbook.
Then your file my_web_server/attributes/default.rb should look like:
override['apache']['default_site_enabled'] = true
And don't forget to specify dependencies in my_web_server/metadata.rb like:
depends "apache2"

I often use roles for override attributes.
Say I have two cookbooks, one for my sweet_rails_app, one to install/configure apache and passenger to install my app on top of.
In my sweet_rails_app_cookbook I may have:
# coding: UTF-8
# Cookbook Name:: sweet_rails_app
# Recipe:: default
include_recipe 'apache_passenger_cookbook::default'
... # recipe code
All attributes in both cookbooks set at the default level in either cookbook.
# coding: UTF-8
name 'sweet_rails_app'
description 'Deploys Sweet Rails App'
run_list "recipe[sweet_rails_app_cookbook]"
base_dir = '/opt/sweet_rails_app'
override_attributes(
sweet_rails_app: {
base_dir: base_dir,
... # more override attributes
},
apache_passenger: {
document_root: base_dir
}
)
Then the role is all that I need to add to the run_list for the node. This also has the added bonus of controlling the order of execution of the two cookbooks.

Related

In Chef how can you pass attributes with "include_recipe"?

I need to call a recipe and pass it specific attribute data, like:
include_recipe [nginx::passenger['my_attributeA' => 'foobar' , 'my_attributeB' => 'foofii']
i.e. in my wrapper, I have to pass data to a called cookbook.
Thanks
Node attributes in chef are global variables you should do this by setting them in the attributes file:
my_cookbook/attributes/default.rb:
default['my_attributeA'] = 'foobar'
default['my_attributeB'] = 'foofii'
my_cookbook/recipe/default.rb:
include_recipe "nginx::passenger"
my_cookbook/metadata.rb:
name "my_coobook"
version "1.2.3"
depends "nginx"
Note, gnerally you'd be setting node attributes like default['nginx']['some_nginx_cookbook_attribute'] in your wrapper to control the nginx cookbook, you probably wouldn't be setting something arbitrary like default['my_attributeA'].
there is no need to pass an argument for attribute assignment; rather, you will need to overload the attribute before including the desired recipe.
the attributes set in the dependent cookbooks before including other dependee cookbook, will be merged.
if the attribute precedence levels are the same, then that data is merged. If the attribute value precedence levels in an array are different, then that data is replaced. For all other value types (such as strings, integers, etc.), that data is replaced.

define keystone_user from openstack/puppet-keystone via hiera?

I am using https://github.com/openstack/puppet-keystone to set up an OpenStack management/controller node. I need to add the 'glance' user to keystone. I want to try and do as much as I can in my hiera data so my manifest will be simple.
Here is my manifest:
class kilo2_keystone {
include controller_ceph
include keystone
include keystone::config
include keystone::user
# keystone_user { 'glance':
# ensure => present,
# }
}
The commented out section works, but I want to be able to do include keystone::user and supply the parameters in my hiera data like so:
keystone::user:
"%{hiera('glance_admin_user')}":
ensure: present
But when I run puppet agent -t on my node I get this error:
Could not find class ::keystone::user
The commented-out code declares a resource of type keystone_user, not a class. Presumably its type, keystone_user, is provided by the puppet-keystone module. The include() family of functions are for declaring classes, not resources, so they are inapplicable to keystone_user.
There is more than one way you could proceed. If you don't anticipate wanting to anything more complicated than declaring one or more keystone_users present, then I'd recommend giving your class a parameter for the user name(s), to which you can assign a value via Hiera:
class kilo2_keystone($usernames = []) {
include controller_ceph
include keystone
include keystone::config
keystone_user { $usernames:
ensure => present,
}
}
On the other hand, if you want to be able to declare multiple users, each with its own set of attributes, then the create_resources() function is probably the path of least resistance. You still want to parameterize your class so that it gets the data from Hiera via automated data binding, but now you want the data to be structured differently, as described in the create_resources() docs: as a hash mapping resource titles (usernames, in your case) to inner hashes of resource parameters to corresponding values.
For example, your class might look like this:
class kilo2_keystone($userdata = {}) {
include controller_ceph
include keystone
include keystone::config
create_resources('keystone_user', $userdata)
}
The corresponding data for this class might look like this:
kilo2_keystone::userdata:
glance:
ensure: present
enabled: true
another_user:
ensure: absent
Note also that you are placing your kilo2_keystone class in the top scope. You really ought to put it in a module and assign it to that module's namespace. The latter would look like this:
class mymodule::kilo2_keystone($userdata = {}) {
# ...
}

How to build a file based on defined-type instances in Puppet

I want my Puppet class to create a file resource with contents based on all instances of a particular defined type. I looked at this question with the idea of iterating over the instances to build the file, but apparently it's a "Bad Idea" per the one answer currently there.
Some background: I am building a monitor_service class in Puppet to deploy a custom monitoring application. The application reads a config file that tells it what to monitor, one item per line, along the lines of
ITEM: /var/things/thing-one (123)
ITEM: /var/things/thing-two (456)
I am also writing a defined type that deploys instances of the monitored items:
define my_thing::monitored_thing ( $port ) {
file { "/var/things/$name":
...
}
}
On a given node, I set up several monitored_things like
my_thing::monitored_thing { "thing-one":
port => 123
}
my_thing::monitored_thing { "thing-two":
port => 456
}
What's the "right" Puppet idiom for building the monitoring service config file? I would prefer for this to work in such a way that the monitor_service class doesn't have to be told which monitored_thing instances it is watching -- just creating a monitored_thing instance should cause it to be added to the config file automatically.
There are several ways to modify/declare only part of a file within multiple defined types:
Use puppetlabs-stdlib's file_line. This lets you specify that a file should contain a specific line. Best when you do not care about the other file contents and just want to make sure a line is present or absent.
Use puppetlabs-concat if you want to make sure that the final file only includes the fragments that you are specifying or the order of the fragments matters.
Use the augeas type if you need to edit/add configuration to a file with a more complicated structure, like xml, apache configurations, etc.

Hiera, default site.pp and error could not find class

I have a server who was running puppet and hiera and, for the moment, 1 client.
I want to manage all my nodes with hiera config files so I only put this in /etc/puppet/manifests/site.pp :
hiera_include(classes, '')
In my file /etc/puppet/hieradata/common :
---
classes:
- "common_test"
- fw_test
- zabbix::agent
zabbix::agent:zabbix_version : '2.2'
zabbix::agent:server: 192.168.1.1
zabbix::agent:serveractive: '192.168.1.1'
zabbix::agent:hostname: 'Test_puppet'
zabbix::agent:manage_firewall: true
With this configuration my parameters (192.168.1.1, true, Test_puppet, etc.) are not set on my client.
Second question, when I add zabbix::userparameters in my class list I have this error Could not find class zabbix::userparameters for...
But this class exist (I use this package https://forge.puppetlabs.com/wdijkerman/zabbix)
I take this example but it's also does'nt work with others classes for the parameters error.
Best regards.
Your parameter keys are incorrect. For example, this ...
zabbix::agent:zabbix_version : '2.2'
... should instead be ...
zabbix::agent::zabbix_version: '2.2'
. The main issue is one too few colons between zabbix::agent and zabbix_version. I don't think whitespace between the key and trailing colon matters, but it's more conventional to not have any.
As for zabbix::userparameters, it is a (defined) resource type, not a class. You cannot include it (or hiera_include() it).

Global resources in Puppet

Is it possible to add a global resource?
I have about 1000 nodes with different configurations and now I want to install a package on every single node. Can it be done in site.pp?
I have a default node, but from what I can tell it is only for unrecognised nodes so I don't think this is the way to change it.
This will depend on the way you have written your puppet manifests. If you have a class included on every node, then you could add the definition to that.
You could user hiera to allow you to customise the default packages on a per machine basis. If you had a module called siteconfig, then you could could create a class something like;
modules/siteconfig/manifests/init.pp
class siteconfig {
include siteconfig::defaults
package{$::siteconfig::params::packages:
ensure => 'present',
}
}
modules/siteconfig/manifests/params.pp
class siteconfig::params(
$packages = []
) {
validate_array($packages)
}
and then define siteconfig::params::packages in hiera as an array of packages to be installed by default. This means that you could easily add more default packages by editing the array in hiera, and you could customise it on a per-host basis.
Bonus points if you work out how to use create_resources instead!

Resources