Puppet: how to remove a directory and everything in it - puppet

I'm sure this is really simple, but I cannot work it out.
I want to delete the directory C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1. My attempts thus far have managed to remove everything inside the directory 1.0.0.1, but I can't work out how to remove the actual directory.
I did think about going up a level, but that would mean that when I copy across the new version of this module (2.2.5), on the next run, Puppet will delete it.
Here are my two attempts:
file resource
file { "${modules_path}/PowerShellGet/1.0.0.1" :
ensure => directory,
recurse => true,
purge => true,
force => true,
}
tidy resource
tidy { "${modules_path}/PowerShellGet/1.0.0.1" :
age => 0,
recurse => true,
rmdirs => true,
}
T.I.A

Try it like this:
file { "${modules_path}/PowerShellGet/1.0.0.1" :
ensure => absent,
recurse => true,
force => true,
}

Related

Puppet: loops for creating file and symlink simultaneously

I would like to parse array and create files and symlink in another directory.
I can create files in sites-available and would like to create a symlink in sites-enabled
Could you prompt me on how I can do it, please? Can I do at once?
$domainsnames.each |String $domain| {
file {"/etc/nginx/sites-available/${domain}.conf":
# ensure => link,
content => template('nginx_on_templates/virtualhost.conf.erb'),
# target => "/etc/nginx/sites-enabled/${domain}.conf",
mode => '0644',
owner => 'root',
group => 'root',
}
}
Thank in advance,
Rostyslav
You probably are managing both sites-available and sites-enabled, and you want to simulate what a2ensite enable <site-name> does, correct?
In that case, you have something like:
$domainsnames.each |String $domain| {
file {"/etc/nginx/sites-available/${domain}.conf":
ensure => file,
content => template('nginx_on_templates/virtualhost.conf.erb'),
mode => '0644',
owner => 'root',
group => 'root',
}
file {"/etc/nginx/sites-enabled/${domain}.conf":
ensure => link,
target => "/etc/nginx/sites-available/${domain}.conf",
}
}
I also recommend you taking a look at the puppetlabs/apache module, where you don't have to manage the .conf yourself, but you manage the configurations for your virtual host:
e.g.:
apache::vhost { 'user.example.com':
port => '80',
docroot => '/var/www/user',
docroot_owner => 'www-data',
docroot_group => 'www-data',
}

Puppet - how to use different file source

