I can't get my Puppet manifest to find templates the way I'd expect so I thought someone might have a quick answer. I'm new to puppet so just trying to understand all the locations for everything and how to reference files properly. If I'm missing something painfully obvious I apologize.
This works:
file {
$zabbix_agent_conf:
owner => root,
group => root,
mode => 0644,
content => template("/etc/puppet/templates/zabbix/files/zabbix_agent_conf.erb"),
require => Package["zabbix-agent"];
}
This does not:
file {
$zabbix_agent_conf:
owner => root,
group => root,
mode => 0644,
content => template("puppet:///templates/zabbix/zabbix_agent_conf.erb"),
require => Package["zabbix-agent"];
}
My /etc/puppet/puppet.conf:
[main]
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$vardir/lib/facter
templatedir=/etc/puppet/templates
prerun_command=/etc/puppet/etckeeper-commit-pre
postrun_command=/etc/puppet/etckeeper-commit-post
[master]
# These are needed when the puppetmaster is run by passenger
# and can safely be removed if webrick is used.
ssl_client_header = SSL_CLIENT_S_DN
ssl_client_verify_header = SSL_CLIENT_VERIFY
You cannot use the puppet URI scheme in combination with the template function as of yet. According to the docs:
Note that the path to the template doesn’t use the same semantics as
the path in a puppet:/// URL. Sorry about the inconsistency. (Source)
Furthermore:
(If a file cannot be located within any module, the template function
will fall back to searching relative to the paths in Puppet’s
templatedir. However, using this setting is no longer recommended.) (Source)
This means that in order to use the templatedir the template function expects a simple relative path:
template("zabbix/zabbix_agent_conf.erb")
It is not recommended to use the templatedir. There is a good reason for this. It is better to group files together under the common denominator of a module, otherwise things can get pretty messy pretty fast. Think of modules as a good way to group all puppet resources that belong to each other: manifests, files, templates, extensions and tests.
So I would recommend creating a zabbix module. Place your puppet code in a zabbix class within a init.pp in the manifest directory of your zabbix module. Then you can place your template in the templates directory of your zabbix module and you can reference it by:
template("zabbix/zabbix_agent_conf.erb")
Hope this helps. Good luck!
Once in a module, use
template("${module_name}/xxx.erb")
to reference your template files (works on puppet 4.x. Not sure for previous versions).
Related
I'm using Puppet to replace Spacewalk Configuration Channels.
I'm very new to puppet, and the class I'm writing should copy some files to the host system.
I have this in my class:
class main_configurations {
file { '/etc/auditbeat':
ensure => directory,
path => '/etc/auditbeat',
require => File['/etc/auditbeat/auditbeat.yml'],
source => 'puppet:///modules/main_configurations/auditbeat/auditbeat.yml',
recurse => true,
}
}
But when I run puppet agent -t I get the following error:
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Could not find resource 'File[/etc/auditbeat/auditbeat.yml]' in parameter 'require' (file: /etc/puppetlabs/code/environments/production/modules/main_configurations/manifests/init.pp, line: 8) on node <servername>
For completeness, this is the folder structure on my puppet server:
/etc/puppetlabs/code/environments/production/modules/main_configurations/files/auditbeat
/etc/puppetlabs/code/environments/production/modules/main_configurations/files/auditbeat/auditbeat.yml
/etc/puppetlabs/code/environments/production/modules/main_configurations/files/auditbeat/audit.rules.d
/etc/puppetlabs/code/environments/production/modules/main_configurations/files/auditbeat/audit.rules.d/auditbeat-rules.conf
But when I run puppet agent -t I get the following error:
Error: Could not retrieve catalog from remote server: Error 500 on
SERVER: Server Error: Could not find resource
'File[/etc/auditbeat/auditbeat.yml]' in parameter 'require' (file:
/etc/puppetlabs/code/environments/production/modules/main_configurations/manifests/init.pp,
line: 8) on node
As #MattSchuchard explained in comments, that means exactly what it says: you have a require parameter that refers to resource File[/etc/auditbeat/auditbeat.yml], but that (Puppet) resource is not declared in any of the manifest files that were processed. This constitutes an inconsistency in your manifest set. It has nothing to do with which files are available for installation from your module or which are already present on the target, nor about what Puppet might do when given a manifest set free of such inconsistencies.
Considering the declaration that is presented:
file { '/etc/auditbeat':
ensure => directory,
path => '/etc/auditbeat',
require => File['/etc/auditbeat/auditbeat.yml'],
source => 'puppet:///modules/main_configurations/auditbeat/auditbeat.yml',
recurse => true,
}
I'm inclined to think that you misunderstand at least what the require metaparameter means. It is one of several that speak to the relative order in which various resources are applied. It says that application of the resource being declared requires the specified other resources to have successfully been applied before. That's surely not what you intend here.
Moreover, a resource reference such as you are assigning to that parameter does not serve as a resource declaration. It does not contain enough information to do so. As the name suggests, it is a reference to a resource declared elsewhere.
It looks like you are trying to manage a subdirectory tree rooted at /etc/auditbeat to match a tree in your module. In that case, you probably want something more like this:
file { '/etc/auditbeat':
# no path required if it is already given by the resource title
ensure => 'directory',
source => 'puppet:///modules/main_configurations/auditbeat',
recurse => true,
}
Mainly, that drops the require parameter.
Note that that combination will also enable purging for the destination subtree, so that unmanaged non-directories anywhere within are removed. If you don't want that then use recurse => 'remote' instead.
There is a variety of other attributes that you might want to add, mostly to do with ownership and mode for the installed files. If you just want to copy some or all of that from the files on the server then you will want to add source_permissions => 'use'. Alternatively, there are attributes for explicitly specifying ownership and mode in your manifest.
I'm trying to set up a Puppet cron job with the following structure:
file { '/usr/local/sbin/file.py':
mode => '0755',
source => 'puppet:///modules/file.py',
require => File['/usr/local/sbin']
}
cron { "cronjob":
require => "ALL_THE_FILES_ABOVE"
command => "...command_to_run_script..."
minute => '*/1'
}
All of the above is in one file run_script.pp. I'm wondering how I can code the require => "ALL_THE_FILES_ABOVE" part.
Thanks!
Based on the information provided in your question, I am going to make the assumption that the contents of run_script.pp is many file resources and the listed cron resource. You state that you want the cron resource there to require all of the file resources in that class. Based on this, here is a clean and efficient solution.
There are a few complicated/advanced ways to arrive at a clean and efficient solution, but the easiest to understand is to use a resource default: https://puppet.com/docs/puppet/5.3/lang_defaults.html
With this, we can establish attribute/value pair defaults for all file resources contained in that scope. This would make it easier to use the before metaparameter on the file resources instead: https://puppet.com/docs/puppet/5.3/metaparameter.html#before
This simplifies the solution to a one-liner in your class:
File { before => Cron['cronjob'] }
Note there will be a caveat to this method, which is that if you are declaring, requiring, or containing a class within this manifest, then this default could be expanded to that "area of effect" and cause a circular dependency. In that case, you should use a per-expression resource default attribute: https://puppet.com/docs/puppet/5.3/lang_resources_advanced.html#per-expression-default-attributes
You can use a multiple require
file{'path/foo':}
file{'path/bar':}
file{'~/foobar':
require => [ File['path/foo'], File['path/bar'] ]
}
or you can use the ordering arrow
-> (ordering arrow; a hyphen and a greater-than sign) — Applies the resource on the left before the resource on the right.
file{'path/foo':} ->
file{'path/bar':} ->
file{'~/foobar':}
Here is more information about relationships and ordering in Puppet
Let us say that I have a case in which I need to apply only two files from a Puppet configuration on some production servers, without touching the rest of the configuration.
/opt/aservice/myfile/thekey.conf
/opt/myfile/thekey.salt
Let's also say that these are controlled by the following Puppet manifest:
#
# author: Nathan Basanese (nathan#basanese.com)
# date: 04/17/2048
#
class keyconfig ( $cluster ){
notify {"Deploying key config. files to $fqdn":}
file {'/opt/aservice/key/config/thekey.conf':
ensure => present,
mode => '0644',
owner => 'aservice-serv',
group => 'aservice-serv',
source => "puppet:///modules/keyconfig/$cluster/thekey.conf",
}
file {'/opt/aservice/key/config/thekey.salt':
ensure => present,
mode => '0644',
owner => 'aservice-serv',
group => 'aservice-serv',
source => "puppet:///modules/keyconfig/$cluster/thekey.salt",
}
}
How would I apply ONLY these two files to a given server from a Puppet Master?
Perhaps, in the puppet agent command that is run on the target server, could I specify a specific Puppet class to use?
I have used the puppet resource command before, but I'm not sure that would work, here.
Every resource is automatically tagged with the fully qualified name of the class or defined type in which it is declared, and with every namespace segment of the class or type name, among other tags. You can use those tags to filter the resources that will be applied during a given catalog run. In the particular example you describe, you could use
puppet agent --no-daemonize --onetime --tags keyconfig
to apply only the resources declared in class keyconfig (and in any other class declared by keyconfig, recursively, but in this case there are no such other classes).
You can also declare tags manually by using the tag metaparameter in your resource declarations. That can allow you to provide for identifying custom collections of resources. And speaking of collections, you can use tags in the selection predicates of resource collectors, too.
The only way to do that is to have that node contain only the class you are wanting to have applied. In your site.pp you would have the following where the 'myhost.dns' is your fqdn. and $mycluster would be replaced by your cluster string.
node 'myhost.dns' {
class { 'keyconfig':
cluster => $mycluster,
}
}
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']".
I have encounter really weird behaviour which goes against what I have learned, tutorial says etc. So I would be glad if someone could explain why that is happening.
I have a role module which is made up of composition of profiles (role-profile pattern). My role consists:
class role::lab_prg_c2_dn inherits lab_prg_c2 {
class { 'profile::cluster_data_node':
namenode_fqdn => $role::lab_prg_c2::namenode_fqdn,
secondarynamenode_fqdn => $role::lab_prg_c2::secondarynamenode_fqdn,
}
->
class{'bigdatasolution':}
}
First class installs technology and second one installs our components and items which are build on top of technology. Hence the technology need to be installed first, thats the reason for "->" dependency. However this seems to me doesn't work correctly. As components from class 'bigdatasolution' are installed somewhere before the class profile::cluster_data_node finishes.
I tried to use require => Class['profile::cluster_data_node'] but that doesn't make any difference!
The content of class{'bigdatasolution':} :
class bigdatasolution {
$hdfs_default_conf = '/usr/local/hadoop.hdfs.conf'
$hbase_default_conf = '/usr/local/hadoop.hbase.conf'
include symlinks
include bdjar
}
Symlinks - create symlinks for the configuration installed in class profile::cluster_data_node and are not directly managed - it will be presented when actually specified package get installed.
bdjar - add our jar to a technology library so content is as follows:
class bigdatasolution::bdjar {
file { "/usr/lib/hadoop/lib/bigdata-properties.jar":
ensure => present,
mode => 0644,
group => 'root',
owner => 'root',
source => "puppet:///modules/bigdatasolution/bigdata-properties.jar"
}
}
I even tried to put require => "technologycalClass" here but that doesn't help either.
Can someone please help me understand what's wrong and how that should be solved properly?
I Using puppet 3 and ordering is specified explicetly - so no arbitrary ordering set by puppet should happen.
Thanks
If your 'profile::cluster_data_node' class 'includes' other classes/modules they will have no dependency ordering with the 'bigdatasolution' class.
I see you actually do include symlinks and bdjar. Basically every piece of ordering you want to have in puppet, you need to write explicitly.
Here you should replace the include statements with require, that way the class cluster_data_node will require the other two modules to complete before it says it has completed. Include is a pretty lose way of importing things in puppet and in my opinion is best to just avoid it and go with explicit require statements instead.
TL;DR: included modules have no transitive ordering; required modules do.