How to create directory using ansible with directory names taken from a file - ansible

How to create a directory using ansible where directory names should be taken from a different file
I have tried using with_file command which didnt help much
-bash-4.2$ cat main.yml
---
- name: It is a test yml
file:
dest: "/tmp/destination/{{ item }}"
state: directory
with_file:
- "/tmp/stuff.yml"
-bash-4.2$ cat /tmp/stuff.yml
test
hello
world
The expected output is - 3 Folders to be created as below
/tmp/destination/test
/tmp/destination/hello
/tmp/destination/world
But the output what I received is - Only 1 Folder created as below
/tmp/destination/test?hello?world

Use with_lines
- name: It is a test yml
file:
dest: "/tmp/destination/{{ item }}"
state: directory
with_lines: cat /tmp/stuff.yml

Related

Get multiple file contents to one Ansible variable

On Ubuntu 18 server in directory /home/adminuser/keys are 5 files that contain key parts:
/home/adminuser/key/
|- unseal_key_0
|- unseal_key_1
|- unseal_key_2
|- unseal_key_3
|- unseal_key_4
File contents:
1bbeaafab5037a287bde3e5203c8b2cd205f4cc55b4fcffe7931658dc20d8cdcdf
bdf7a6ee4c493aca5b9cc2105077ec67738a0e8bf21936abfc5d1ff8080b628fcb
545c087d3d59d02556bdbf8690c8cc9faafec0e9766bb42de3a7884159356e91b8
053207b0683a8a2886129f7a1988601629a9e7e0d8ddbca02333ce08f1cc7b3887
2320f6275804341ebe5d39a623dd309f233e454b4453c692233ca86212a3d40b5f
Part of Ansible playbook (task):
- name: Reading file contents
command: cat {{item}}
register: unseal_keys
with_fileglob: "/home/adminuser/keys/*"
The error that I get:
"[WARNING]: Unable to find '/home/adminuser/keys' in expected paths (use -vvvvv to see paths)"
I have tried to:
change user that creates directory and files
change path to /home/adminuser/keys/ and /home/adminuser/keys
I expect all of the file contents (that is parts of a single key) to be merged into one string:
1bbeaafab5037a287bde3e5203c8b2cd205f4cc55b4fcffe7931658dc20d8cdcdfbdf7a6ee4c493aca5b9cc2105077ec67738a0e8bf21936abfc5d1ff8080b628fcb545c087d3d59d02556bdbf8690c8cc9faafec0e9766bb42de3a7884159356e91b8 053207b0683a8a2886129f7a1988601629a9e7e0d8ddbca02333ce08f1cc7b38872320f6275804341ebe5d39a623dd309f233e454b4453c692233ca86212a3d40b5f
Given the files below for testing
shell> tree /tmp/admin/
/tmp/admin/
└── key
├── key_0
├── key_1
└── key_2
1 directory, 3 files
shell> cat /tmp/admin/key/key_0
abc
shell> cat /tmp/admin/key/key_1
def
shell> cat /tmp/admin/key/key_2
ghi
Use the module assemble to: "assemble a configuration file from fragments."
Declare the path
key_all_path: /tmp/admin/key_all
and assemble the fragments
- assemble:
src: /tmp/admin/key
dest: "{{ key_all_path }}"
This will create the file /tmp/admin/key_all
shell> cat /tmp/admin/key_all
abc
def
ghi
Read the file and join the lines. Declare the variable
key_all: "{{ lookup('file', key_all_path).splitlines()|join('') }}"
gives
key_all: abcdefghi
Example of a complete playbook for testing
- hosts: localhost
vars:
key_all_path: /tmp/admin/key_all
key_all: "{{ lookup('file', key_all_path).splitlines()|join('') }}"
tasks:
- assemble:
src: /tmp/admin/key
dest: "{{ key_all_path }}"
- debug:
var: key_all
Thanks !
Problem was in paths and hosts where task had to be executed.
Problem is solved by locating and reading files localy and executing this task:
- name: Reading file contents
command: cat "{{item}}"
register: keys ----> all file contents to variable "keys"
with_fileglob: "~/keys/*" ----> this is path to directory all files are storedon my local machine
delegate_to: localhost ----> here I specify that this task will be executed on local machine
become: false ----> remove sudo so that password is not requested

Find the latest file in a path and fetch it to another server. Use the filename only

