how to remove all /etc/*.txt files with puppet - puppet

this puppet manifest will remove the file /etc/file.txt if it exists:
file { "/etc/file.txt":
ensure => absent,
}
how to tell puppet to remove all files /etc/*.txt?
according to the reference, it seems that puppet file does not allow wildcards.
https://puppet.com/docs/puppet/latest/types/file.html
ps: I am aware that I could execute a script from puppet, but I would prefer another more elegant way.

There's a built-in type for this called 'tidy', which allows you to specify a file glob pattern of files to remove.
Check it out at https://puppet.com/docs/puppet/latest/types/tidy.html.

You can use a glob pattern with tidy: https://puppet.com/docs/puppet/latest/types/tidy.html
So this would be your solution:
tidy { "delete-txt-files-in-etc":
path => "/etc",
recurse => true,
matches => [ '*.txt' ],
rmdirs => false,
}

Related

Manage multiple files permissions using puppet

How do I set file permission from list of file names from cat command?
For example, below command returns 3 file names:
$ cat /tmp/test | grep file
/etc/systemd/file_1.log
/etc/systemd/file_2.log
/etc/systemd/file_3.log
How do I use puppet to run the command, get the file names and then loop the 3 file names and set permission accordingly?
The files are resources and if you want to manage a resource you have to know it's there so dynamically created log files are not easy. If you know the file names already then you can use something like this and pass an array into the file resource.
file { ['/etc/systemd/file_1.log',
'/etc/systemd/file_1.log',
'/etc/systemd/file_1.log'] :
ensure => 'file',
mode => '0644',
owner => 'root',
group => 'root',
}
An other method might be to use an exec
exec { 'chmod 644 /etc/systemd/file_*.log':
path => ['/usr/bin', '/usr/sbin',],
}
But you really need something like an onlyif or unless or this is going to execute every 30 minutes and that breaks the idempotent rule we try and apply with Puppet code where things only change if they need correcting. So you're going to need a command line that'll test the permissions and return a boolean to the onlyif.
There are more details here https://puppet.com/docs/puppet/5.5/types/exec.html
A alternative (and the way I'd do it) would be to expose the contents of that file via an external fact which passes the list of files to Puppet to use in the catalog compilation. An external fact can be a bash script so I'd create a file called /etc/facter/facts.d/logfiles.sh, obviously I'd deploy this using Puppet.
#!/usr/bin/env bash
logfiles=($(grep file /tmp/test))
echo "logfiles=${logfiles[*]}"
Then in my Puppet code I'd have something like this;
$logfiles.each |String $logfile| {
file { $logfile :
ensure => 'file',
mode => '0644',
owner => 'root',
group => 'root',
}
}
So when the Puppet run happens the list of log files will be returned to Puppet via the facts and then each file listed is defined as a resource with the correct permissions.
How do I set file permission from list of file names from cat command?
There are two main alternatives, but I observe first that your example is of the output from grep, not cat, and that the cat in that example is superfluous. Nevertheless, those details don't change the big picture -- substantially the same approaches are applicable for data output by any command.
It would be more idiomatic to write a custom fact that captures the filenames (as of the time of each catalog request), and use that information to create the appropriate File resources.
Custom facts are not that hard, but the full details are more than would be appropriate for an SO answer. Supposing that you have a fact $facts['systemd_logs'] whose value is an array of the absolute filenames, you can compactly express the whole group of wanted File resources like so:
file { $facts['systemd_logs']:
mode => '0644',
}
(or whatever mode it is that you want).
It would be quicker (and dirtier) to use an Exec resource to run an appropriate command:
exec { 'ensure correct file permissions':
command => 'chmod 0644 $(/bin/grep file /tmp/test)',
onlyif => '/bin/grep -q file /tmp/test',
provider => 'shell',
}

How to program puppet to extract tarball only if its different

I want to use puppet to do this :
First puppet run, extract contents of tarball (which is stored on some server)
Subsequent puppet runs, extract contents of the tarball only if the tarball is different from the earlier run
Any suggestions on how to do this in Puppet ? I am struggling with how to use the "onlyif" clause in Puppet to achieve this.
You could do this in just one puppet run with something like:
$filename = 'somefile'
$path = '/somepath'
file { 'filename':
ensure => file,
source => 'file:/<SOMEPATH>/<SOMEFILE>',
path => "${path}/${filename}",
notify => Exec['extract tar'],
}
exec { 'extract tar':
refreshonly => true,
command => "tar --overwrite -xf ${filename}",
path => '/bin',
cwd => $path,
}
But I think using puppet/archive module would be a cleaner solution.

Chmod directory from other module by puppet

I'm using a 3rd part puppet module which I wish not to change (Tomcat). It creates a directory with mode=644, which I wish to change to 664 (recursively).
When I'm trying this, puppet is unhappy since this resource is already defined in the other module.
file { '/var/lib/tomcat' :
ensure => directory,
mode => 0664,
recurse => true,
}
Any ideas how can I go around this?
You can use the collector syntax to override some attributes for a resource that has already been declared.
File<| title == '/var/lib/tomcat' |> {
mode => '0664'
}
Use this sparingly. Incompatible overrides will still clash, and your manifests become difficult to debug.
The safest approach is to make the attribute a module parameter (by sending an appropriate patch upstream).
You should use the 'exec' resource type.
exec {"chmod -R 664 /var/lib/tomcat":
path => "/bin",
command => "chmod -R 664 .",
cwd => "/var/lib/tomcat"
}
It's the only workaround i found to avoid duplicate resource name
in bash you can use
cd /var/lib
chmod -R 664 Tomcat

Need some help in appending more than one line to a file in puppet

Using this manifest
file_line { 'sudo_rule':
path => '/etc/sudoers',
line => '%sudo ALL=(ALL) ALL',
}
Puppet adds a line, but I want more than one line to append to a file.
File_line only
Ensures that a given line is contained within a file. (according to the doc)
So you may add more lines to your puppet configuration file and it will work out of the box since puppet only ensures that they are there but doesn't add them continuously.
Maybe you tell us what your usecase is so that we can help you better. Another option would also be augeas to load config files into a tree like datastructure and edit the appropriate values in place.
Example usage:
augeas { "sshd_config":
context => "/files/etc/ssh/sshd_config",
changes => [
"set PermitRootLogin no",
],
}

Uncomment a line in Puppet

I'm getting into Puppet, and loving it, but am hitting my head against a wall with one small thing which I'm sure must be easier than I'm making it.
I wish to uncomment this line in the .bashrc of a user:
#force_color_prompt=yes
I've been using augeas for lots of things, but it seems as though that won't work with this.
I note that there's a file_line resource which I can use to ensure a line is present in a file, but I need the line to remain in the same place.
I don't wish to replace the .bashrc entirely with my own copy, despite seeing that this pattern is popular in Puppet, it just doesn't make sense to me as I don't want to maintain my own version between upgrades.
In sed I use this:
sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/g" ~/.bashrc
Any ideas?
You could just add your sed command to an exec with an unless option using grep. Something like this (untested):
exec { 'force_color_prompt':
command => 'sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/g" .bashrc'
cwd => '/home/user',
shell => true,
unless => 'grep -Fxq "force_color_prompt=yes" .bashrc',
}
Or use the file_line resource you mentioned (part of the Puppet Labs stdlib module I believe) to add the line uncommented and leave the commented line untouched.
In my experience, file_line will replace a line that matches the regex.
So to get force_color_prompt=yes vs. #force_color_prompt=yes you could:
file_line {
'color_prompt':
path => '/home/<youruser>/.bashrc',
match => 'force_color_prompt',
line => "force_color_prompt=yes",
}
Importantly, if the regex matches, the replace happens in place, ie. it will change the line, not the location of the line. If the regex does not match however, the line will be appended to the end of the file.
This experience is with Puppet 3.1.
Reference: https://forge.puppetlabs.com/puppetlabs/stdlib
The shellvar already can uncomment lines
shellvar { '.bashrc':
ensure => present,
target => "/home/${your_user}/.bashrc",
variable => 'force_color_prompt'
uncomment => true,
}
I perceive this much cleaner than using exec and calling sed.
While Augeas alone cannot do it, the shellvar provider from Augeasproviders will be able to do it, whenever this PR is merged.

Resources