How to read line-by-line in a file on remote machine - ansible

first line: /u01/app/oracle/oradata/TEST/
second line: /u02/
How to read both lines in a same variable and by using same varible i want know the present working directory through shell commands in ansible

You can use command to read a file from disk
- name: Read a file into a variable
command: cat /path/to/your/file
register: my_variable
And then do something like below to loop over the lines in the file.
- debug: msg="line: {{ item }}"
loop: y_variable.stdout_lines

The task below creates the list of the lines from a file
- set_fact:
lines_list: "{{ lines_list|default([]) + [item] }}"
with_lines: cat /path/to/file
It's possible to create both a list
"lines_list": [
"/u01/app/oracle/oradata/TEST/",
"/u02/"
]
and a dictionary
"lines_dict": {
"0": "/u01/app/oracle/oradata/TEST/",
"1": "/u02/"
}
with the combine filter
- set_fact:
lines_dict: "{{ lines_dict|default({})|combine({idx: item}) }}"
with_lines: cat /path/to/file
loop_control:
index_var: idx
"Present working directory through shell commands in ansible" can be printed from the registered variable. For example
- command: echo $PWD
register: result
- debug:
var: result.stdout
(not tested)

Related

Error while accessing variables in vars file in a role

As a follow up to this question How to read a particular part of file in ansible. I am trying to do the same but by using roles. The variables are stored in vars files
Here is the vars/main.yml file in the role
add:
commands: []
sub:
commands: []
multiply:
commands: []
div:
commands: []
Here's the code in tasks/main.yml file
- name: Getting the Add Commands
set_fact:
add.commands: "{{add.commands + [ item ]}}"
with_lines: "cat {{ {{playbook_dir}}/testing/files/data.txt }}"
when: item is search('^add')
- debug:
var: add.commands
- name: Getting the Sub Commands
set_fact:
sub.commands: "{{sub.commands + [ item ]}}"
with_lines: "cat {{ {{playbook_dir}}/testing/files/data.txt }}"
when: item is search('^sub')
- debug:
var: sub.commands
- name: Getting the Multiply Commands
set_fact:
multiply.commands: "{{multiply.commands + [ item ]}}"
with_lines: "cat {{ {{playbook_dir}}/testing/files/data.txt }}"
when: item is search('^multiply')
- debug:
var: multiply.commands
- name: Getting the Div Commands
set_fact:
div.commands: "{{div.commands + [ item ]}}"
with_lines: "cat {{ {{playbook_dir}}/testing/files/data.txt }}"
when: item is search('^div')
- debug:
var: div.commands
Code to execute the role
testing.yml
- name: Main Program
hosts: localhost
roles:
- testing
I thought that I would get the add commands for add.commands and similarly for others but I am getting the following error
"msg": "The variable name 'add.commands' is not valid. Variables must start with a letter or underscore character, and contain only letters, numbers and underscores."
Can anyone tell me how to troubleshoot this error and why it happened in the first place.
This is as expected and the error clearly states that.
Also as per ansible,
Variable names should be letters, numbers, and underscores. Variables
should always start with a letter.
So . can't be part of the variable name.

Use awk with ansible to run command

I have a playbook below:
- hosts: localhost
vars:
folderpath:
folder1/des
folder2/sdf
tasks:
- name: Create a symlink
shell: "echo {{folderpath}} | awk -F'/' '{system(\"mkdir \" $1$2 );}'"
register: result
#- debug:
# msg: "{{ result.stdout }}"
with_items:
- " {{folderpath}} "
However when I run the playbook I get 2 folders made. The first one is :
1- folder1des (as expected)
2- folder2 (this should ideally be folder2sdf )
I have tried many combination and still it doesnt want to work. What do I need to have it work properly.
I do not have ansible environment at the moment. But following should work:
- hosts: localhost
tasks:
- name: Create a symlink
shell: "echo {{item}} | awk -F'/' '{system(\"mkdir \" $1$2 );}'"
register: result
#- debug:
# msg: "{{ result.stdout }}"
with_items:
- folder1/des
- folder2/sdf
Reference: Ansible Loops Example
Explanation:
You were adding a single list object to the with_items. so in your with_items it finds only one object (which is of type list) to iterate over. Hence it runs only once. So now what I have done is I have passed a list of items to with_items that way it can iterate over the multiple items present in with_items.
Hope this helps!
Maybe
- hosts: localhost
vars:
folderpath:
folder1/des
folder2/sdf
tasks:
- name: Create a symlink
file:
state : link
path : "{{ item | regex_replace('[0-9]/','_') }}"
src : "{{ item }}"
with_items: " {{ folderpath }} "
Nothing in your given code creates symlinks. Is that really what you meant to do?

Pass parameter from .sh file to .yml file?