---
- name: Find the latest file
find:
paths: /tmp/data
file_type: file
age: -2m
age_stamp: mtime
register: files
- debug:
msg: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path if//files.files|count > 0 else "cannot find any file" }}'
- name: Copy file, if found
fetch:
src: '{{ (files.files | sort(attribute="mtime", reverse=true) | first).path }}'
dest: '/tmp'
when: files.files|count > 0
In the above code when the fetch module is running it's just copying the full path. I just need the file. Can someone assist with what src can be set so that it just copies the latest file which is found and not the entire path?
Q: "Copy the latest file which is found and not the entire path."
A: Set flat: true and end the dest path by the slash /. See the notes below. Quoting from flat:
If dest ends with '/', it will use the basename of the source file, similar to the copy module. This can be useful if working with a single host, or if retrieving files that are uniquely named per host.
For example, given the files
shell> tree data1
data1
├── file1
├── file2
└── file3
The playbook below will copy the latest file (but not older than 2 minutes) from the directory data1 to the directory /tmp/localhost/data1/
shell> cat playbook.yml
- hosts: localhost
tasks:
- name: find the latest file
find:
paths: data1
file_type: file
age: -2m
age_stamp: mtime
register: files
- name: Copy file if found
fetch:
src: "{{ (files.files|sort(attribute='mtime', reverse=true)|first).path }}"
dest: /tmp
when: files.files|count > 0
The result will be the file stored in /tmp/localhost/data1/file3
shell> ll /tmp/localhost/data1/file3
-rw-rw-r-- 1 admin admin 0 Mar 1 15:18 /tmp/localhost/data1/file3
If you want to copy the file only change the attributes dest and flat, e.g.
- name: Copy file if found
fetch:
src: "{{ (files.files|sort(attribute='mtime', reverse=true)|first).path }}"
dest: /tmp/
flat: true
when: files.files|count > 0
The result will be the file stored in /tmp/file3
shell> ll /tmp/file3
-rw-rw-r-- 1 admin admin 0 Mar 1 15:18 /tmp/file3
Notes
The module fetch is used for fetching files from remote machines and storing them locally.
By default, the fetched files are stored in a 'host-based directory'. For example, if the dest directory is /backup an src file named /etc/profile on host host.example.com, would be saved into /backup/host.example.com/etc/profile. The hostname is based on the inventory name. See dest
By default, the attribute flat is False

ansible-playbook gather information from a file

I want to read a file by ansible and find specific thing and store all of them in a file in my localhost
for example there is /tmp/test file in all host and I want to grep specific thing in this file and store all of them in my home.
What should I do?
There might be many ways to accomplish this. The choice of Ansible modules (or even tools) can vary.
One approach is (using only Ansible):
Slurp the remote file
Write new file with filtered content
Fetch the file to Control machine
Example:
- hosts: remote_host
tasks:
# Slurp the file
- name: Get contents of file
slurp:
src: /tmp/test
register: testfile
# Filter the contents to new file
- name: Save contents to a variable for looping
set_fact:
testfile_contents: "{{ testfile.content | b64decode }}"
- name: Write a filtered file
lineinfile:
path: /tmp/filtered_test
line: "{{ item }}"
create: yes
when: "'TEXT_YOU_WANT' in item"
with_items: "{{ testfile_contents.split('\n') }}"
# Fetch the file
- name: Fetch the filtered file
fetch:
src: /tmp/filtered_test
dest: /tmp/
This will fetch the file to /tmp/<ANSIBLE_HOSTNAME>/tmp/filtered_test.
You can use the Ansible fetch module to download files from the remote system to your local system. You can then do the processing locally, as shown in this Ansible cli example:
REMOTE=[YOUR_REMOTE_SERVER]; \
ansible -m fetch -a "src=/tmp/test dest=/tmp/ansiblefetch/" $REMOTE && \
grep "[WHAT_YOU_ARE_INTERESTED_IN]" /tmp/ansiblefetch/$REMOTE/tmp/test > /home/user/ansible_files/$REMOTE
This snippet runs the ad-hoc version of Ansible, calling the module fetch with the source folder (on the remote) and the destination folder (locally) as arguments. Fetch copies the file into a folder [SRC]/[REMOTE_NAME]/[DEST], from which we then grep what we are interested in, and output that in the /home/user/ansible_files/$REMOTE.

Ansible copy file using command syntax

The assignment is as follows:
Lets create a file touch afile.txt, prior to creating tasks
Create a playbook test.yml to
copy afile.txt from your control machine to host machine at /home/ubuntu/ location as afile_copy.txt and
debug the above task to display the returned value
Execute your playbook (test.yml) and observe the output
I did following
Created the afile_copy.txt using touch
created the playbook as follows:
- name: copy files
hosts: all
tasks:
- name: copy file
command: cp afile.txt /home/ubuntu/afile_copy.txt
register:output
- debug: var=output
When I run the playbook using the command
ansible-playbook -i myhosts test.yml
it fails with the error message
stderr: cp: cannot stat 'afile.txt' : no such file or directory
The afile.txt is present in directory /home/scrapbook/tutorial
You should use copy module instead of command module. command module executes on the remote node.
1)first execute the ad-hoc command for copy:
ansible all -i myhosts -m copy -a "src=afile.txt dest=/home/ubuntu/"
2) After execute the above command,execute this playbpook:
hosts: all
tasks:
stat: path=/home/ubuntu/afile_copy.txt
register: st
name: rename
command: mv afile.txt /home/ubuntu/afile_copy.txt
when: not st.stat.exists
register: output
debug: var=output
Copy module should be used instead of command module
- name: copy files
hosts: all
tasks:
- name: copy file
copy: src=afile.txt dest=/home/ubuntu/afile_copy.txt
register:output
- debug: var=output
---
- name: copy files
hosts: all
tasks:
- name: copy file
copy:
src: afile.txt
dest: /home/ubuntu/afile_copy.txt
register: output
- debug: var=output

Ansible how naming of file issues

I have ansible creating files from the inventory file based off their IPs.
- local_action: file dest=/file{{ groups['firewall'] }}.txt state=touch
When it creates the file however it names it
[u'10.12.89.12'].txt
Is there a way to get it to name it 10.13.89.12.txt?
Can you try this:
- local_action:
module: file
dest: /file/{{ item }}.txt
state: touch
with_items: groups['firewall']

Resources