I created a configuration in Puppet for Nagios agent (NRPE). Now, I'm trying to set different file sources depending on the existence of dirs. First, I check if a specific directory exists and then set specific file content. My current config files look like:
class nagios_client::file_nagios-check-Linux-stats {
include nagios_client::check_location_lib-nagios
file { '/usr/lib/nagios/plugins/check_linux_stats.pl':
ensure => file,
owner => root,
group => root,
mode => 755,
content => template("nagios_client/check_linux_stats.pl.erb"),
require => Exec["check_usr-lib_exists"],
}
file { '/usr/lib64/nagios/plugins/check_linux_stats.pl':
ensure => file,
owner => root,
group => root,
mode => 755,
content => template("nagios_client/check_linux_stats.pl.erb"),
require => Exec["check_usr-lib64_exists"],
}
file { '/usr/lib32/nagios/plugins/check_linux_stats.pl':
ensure => file,
owner => root,
group => root,
mode => 755,
content => template("nagios_client/check_linux_stats.pl.erb"),
require => Exec["check_usr-lib32_exists"],
}
}
This works fine, but I have a problem with this:
class nagios_client::file_nrpe-cfg {
# include nagios_client::check_location_lib-nagios
file { '/etc/nagios/nrpe.cfg.def':
path => '/etc/nagios/nrpe.cfg',
ensure => file,
owner => root,
group => root,
mode => 644,
content => template("nagios_client/nrpe-cfg.erb"),
require => Exec["check_usr-lib_exists"],
}
file { '/etc/nagios/nrpe.cfg.32':
path => '/etc/nagios/nrpe.cfg',
ensure => file,
owner => root,
group => root,
mode => 644,
content => template("nagios_client/nrpe-cfg-32.erb"),
require => Exec["check_usr-lib32_exists"],
}
file { '/etc/nagios/nrpe.cfg.64':
path => '/etc/nagios/nrpe.cfg',
ensure => file,
owner => root,
group => root,
mode => 644,
content => template("nagios_client/nrpe-cfg-64.erb"),
require => Exec["check_usr-lib64_exists"],
}
}
It looks like require => Exec[...] is ignored.
My check definition:
class nagios_client::check_location_lib-nagios {
exec { 'check_usr-lib_exists':
command => '/bin/true',
onlyif => '/usr/bin/test -d /usr/lib/nagios/plugins',
}
exec { 'check_usr-lib32_exists':
command => '/bin/true',
onlyif => '/usr/bin/test -d /usr/lib32/nagios/plugins',
}
exec { 'check_usr-lib64_exists':
command => '/bin/true',
onlyif => '/usr/bin/test -d /usr/lib64/nagios/plugins',
}
}
I'm using Puppet 3.8.7. How to do it in the right way?
The problem with what you have is that you are using require, which only makes sure that the specified resource (in this case each exec) executes before the file resource. The behavior you want corresponds more closely to notify relationships (which create a refresh event), however, file resources do not care about refresh events. You can read more about refresh relationships here: https://puppet.com/docs/puppet/latest/lang_relationships.html#refreshing-and-notification.
There are 2 possible ways I can think of fixing this. The first one would be to use an exec statement to manage the file, instead of a file resource. This is definitely not optimal, since you lose all of the parameters from the file resource (I definitely do not recommend this approach, but you could).
The other way would be to create a custom ruby fact to check if the files exist. The fact would look something like this:
Facter.add('nagios_directories') do
confine kernel: 'Linux'
setcode do
paths_to_check = [
'/usr/lib/nagios/plugins',
'/usr/lib32/nagios/plugins',
'/usr/lib64/nagios/plugins',
]
paths_to_check.select { |d| File.directory?(d) }
end
end
This fact would check all the directories listed in the paths_to_check array, and return an array containing the directories that do exist. If none of the directories exist, it would return an empty array.
Once you have that fact set up, you can then rewrite your code like this:
class nagios_client::file_nrpe-cfg {
if (member($fact['nagios_directories'], '/usr/lib/nagios/plugins')) {
file { '/etc/nagios/nrpe.cfg.def':
path => '/etc/nagios/nrpe.cfg',
ensure => file,
owner => root,
group => root,
mode => 644,
content => template("nagios_client/nrpe-cfg.erb"),
}
}
if (member($fact['nagios_directories'], '/usr/lib32/nagios/plugins')) {
file { '/etc/nagios/nrpe.cfg.32':
path => '/etc/nagios/nrpe.cfg',
ensure => file,
owner => root,
group => root,
mode => 644,
content => template("nagios_client/nrpe-cfg-32.erb"),
}
}
if (member($fact['nagios_directories'], '/usr/lib64/nagios/plugins')) {
file { '/etc/nagios/nrpe.cfg.64':
path => '/etc/nagios/nrpe.cfg',
ensure => file,
owner => root,
group => root,
mode => 644,
content => template("nagios_client/nrpe-cfg-64.erb"),
}
}
}
Here is some additional documentation for custom facts: https://puppet.com/docs/facter/3.9/fact_overview.html.
Lastly, if you are using Puppet 6 (currently the latest release), you can write a custom Ruby function and make use of the new deferred type. This type allows you to execute functions on the agent during catalog run time (before this release, all Puppet functions where executed on the Puppet Master at compile time), which means you can use a function to check if a file exists. I have not had a chance to try this feature, but you can view the documentation here: https://puppet.com/docs/puppet/6.0/integrating_secrets_and_retrieving_agent-side_data.html.

Puppet : how to resolve "file_line" multi match patterns

I'm trying to change configuration file using puppet.
This is my test.txt file that i want to change :
[default]
#puppet=no
abc=123
[nova]
#puppet=no
I want to change "#puppet=no" to "puppet=yes" only on [default] tab.
This is my test.pp for two version :
file_line{"someline":
path => '/root/openstack-puppet/computenode/nova/test.txt',
match => '[default]\n#puppet',
line => 'puppet=ok'
}
This one failed to find match pattern, so it just add "puppet=ok" at the end of file.
file_line{"someline":
path => '/root/openstack-puppet/computenode/nova/test.txt',
match => '#puppet',
line => 'puppet=ok'
}
This one failed because of multi match pattern problem.
I tried Augeas also, but I can't find how to uncomment using Augeas.
Somebody please help me with this problem!!
=========================================================================
I run this code :
file_line { 'someline':
path => '/root/openstack-puppet/computenode/nova/test.txt',
after => '\[default\]',
multiple => 'false',
match => '#puppet',
line => 'puppet=ok',
}
But when I run with "puppet apply" it still makes same error :
Error: More than one line in file '/root/openstack-puppet/computenode/nova/test.txt' matches pattern '#puppet'
Error: /Stage[main]/Main/File_line[someline]/ensure: change from absent to present failed: More than one line in file '/root/openstack-puppet/computenode/nova/test.txt' matches pattern '#puppet'
I think that 'after' attribute cannot applied when 'match' attribute is defined.
When I erase 'match' attribute, it works, but it didn't replace original string('#puppet=no').
It just added new line after [default] like this :
[default]
puppet=ok
#puppet=no
abc=123
dedd=0
[nova]
#puppet=no
So the issues still remain, how can I erase(or replace) the string '#puppet=no'
only on [default] tab??
The after attribute will solve this problem for you. Taking your second resource and cleaning up some, we have:
file_line { 'someline':
path => '/root/openstack-puppet/computenode/nova/test.txt',
match => '#puppet',
line => 'puppet=ok'
after => '[default]',
multiple => false,
}
Notice I also added the multiple attribute to safeguard against changing more than just the line you want to change.
The reason your first resource would have issues is threefold. First, file_line requires that your line attribute have a successful regexp match against the match attribute, which is not true in your case. Second, putting [default] in the match attribute means that [default] would be removed from your file if the resource succeeded as you wrote it. Third, you need to escape [] in your regexp, so it would look like \[default\] if you wanted to go that route (and you do not for the first two reasons given).
The file looks like it fits with the ini file format so a better solution would be to use the inifile resource type https://forge.puppet.com/modules/puppetlabs/inifile
ini_setting { "sample setting":
ensure => present,
path => '/root/openstack-puppet/computenode/nova/test.txt',
section => 'default',
setting => 'puppet',
value => 'yes',
}
Hi you can try it.
include stdlib
file_line{"someline":
ensure => 'present',
after => 'default',
multiple => false,
path => '/root/openstack-puppet/computenode/nova/test.txt',
line => 'puppet=ok',
}

