Puppet: Could not find resource 'File[/etc/auditbeat/auditbeat.yml]' in parameter 'require' - puppet

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.

Related

Tidy can’t use matches with recurse 0, false, or undef

I have the following Puppet resource.
tidy {
'beat_lock':
age => '8h',
path => '/var/lib/beat/',
alias => 'beat_lock',
matches => 'run.lock',
type => 'mtime'
}
I am getting an error stating the following:
Error: Failed to apply catalog: Parameter matches failed on Tidy[filebeat_lock]: Tidy can't use matches with recurse 0, false, or undef
The entity I want to cleanup is a file not a directory. So, why is the error showing up?
The entity I want to cleanup is a file not a directory. So, why is the error showing up?
You're telling Puppet that the entity you want to clean up is the directory /var/lib/beat. That's what the path parameter designates if you specify it, or what the the resource title designates if you don't explicitly specify the path parameter. At the same time, you have not provided a value for the recurse parameter, so the resource defaults to non-recursive, as if you had specified recurse => false. It doesn't make sense to use matches in this context, where you've already specified exactly which file is to be managed.
There is a variety of ways to spell it, but the simplest way to express what you seem actually to want would be this:
tidy { '/var/lib/beat/run.lock':
age => '8h',
type => 'mtime'
}
If you prefer to be able to refer to this resource elsewhere as Tidy['beat_lock'] then you might instead say
tidy { 'beat_lock':
path => '/var/lib/beat/run.lock',
age => '8h',
type => 'mtime'
}
I don't see much reason to introduce an alias, however, and you certainly don't need one that's the same as the resource title. I don't have any aliases declared anywhere in my own manifest set, and I don't recommend their use.

How do I apply only one file or two classes from a Puppet Master server?

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,
}
}

Can Hiera lookups be done in a module?

I have a service implemented in Java which depends on 3 property files. I have defined 'define' for each of the property file in a common properties module and consuming them from service specific module. The 'define' for one of the property file is shown below:
define properties::rabbitmq (
$property_file,
$service_name,
$rabbitmq_host,
$rabbitmq_username,
$rabbitmq_password,
$rabbitmq_port,
$rabbitmq_vhost) {
file { $property_file:
ensure => file,
content => template('config/rabbitmq.properties.erb'),
mode => '0644',
notify => Service[$service_name],
}
}
I am following roles and profile pattern in my puppet code and doing all hiera lookups in service specific profile. Now because of this whenever there is a change in property files, I need to make cascading changes to all of my puppet modules that consumes that property file. The changes are needed in profile (hiera lookup), module init.pp (addition/removal of parametes from constructor) and config.pp (parameter adjustment when invoking 'define' for a property file).
I feel that the above problem can be solved by incorporating hiera lookups in 'define' for a property file, like this:
define properties::rabbitmq ($property_file, $service_name,) {
$rabbitmq_host = hiera('rabbitmq_host')
$rabbitmq_username = hiera('rabbitmq_username')
$rabbitmq_password = hiera('rabbitmq_password')
$rabbitmq_port = hiera('rabbitmq_port')
$rabbitmq_vhost = hiera('rabbitmq_vhost')
file { $property_file:
ensure => file,
content => template('config/rabbitmq.properties.erb'),
mode => '0644',
notify => Service[$service_name],
}
}
But, above is a violation of roles and profile pattern. The above is doing hiera lookup in a module instead of doing it in profile. Now, the module has a tight dependency on hiera. It being an internal module (not meant for puppet forge), I guess, it should be OK to violate the guideline in favor of code maintainability.
I seek opinion from others on above.

Do puppet conditionals ensure order, or do I still need to add metaparameters

I have code similar to the following:
class someclass($ensure = installed)
{
if($ensure == installed)
{
$installValue = installed
file { "someprogram.msi":
ensure => file,
source => 'somewhere',
path => 'C:/puppet-files/someprogram.msi',
}
}
else
{
$installValue = absent
}
package{ "someprogram":
ensure => $installValue,
source => 'C:/puppet-files/someprogram.msi',
}
}
Does the if statement containing the file resource ensure that the file resource will get applied before the package resource? Or do I need to explicitly state this in the metaparameters? Also, I am assuming that the $installValue will always be set before the package is installed, is that correct?
Thank you,
Derongan
You should specify the ordering explicitly, however the variable will be initialised correctly.
The ordering of resources in Puppet 3 is deterministic, but essentially random as it's based on hashes of the resource titles. In Puppet 3.3, this behaviour can be changed to the manifest order (release notes), but I wouldn't recommend relying on this - certainly if you're sharing the module, there's no guarantee that others use the same setting.
Since the file resource may not exist (if ensure => absent), you can't specify the relationship on the package resource. Instead, add before => Package['someprogram'], to the file resource.

Trouble locating templates in Puppet

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).

Resources