I am going to use puppet bind module from
https://github.com/thias/puppet-bind
any idea how I can use hiera in yaml format with this?
I have tried using this in Hiera, but it does not pass the values to the module.
---
classes:
- 'bind::server'
profile::bind::conf:
'/etc/named.conf':
zones:
'example.com': ['type master', 'file ]
any suggestions?
The parameters cannot be bound to the module's classes automatically - zones are created through a define.
Creating values for define instances in Hiera is a two-step process.
Create the data. Your's is fine, but the key is misleading.
e.g.
bind_server_confs:
'/etc/named.conf':
zones:
'example.com': ['type master', 'file ]
Create resources from the hash using the create_resources function.
like
create_resources('bind::server::conf', hiera('bind_server_confs'), {})
The default result of {} will (correctly) lead to no resources being created.
Related
I am having some trouble using module hiera data.
module: /etc/puppetlabs/code/environments/production/modules/usehiera
tree structure:
usehiera
usehiera/hiera.yaml
usehiera/data
usehiera/data/common.yaml
usehiera/manifests
usehiera/manifests/init.pp
hiera.yaml:
---
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: 'common'
- path: 'common.yaml'
data/common.yaml:
---
usehiera::apples: 'this is some data'
manifests/init.pp:
class usehiera{
file{'/tmp/hiera_lookup.txt':
ensure => present,
#content => hiera('oranges') #this works with global hiera
content => $apples
}
}
As you can see I seem to have the global hiera working with "hiera('oranges')" when I run this module on my node. When I try to use the module hiera data the puppet run finishes successfully but hiera_lookup.txt is just empty.
Steps I have taken to troubleshoot:
restart puppetserver after hiera changes
try using $usehira::apples
try using hiera('apples')
moving my hiera.yaml inside data/
using lookup with --explain doesnt really give me anything useful, just says lookup() not found
Can anyone help me out? I have been stuck with this for a decent amount of time and not sure what the issue could be.
As #MattSchuchard pointed out in comments, your hiera.yaml is inappropriately formed. The documentation contains examples.
But a bigger issue seems to be incorrect expectations. Evidently, you assume that ordinary class variable $usehiera::apples will automatically take the value associated with the corresponding key in the module-level hiera data, but that simply is not the case. Hiera data -- whether global, environment-level, or module-level -- is automatically bound to class parameters, but not to other class variables.
You can set ordinary class variables from hiera data via explicit lookup:
# the hiera() function is deprecated; use lookup():
$apples = lookup('usehiera::apples')
Alternatively, you can make $apples a class parameter:
class usehiera(String $apples) {
file{'/tmp/hiera_lookup.txt':
ensure => 'present',
content => $apples,
}
}
Note well that if you make it a parameter then its value can also be customized via a resource-like class declaration, which takes precedence over your Hiera data.
Note also that the difference between global, per-environment, and module-specific Hiera data is just scope and precedence, not functionality.
is it possible to create a system group from hiera?
I know how to create a system group in the manifest via class, but I have failed to move that to hiera
Any example of creating a systemgroup "foo" with gid "1000" in hiera would be highly appreciated.
Thanks
Hiera is a data service. It can provide data about system groups, or about any kind of resource at all, but you need at least a little bit of manifest code somewhere to make a resource declaration out of that. For example, this pushes all the details out of the manifest and into Hiera (or other manifest code):
class mymodule::groups(Hash[String, Hash] $groupdata) {
$groupdata.each |$gname, $params| {
group { $gname: * => $params }
}
}
Hiera data feeding that class might look something like this:
mymodule::groups::groupdata:
group1:
system: true
group2:
gid: 42
system: true
group3:
ensure: absent
The value for $groupdata is, as declared by the class, a Hash of Hashes. The keys are group names, and the values are hashes of property names and values for the built-in Group resource type.
There are many other ways that one could accomplish this, with different advantages and disadvantages. I present this one because it is among the simplest.
I read a lot about ordering puppet classes with containment (iam using Puppet 6). But it still does not work for me in one case. Maybe my english is not good enough and i miss something. Maybe somebody know what iam doing wrong.
I have a profile to installing a puppetserver (profile::puppetserver). This profile has three sub-classes which I contain within the profile::puppetserver
class profile::puppetserver(
) {
contain profile::puppetserver::install
contain profile::puppetserver::config
contain profile::puppetserver::firewall
}
That works fine for me. Now I want to expand this profile and install PuppetDB. For this, i use the puppetdb module from puppet forge:
So what i do is add profile::puppetserver::puppetdb and the contain to the profile::puppetserver
class profile::puppetserver::puppetdb(
) {
# Configure puppetdb and its underlying database
class { 'puppetdb': }
# Configure the Puppet master to use puppetdb
class { 'puppetdb::master::config': }
}
When i provision my puppetserver first and add the profile::puppetserver::puppetdb after it, puppetdb installs and everything works fine.
If I add it directly with contain, and provisioning everything at once, it crashes. It's because the puppetdb module is installed randomly during my master server installs (and also the postgresql server and so on). That ends in my puppetserver is not running and my puppetdb generate no local ssl certificates and the service doesn't comes up.
What i try first:
I installed the puppetdb Package in my profile::puppetserver::puppetdb directly and use the required flag. It works when i provision all at once.
class profile::puppetserver::puppetdb (
) {
Package { 'puppetdb':
ensure => installed,
require => Class['profile::puppetserver::config']
}
}
So i think i could do the same in the code above:
class profile::puppetserver::puppetdb(
) {
# Configure puppetdb and its underlying database
class { 'puppetdb':
require => Class['profile::puppetserver::config']
}
# Configure the Puppet master to use puppetdb
class { 'puppetdb::master::config':
require => Class['profile::puppetserver::config']
}
}
But this does not work...
So i read about puppet class containment and ordering by chains. So i did this in my profile::puppetserver
class profile::puppetserver(
) {
contain profile::puppetserver::install
contain profile::puppetserver::config
contain profile::puppetserver::firewall
contain profile::puppetserver::puppetdb
Class['profile::puppetserver::install'] ->
Class['profile::puppetserver::config'] ->
Class['profile::puppetserver::firewall'] ->
Class['profile::puppetserver::puppetdb']
}
But it still does not have any effect... he still starts to install postgresql and the puppetdb package during my "puppetserver provisioning" in the install, config, firewall steps.
How i must write the ordering, that all things from the puppetdb module, which i call in profile::puppetserver::puppetdb, only starts when the rest of the provisioning steps are finished?
I really don't understand it. I think maybe it haves something to do with the fact, that i declare classes from the puppetdb module inside of profile::puppetserver::puppetdb and not the directly Resource Type. Because when i use the Package Resource Type with the Require Flag, it seems to work. But i really don't know how to handle this. I think there must be a way or?
I think maybe it haves something to do with the fact, that i declare
classes from the puppetdb module inside of
profile::puppetserver::puppetdb and not the directly Resource Type.
Because when i use the Package Resource Type with the Require Flag, it
seems to work.
Exactly so.
Resources are ordered with the class or defined-type instance that directly declares them, as well as according to ordering parameters and instructions applying to them directly.
Because classes can be declared multiple times, in different places, ordering is more complicated for them. Resource-like class declarations such as you demonstrate (and which you really ought to avoid as much as possible) do not imply any particular ordering of the declared class. Neither do declarations via the include function.
Class declarations via the require function place a single-ended ordering constraint on the declared class relative to the declaring class or defined type, and declarations via the contain function place a double-ended ordering constraint similar to that applying to all resource declarations. The chaining arrows and ordering metaparameters can place additional ordering constraints on classes.
But i really dont know how to handle this. I think there must be a way or?
Your last example shows a viable way to enforce ordering at the level of profile::puppetserver, but its effectiveness is contingent on each of its contained classes taking the same approach for any classes they themselves declare, at least where those third-level classes must be constrained by the order of the second-level classes. This appears to be where you are falling down.
Note also that although there is definitely a need to order some things relative to some others, it is not necessary or much useful to try to enforce an explicit total order over all resources. Work with the lightest hand possible, placing only those ordering constraints that serve a good purpose.
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 = {}) {
# ...
}
Lets say I want to define a set of resources that have dependencies on each other, and the dependent resources should reuse parameters from their ancestors. Something like this:
server { 'my_server':
path => '/path/to/server/root',
...
}
server_module { 'my_module':
server => Server['my_server'],
...
}
The server_module resource both depends on my_server, but also wants to reuse the configuration of it, in this case the path where the server is installed. stdlib has functions for doing this, specifically getparam().
Is this the "puppet" way to handle this, or is there a better way to have this kind of dependency?
I don't think there's a standard "puppet way" to do this. If you can get it done using the stdlib and you're happy with it, then by all means do it that way.
Personally, if I have a couple defined resources that both need the same data I'll do one of the follow:
1) Have a manifest that creates both resources and passes the data both need via parameters. The manifest will have access to all data both resources need, whether shared or not.
2) Have both defined resources look up the data they need in Hiera.
I've been leaning more towards #2 lately.
Dependency is only a matter of declaring it. So your server_module resource would have a "require => Server['my_server']" parameter --- or the server resource would have a "before => Server_module['my_module']".