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

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

Related

How to add content/string containing special character in file using ansible playbook?

Problem Statement:
I want to update the file /app/opt/MicroStrategy/MSIReg.reg_bkp with content "DSNotUseUnicodeForPT"=dword:00000001 under the line matching [HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Castor].
I have created the below playbook task to use three variables:
- name: Add the entry as per our requirement
ansible.builtin.lineinfile:
path: "{{ FILE_PATH_TO_CHANGE }}"
insertafter: "{{ STRING_TO_MATCH }}"
line: "{{ STRING_TO_ADD }}"
owner: root
group: root
mode: '0664'
state: present
The above variables I am passing as extra variables as below but the file is not getting updated. Can someone please help me with possible reasons?
FILE_PATH_TO_CHANGE=/app/opt/MicroStrategy/MSIReg.reg_bkp
STRING_TO_MATCH=[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Castor]
STRING_TO_ADD="DSNotUseUnicodeForPT"=dword:00000001
Command ran is: ansible-playbook edit_file.yml -u username -e "FILE_PATH_TO_CHANGE=/app/opt/MicroStrategy/MSIReg.reg_bkp STRING_TO_ADD="DSNotUseUnicodeForPT"=dword:00000001" STRING_TO_MATCH=[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Castor] --ask-pass
Update: Contain of /app/opt/MicroStrategy/MSIReg.reg_bkp
[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Castor]
"ClusterMembers"="hostnames"
"ClusterName"="abcd"
"DSHostName"=""
"DSMaxConn"=dword:000003e8
"DSNumAggregateThreads"=dword:00000004
"DSNumDecompressThreads"=dword:00000001
"DSNumDeserializeThreads"=dword:00000004
"DSNumReceiverThreads"=dword:00000001
"DSPort"=dword:00007621
"HomePath"="/app/opt/MicroStrategy/IntelligenceServer"
"IgnoreAllExceptions"=dword:00000000
"MaintenanceClusterMembers"="hostnames"
"MaintenanceModeEnabled"=dword:00000001
"ProcessAffinity"=""
"UseServerOSLocaleinFallback"="0"
[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Instances]^M
"DefaultInstanceName"="CastorServer"
[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Instances\CastorServer]
"AsymmetricClustering"=dword:00000001^M
"ClusteringInUse"=dword:00000001^M
"MetaDataDBEncryption"="UTF8"^M
"MetaDataDatabaseVersion"="-1"^M
"MetaDataODBCDriverLibraryName"="<MySQL_ODBC_DIR>/libmyodbc8w.so"^M
"MetaDataODBCDriverVersion"="3.52"
"NumberOfNodesInCluster"=dword:00000002
The challenge with passing [HKEY_LOCAL_MACHINE...] was that it was being treated like a List so I had to make this variable value to just HKEY_LOCAL_MACHINE without []. This works but I am not sure if you like this modification for your insertlineafter value.
Here is the playbook
---
- name: SO test
hosts: localhost
connection: local
vars:
FILE_PATH_TO_CHANGE: /home/user100/Documents/ansible/testso3.txt
STRING_TO_MATCH: HKEY_LOCAL_MACHINE
STRING_TO_ADD: '"DSNotUseUnicodeForPT"=dword:00000001"'
tasks:
- name: write in file
lineinfile:
path: "{{ FILE_PATH_TO_CHANGE }}"
insertafter: "^.*{{ STRING_TO_MATCH }}.*$"
line: "{{ STRING_TO_ADD }}"
mode: '0664'
state: present
and the file before the play
[user100#zini-1880 ansible]$ cat testso3.txt
[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Castor]
"ClusterMembers"="hostnames"
"ClusterName"="abcd"
"DSHostName"=""
"DSMaxConn"=dword:000003e8
"DSNumAggregateThreads"=dword:00000004
"DSNumDecompressThreads"=dword:00000001
"DSNumDeserializeThreads"=dword:00000004
"DSNumReceiverThreads"=dword:00000001
"DSPort"=dword:00007621
"HomePath"="/app/opt/MicroStrategy/IntelligenceServer"
"IgnoreAllExceptions"=dword:00000000
"MaintenanceClusterMembers"="hostnames"
"MaintenanceModeEnabled"=dword:00000001
"ProcessAffinity"=""
"UseServerOSLocaleinFallback"="0"
[user100#zini-1880 ansible]$
and after the play
[user100#zini-1880 ansible]$ cat testso3.txt
[HKEY_LOCAL_MACHINE\SOFTWARE\MicroStrategy\DSS Server\Castor]
"DSNotUseUnicodeForPT"=dword:00000001"
"ClusterMembers"="hostnames"
"ClusterName"="abcd"
"DSHostName"=""
"DSMaxConn"=dword:000003e8
"DSNumAggregateThreads"=dword:00000004
"DSNumDecompressThreads"=dword:00000001
"DSNumDeserializeThreads"=dword:00000004
"DSNumReceiverThreads"=dword:00000001
"DSPort"=dword:00007621
"HomePath"="/app/opt/MicroStrategy/IntelligenceServer"
"IgnoreAllExceptions"=dword:00000000
"MaintenanceClusterMembers"="hostnames"
"MaintenanceModeEnabled"=dword:00000001
"ProcessAffinity"=""
"UseServerOSLocaleinFallback"="0"
[user100#zini-1880 ansible]$
if you want to not have the vars in your play-book, you can remove them here and pass as command line arguments as you did in your original post.

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

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)

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)

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