conditional within define in puppet

Running Puppet 3.8
I have two defines:
define desktop::vinstall () {
package { $title:
ensure => installed,
allow_virtual => true,
configfiles => keep,
}
}
and
define desktop::vinstallwseeds () {
package { $title:
ensure => installed,
allow_virtual => true,
configfiles => keep,
require => File["/var/cache/debconf/pkg-${title}.seeds"],
responsefile => "/var/cache/debconf/pkg-${title}.seeds",
}
file { "/var/cache/debconf/pkg-${title}.seeds":
source => "puppet:///modules/desktop/pkg-${title}.seeds",
ensure => present,
}
}
Would like to turn these into one define statement with an optional boolean argument, something like:
define desktop::vinstallopt ( $queryresponse = 'false', ) {
package { $title:
ensure => installed,
allow_virtual => true,
configfiles => keep,
if $queryresponse == 'true' {
require => File["/var/cache/debconf/pkg-${title}.seeds"],
responsefile => "/var/cache/debconf/pkg-${title}.seeds",
}
}
file { "/var/cache/debconf/pkg-${title}.seeds":
source => "puppet:///modules/desktop/pkg-${title}.seeds",
ensure => present,
}
}
and then instantiate it with statements like this one in init.pp:
#desktop::vinstallopt { 'gdebi': queryresponse => 'false', }
But doing so gives an error:
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Puppet::Parser::AST::Resource failed with argument error ArgumentError: Invalid resource type desktop::vinstallopt at /etc/puppet/modules/desktop/manifests/init.pp:40 on node machine.prvt.net
where line 40 has the syntax above. I'm a newbie with puppet, so my apologies if this turns out the be a simple syntax question. I've tried to find a way to make this work from the PuppetLabs documentation and from other puppet users, so far without luck.
You are trying to embed an if block inside a resource declaration. Alas, this is not possible. The block must be global or in a regular block (e.g., class body, define body, lambda body).
In this case, you want to "amend" the package resource, so to speak. I like to use the following construct for this purpose:
package { $title:
ensure => installed,
allow_virtual => true,
configfiles => keep,
}
if $queryresponse {
Package[$title] {
require => File["/var/cache/debconf/pkg-${title}.seeds"],
responsefile => "/var/cache/debconf/pkg-${title}.seeds",
}
}
Please note that this override syntax is only allowed in this scope because the require and responsefile attributes don't have any value assigned originally.

puppet chown/chmod against files under a directory in batch

In puppet, you can chown/chmod a single file by doing:
file {
'/var/log/mylog/test.log':
ensure => 'present',
mode => '0644',
owner => 'me';
}
Two questions on this:
ensure=>'present' is gonna make sure '/var/log/mylog/test.log' exists, if it doesn't it creates it. Is there any way I can make it do actions if file exists, if file doesn't exist, don't bother to create/delete it, just ignore it and carry on.
Let's say I have 3 files under /var/log/mylog/, I want to chown/chmod against them all in a batch instead of having 3 file resource sections in my puppet code. Can I do something like below(of coz, the code below doesn't exist, it's in my dream now ^_^ ):
files {
'/var/log/mylog/*.log':
ensure => 'present',
mode => '0644',
owner => 'me';
}
If you want to specify to take a given action if file exists, if file doesn't exist etc. you have no choice (to my knownledge) currently than to use the exec resource with creates + onlyif or unless directives.
You could use for instance (see reference doc)
exec { "touch /var/log/mylog/test.log":
path => "/usr/bin:/usr/sbin:/bin",
user => "${yourmodule::params::user}",
group => "${yourmodule::params::group}",
creates => "/var/log/mylog/test.log",
unless => "test -f /var/log/mylog/test.log"
}
file { '/var/log/mylog/test.log':
ensure => 'present',
mode => "${${yourmodule::params::mode}",
owner => "${yourmodule::params::user}",
group => "${yourmodule::params::group}",
require => Exec["touch /var/log/mylog/test.log"]
}
No. Again, you'll have to use an execresource.

Resources