I am new to Ansible as well as Ubuntu system also. I want to pass the multiple variables from .sh file to .yml. I have plan to store all input variables in an array then passing the variable one by one using for loop while calling the file distributed-setup.yml.
Currently, I am trying to pass a variable.For that,I am following the below steps.
While executing the First.sh file I am passing the a variables like First.sh Input.yaml
First.sh file is like this
echo $1
ansible-playbook distributed-setup.yml --extra-vars="v:$1" -${1:-v} | tee output.txt
Distributed-setup.yml
---
- name: Executing slaves
hosts: slave
gather_facts: no
vars:
v: "{{lookup('env','v') }}"
contents: "{{ lookup('file','/home/ubuntu/Ansible-setup/Distributed-Ubuntu-Setup/Input/Input.yaml') | from_yaml }}"
log: "{{ contents['log'][0] }}"
timeout: "{{ contents['ansible-timeout'][0] }}"
In the line, contents: I need to use variable 'v' instead of Input.yaml.
How to do this?
One of the easiest ways to do this is through the environment
someVar=value ansible-playbook ...
and then, inside your Ansible code, you can refer to ansible_env.someVar. You can also export the variable and not need to define it on the same line.
To make this a bit more concrete for your use case:
input_yaml=/home/ubuntu/Ansible-setup/Distributed-Ubuntu-Setup/Input/Input.yaml
export input_yaml
ansible-playbook distributed-setup.yml
...and in your Ansible file:
contents: "{{ lookup('file', ansible_env.input_yaml) | from_yaml }}"
This is how you could use your variable v within other ones:
---
- hosts: localhost
connection: local
gather_facts: no
vars:
v: "{{ lookup('env','v') }}"
b: "{{ lookup('file','/tmp/{{ v }}') | from_yaml }}"
tasks:
- name: set contents
set_fact:
contents: "{{ lookup('file','/tmp/{{ v }}') | from_yaml }}"
- name: debug
debug:
msg: "{{ b }} == {{ contents }}"
when: b == contents
v will get the value of the existing environment var v and then use it on var b later in a task just in case is created another variable named contents with the value of b in this case using set_fact
For testing do:
$ export v=foo
$ date > /tmp/foo
$ ansible-playbook test.yml
It will set v to foo then will create a file in /tmp/foo with the current date (output of the date command)

ansible read (more than one) values from a line in file

i am trying to read variables from a file into an array of something, but not into a pre defined variable.
The goal is a playbook, that searches for lines with item.0 and NOT item.1 and deletes them, later the playbook makes sure, that a line with item.0 item.1 is present, thats why i need this splitted.
For example i have a file with lines like this:
Parameter Value
Parameter Value
Parameter Value
to use this in a loop until EOF.
example part ot the playbook:
- name: lineinfile loop
lineinfile:
path: /myfile
regexp '^{{somethinglike item.0}}.(?!{{something like item.1}})'
state absent
...
Does anybody know a solution for the lookup and the loop?
Best regards
This should help you.
Input file
cat filein
Parameter1,Value1
Parameter2,Value2
Parameter3,Value3
Playbook:
---
- hosts: test
tasks:
- name: reg
shell: cat filein
register: myitems
- name: deb
debug: var=myitems.stdout_lines
- name: echo to file
shell: "echo {{ item.split(',')[1] }} - {{ item.split(',')[0] }} >> fileout"
with_items: "{{ myitems.stdout_lines }}"
Output file:
cat fileout
Value1 - Parameter1
Value2 - Parameter2
Value3 - Parameter3
This is not state of the art but should work.
The solutuion:
There is a ansible role in ansible galaxy, it provides exactly what i need:
https://github.com/mkouhei/ansible-role-includecsv

In Ansible, how do I export an environment variable in one task so it can be used by another task?

Say I have the following file
foo.txt
Hello world=1
Hello world=2
...
Hello world=N
I want to use Ansible to insert another Hello world line, like this
foo.txt
Hello world=1
Hello world=2
...
Hello world=N
Hello world=N+1
IOW, I don't know home many Hello world lines there are, I need to find out via script, and get the value of N.
In Ansible, say I have the following shell task
- name: Find the last Hello world in foo.txt, and get the value of N
shell: >
# Get last Hello world line in foo.txt. I want to export this as an
# environment variable
LAST_HW_LINE=`awk '/Hello world/ {aline=$0} END{print aline}' "foo.txt"`
# Get left side of equation
IFS='=' read -ra LS <<< "$LAST_HW_LINE"
# Get the value of N
NUM=${LS##*\.}
# Increment by 1. I want to export this as an environment variable
NUM=$((NUM+1))
I want to be able to subsequently do this
- name: Add the next Hello world line
lineinfile:
dest: foo.txt
insertafter: "{{ lookup('env', 'LAST_HW_LINE') }}"
line: "Hello world={{ lookup('env', 'NUM') }}"
Maybe there's a better way to do this than using environment variables?
Register Variables
- shell: /usr/bin/foo
register: foo_result
Registering stdout as ansible variables
- debug: msg="{{ hello.stdout }}"
- debug: msg="{{ hello.stderr }}"
Including task with variables:
tasks:
- include: wordpress.yml wp_user=timmy
Including role with variables
- hosts: webservers
roles:
- common
- { role: foo_app_instance, dir: '/opt/a', app_port: 5000 }
For your case:
- name: so question 39041208
hosts: '{{ target | default("all") }}'
tasks:
- name: Find the last Hello world in foo.txt, and get the value of N
# shell: awk '/Hello world/ {aline=$0} END{print aline}' "/home/ak/ansible/stackoverflow/q39041208.txt"
shell: awk '/Hello world/ {aline=$0} END{print NR}' "/home/ak/ansible/stackoverflow/q39041208.txt"
register: last_line
ignore_errors: true
- name: debug
debug: msg="last line {{ last_line.stdout }}"
- name: debug next number
debug: msg="next num {{ last_line.stdout | int + 1 }}"
- name: Add the next Hello world line
lineinfile:
dest: /home/ak/ansible/stackoverflow/q39041208.txt
insertafter: "{{ last_line.stdout }}"
line: "Hello world={{ last_line.stdout | int + 1 }}"

Resources