How can I use Ansible lineinfile to remove all but a few specific lines? - linux

I'm attempting to ensure all but a few specific lines are removed from a file. I can get halfway there with the following task.
- name: ensure only the correct lines are present
lineinfile: dest=/path/to/file
regexp="pattern1|pattern2[0-9]*|pattern3[0-9]*"
state=present
backup=yes
Ultimately I want to ensure that pattern1, pattern2[0-9]*, and pattern3[0-9]* are the only lines that remain in this file. I've attempted to come up with a regex that negates this one and then specify state=absent but I've been unsuccessful so far.

If you want only specific lines in your file, why don't you just transfer that file with your desired lines to the remote server? You can use copy module to transfer that file as is or template module to dynamically substitute some variables inside or even assemble module to generate a file from some fragments(such as config).

Related

How to use fetch to add output to txt file, instead of overwriting the file?

I want to use fetch to gather a line of info from multiple nodes, and store them in the same txt file.
right now I have:
fetch:
src: /path/to/file.txt
dest: /ansible/path/to/file.txt
flat: yes
Instead of adding info to the existing txt file, it overrides the file and deletes the old info.
According to the official documentation of fetch module
Files that already exist at dest will be overwritten if they are different than the src.
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fetch_module.html
You maybe could use lineinfile or blockinfile module.
Fetch all the files that you want to append while renaming them with some combination of ansible_hostname in the name string. All files need to be added in the same folder, the destination name used will make the difference since you get the same file name from all sources it might be ending up overwriting the name. Use a changing variable like ansible_hostname or some sort of node identifier like IP address. Use this variable in building the file name for your fetched file
get a list of all the fetched files in a variable
Iterate thru that variable and then try lookup for each file
block={{lookup('file', 'sourceFile')}}
You can also iterate over all files in a folder, while appending to the end of the destination file. In your case, I believe blockinfile will be appropriate for this operation.

How to take backup of file without changing its time-stamp with Ansible playbook

How to take backup of file without changing its time-stamp with Ansible playbook? I tried backup=yes but the problem is like it changes the timestamp os the file.
Code:- dest={{item}} state=absent regexp='TLSv1' backup=yes with_items: ('{{certs_dir.stdout_lines}}')
I'm retracting my initial "It can't be done" response - it should be possible by using a series of plays, but it's not very pretty.
If you really need the backup file to keep the time-stamp, you might want to put in an official request on the developer mailing list.
Use the stat module on the initial file to retrieve the file timestamp
Register the backup file name in the return value backup_file from the file or copy module.
Use the command module to call the touch command to set the time of the backup_file to the original time. (The Ansible stat module does not adjust file timestamps.)

Read file contents to variable in grub.cfg file

Q1. Wanted to know how do you read the contents of a file to a variable at boot time in grub.cfg?
Q2. Could that be extended to read an .ini type file where you can read the values for various name entries?
[section]
nothisone=whatever
thisone=this is what I want to get
TIA!!
In order to do exactly what you are asking for, you would probably need to write your own GRUB module.
However, you should be able to achieve what you're after either using the configfile command, or with some clever application of the environment block feature.
Use "source" command to include another config file but unlike "configfile" which will change context.
Source is like an online macro while configfile likes a function - environment changes in configfile will not be preserved but source is expanding whatever in the source file and put in the main block, environment variable can be changed in this way.
https://www.gnu.org/software/grub/manual/grub/grub.html#source
https://www.gnu.org/software/grub/manual/grub/grub.html#configfile

In Puppet using Hiera, where do I put the files I want to have installed on nodes?

I know puppet modules always have a files directory and I know where it's supposed to be and I have used the source => syntax effectively from my own, handwritten modules but now I need to learn how to deploy files using Hiera.
I'm starting with the saz-sudo module and I've read the docs but I can't see anything about where to put the sudoers file; the one I want to distribute.
I'm not sure whether I need to set up a site-wide files dir in /etc/puppetlabs/puppet and then make subdirs in there for every module or what. And does Hiera know to look in /etc/puppetlabs/puppet/files/sudo if I say, source => "puppet:///files/etc/sudoers" ? Do I need to add a pathname in /etc/hiera.yaml? Add a line - files ?
Thanks for any clues.
My cursory view of the puppet module, given their example of using hiera:
sudo::configs:
'web':
'source' : 'puppet:///files/etc/sudoers.d/web'
'admins':
'content' : "%admins ALL=(ALL) NOPASSWD: ALL"
'priority' : 10
'joe':
'priority' : 60
'source' : 'puppet:///files/etc/sudoers.d/users/joe'
Suggest it assumes you have a "files" puppet module. So under you puppet modules section:
mkdir -p files/files/etc/sudoers.d/
Drop your files in there.
Explanation:
The url 'puppet:///files/etc/sudoers.d/users/joe' is broken down thus:
puppet: protocol
///: Three slashes indicate the source of the file is in a module.
files: name of the module
etc/sudoers.d/users/joe: full path to the file within the module's "files" directory.
You don't.
The idea of a module (Hiera backed or not) is to lift the need to manage the whole sudoers file from you. Instead, you can manage each single entry in the sudoers file.
I recommend reviewing the documentation carefully. You should definitely not have a file { "/etc/sudoers": } resource in your manifest.
Hiera doesn't have to do anything with Files.
Hiera is like a Variables Database, and servers you based on the hierarchy you have.
the files inside puppet, are usually accessed in methods like source => but also these files are using some basic structure.
In most cases when you call an file or template.
A template can serve your needs to automatically build an sudoers based on that.
There are also modules that supports modifying sudoers too.
It is up to you what to do.
In this case, saz stores the location of the file in hiera, but the real location can be a file inside your puppet (like a module file or something similar).
Which is completely unrelated.
Read about puppet file server
If you have questions, just ask.
V

Puppet how to run all manifests in directory

So I have a directory of puppet manifests that I want to run.
Is it possible to do something like:
include /etc/puppet/users/server522/*.pp
and have puppet run them?
I've tried
include users::server522::*
and several other variations
I always get an error about puppet being unable to find it.
Is there anyway to do this?
So my final solution to this was write a script that would take the directory listing and for each .pp file add an include into the server522.pp file. Quite annoying that puppet won't include an entire directory.
What are you trying to do here, and are you sure you're doing it the correct way? To wit, if you have multiple manifests corresponding to multiple servers, you need to define the nodes for each server. If OTOH you're trying to apply multiple manifests to a single node it's not clear why you would be doing that, instead of just using your defined classes. A little more information would be helpful here.
I do not see the point of each user having its own manifest. I would rather create script that would automatically build one manifest file, basing on data from some source, for instance from HEAD of git repository containing CSV file with current list of users.
If you realy want to use separate manifest file for every user you may consider having seprate module for every user:
manifests
default.pp <-- here comes default manifest
module_for_user_foo/
manifests/
init.pp <-- here comes your 'foo' user
module_for_user_bar/
manifests/
init.pp <-- here comes your 'bar' user
Now you may copy modules containing manifests.

Resources