Ansible looping items in file - ansible

I have a file(a_file.txt) like this:
22
23
8080
I need to loop each item in a_file.txt with my host and formatted to be host:22, host:23, host:8080...and so on, so I can use shell module in playbook like this:
---
- hosts: host1
tasks:
- name: Remote hostname
shell: hostname
register: hostname
- name: Read items from a_file.txt
shell: cat a_file.txt
register: item_output
- name: Run shell command
shell: someCommand {{hostname.stdout_line|nice_to_yaml}}:{{item}}
with_items: item_output.stdout_lines
However, my someCommand failed because I have:
{{hostname.stdout_line|nice_to_yaml}} = - hostname\n
{{<item in a_file.txt>}} = [u'\22, u'\23, u'\8080]

you have to use:
- name: Run shell command
shell: someCommand {{hostname.stdout_line|nice_to_yaml}}:{{item}}
with_items: "{{ item_output.stdout_lines }}"

Related

Unable to correctly use a variable in ansible

I have the following scenario:
The inventory file is laid out as below:
[my_host]
host
server
[host:children]
hostm
hosts
[hostm]
host01
[hosts]
host02
host03
The group_vars file(s) is as below:
host.yml
user: user01
ansible_python_interpreter: /usr/bin/python3
The host_vars file(s) is as below:
host01.yml
id: ABC
nr: 00
host02.yml
id: DEF
nr: 20
host03.yml
id: GHI
nr: 02
Now using the above, I'm trying to run a playbook as described below:
custom.yml
- hosts: "{{ v_host | default([]) }}"
remote_user: root
tasks:
- name: Run the shell script
become: true
become_user: "{{ user }}"
become_method: su
become_exe: "su -"
ansible.builtin.shell: cleanipc {{ item.nr }} remove
with_items:
- "{{ v_host }}"
register: shell_result
no_log: false
changed_when: false
- name: print message
ansible.builtin.debug:
var: shell_result.stdout_lines
To run the playbook, I use the below command:
>ansible-playbook -i /path-to-inventory-file/file custom.yml -e 'v_host=host'
I'm trying to get the playbook to run the shell command on all child nodes of 'host', i.e., 'host01', 'host02' and 'host03', with the value of the variable 'nr' automatically substituted for each host.
I tried changing the lookup of the variable using hostvars as below:
ansible.builtin.shell: cleanipc {{ hostvars[item]['nr'] }} remove
But this didn't work either. Thank you for any help or guidance you can provide.
Thank you!

ansible lineinfile replace a line begin containing a pattern with default ports in multiple files based on input array

---
-
gather_facts: true
hosts: abc,pqr,xyz
name: "playbook"
serial: 1
tasks:
-
block:
-
shell: "ls /etc/maria/" # could be n number of ports like 123, 456, 789
register: ports
-
lineinfile:
line: PORT={{ new_ports }}
path: "/etc/instance_{{ item }}/mariadb.conf"
regexp: '^PORT='
with_items: "{{ ports.stdout_lines }}"
new_ports: # length of this would be based on number of ports, should create an array based on array size of `ports`
- 8880
- 8881
- 8882
Say for example I've some 3 ports from ls /etc/maria/ 123456789 and 3 corresponding files /etc/instance_123/mariadb.conf,
/etc/instance_456/mariadb.conf,
/etc/instance_789/mariadb.conf.
could be n number of ports & files.
I would like to replace line starting with ^PORT= in /etc/instance_123/mariadb.conf to PORT=8880 and so on until the length of array ports.
Results getting with suggested code:
Before
/etc/instance_1234/mariadb.conf | grep port
port=1234
playbook
- hosts: abc
gather_facts: false
vars:
ansible_python_interpreter: /usr/bin/python3
serial: 1
tasks:
- shell: ls /etc/maria/
register: ports
- debug:
msg: "{{ ports.stdout_lines|length }}"
- lineinfile:
path: "/etc/instance_{{ item }}/mariadb.conf"
regexp: "^port=.*$"
line: "port={{ new_ports[ansible_loop.index0] }}"
loop: "{{ ports.stdout_lines }}"
loop_control:
extended: true
vars:
new_ports: "{{ range(8880, 8880 + ports.stdout_lines|length) }}"
After
/etc/instance_1234/mariadb.conf | grep port
port=x
For example, given the files
shell> ssh admin#test_11 ls /tmp/mongo
123
456
shell> ssh admin#test_12 ls /tmp/mongo
123
456
789
The playbook
- hosts: test_11,test_12
gather_facts: false
serial: 1
tasks:
- command: ls /tmp/mongo
register: ports
- lineinfile:
path: "/tmp/etc/instance_{{ item }}/mongodb.conf"
regexp: "^PORT=.*$"
line: "PORT={{ new_ports[ansible_loop.index0] }}"
create: true
loop: "{{ ports.stdout_lines }}"
loop_control:
extended: true
vars:
new_ports: "{{ range(8880, 8880 + ports.stdout_lines|length) }}"
creates, or updates the configuration files
shell> ssh admin#test_11 ls /tmp/etc/
instance_123
instance_456
shell> ssh admin#test_11 cat /tmp/etc/instance_123/mongodb.conf
PORT=8880
shell> ssh admin#test_11 cat /tmp/etc/instance_456/mongodb.conf
PORT=8881
shell> ssh admin#test_12 ls /tmp/etc/
instance_123
instance_456
instance_789
shell> ssh admin#test_12 cat /tmp/etc/instance_123/mongodb.conf
PORT=8880
shell> ssh admin#test_12 cat /tmp/etc/instance_456/mongodb.conf
PORT=8881
shell> ssh admin#test_12 cat /tmp/etc/instance_789/mongodb.conf
PORT=8882

ansible ERROR! conflicting action statements: hosts, command while running

- name: test
hosts: all
gather_facts: no
tasks:
#command 1
- name: ansible-test command 1
iosxr_command:
commands:
- show inventory
when: ansible_network_os == 'iosxr'
register: output
- debug:
var: output.stdout
- name: print command executed
hosts: 127.0.0.1
connection: local
command:
- echo sh inventory
register: output1
- debug:
var: output1.stdout
this is my playbook
ERROR! conflicting action statements: hosts, command
The error appears to be in '/root/container/playbook2.yaml': line 16, column 5, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: print command executed
^ here
I am encountering this error.
Please help me fix the issue.
Indents. You need to start a new play with a new set of hosts and a new task list.
- name: test
hosts: all
gather_facts: no
tasks:
#command 1
- name: ansible-test command 1
iosxr_command:
commands:
- show inventory
when: ansible_network_os == 'iosxr'
register: output
- debug:
var: output.stdout
- name: print command executed
hosts: 127.0.0.1
connection: local
gather_facts: no
tasks:
- command: echo sh inventory
register: output1
- debug:
var: output1.stdout

ansible overwrite variable depending on result

I am running several shell commands in an ansible playbook that may or may not modify a configuration file.
One of the items in the playbook is to restart the service. But I only want to do this if a variable is set.
I am planning on registering a result in each of the shell tasks, but I do not want to overwrite the variable if it is already set to 'restart_needed' or something like that.
The idea is the restart should be the last thing to go, and if any of the commands set the restart variable, it will go, and if none of them did, the service will not be restarted. Here is an example of what I have so far...
tasks:
- name: Make a backup copy of file
copy: src={{ file_path }} dest={{ file_path }}.{{ date }} remote_src=true owner=root group=root mode=644 backup=yes
- name: get list of items
shell: |
grep <file>
register: result
- name: output will be 'restart_needed'
shell: |
NUM=14"s"; if [ "${NUM}" != "s" ]; then sed -i "${NUM}/no/yes/g" {{ file_path }}; echo "restart_needed"; else echo "nothing_changed" ; fi
with_items: "{{ result.stdout_lines }}"
register: output
- name: output will be 'nothing_changed'
shell: |
NUM="s"; if [ "${NUM}" != "s" ]; then sed -i "${NUM}/no/yes/g" {{ file_path }}; echo "restart_needed"; else echo "nothing_changed" ;; fi
with_items: "{{ result.stdout_lines }}"
register: output
- name: Restart service
service: name=myservice enabled=yes state=restarted
In the above example, the variable output will be set to restart_needed after the first task but then will be changed to 'nothing_changed' in the second task.
I want to keep the variable at 'restart_needed' if it is already there and then kick off the restart service task only if the variable is set to restart_needed.
Thanks!
For triggering restarts, you have two options: the when statement or handlers.
When statement example:
tasks:
- name: check if string "foo" exists in somefile
shell: grep -q foo somefile
register: result
- name: restart service
service:
name: myservice
enabled: yes
state: restarted
when: result.rc == 0
Handlers example:
tasks:
- name: check if string "foo" exists in somefile
shell: grep -q foo somefile
register: result
changed_when: "result.rc == 0"
notify: restart service
handlers:
- name: restart service
service:
name: myservice
enabled: yes
state: restarted

Return Variable from Included Ansible Playbook

I have seen how to register variables within tasks in an ansible playbook and then use those variables elsewhere in the same playbook, but can you register a variable in an included playbook and then access those variables back in the original playbook?
Here is what I am trying to accomplish:
This is my main playbook:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
roles:
- some_role
sub-playbook.yml:
---
- hosts: localhost
tasks:
- name: Collect info from Jenkins Job
script: whatever.py --url "{{ job_url }}"
register: jenkins_artifacts
I'd like to be able to access the jenkins_artifacts results back in main_playbook if possible. I know you can access it from other hosts in the same playbook like this: "{{ hostvars['localhost']['jenkins_artifacts'].stdout_lines }}"
Is it the same idea for sharing across playbooks?
I'm confused what this question is about. Just use the variable name jenkins_artifacts:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
debug:
var: jenkins_artifacts
This might seem complicated but I love doing this in my Playbooks:
rc defines the name of the variable which contains the return value
ar gives the arguments to the include tasks
master.yml:
- name: verify_os
include_tasks: "verify_os/main.yml"
vars:
verify_os:
rc: "isos_present"
ar:
image: "{{ os.ar.to_os }}"
verify_os/main.yml:
---
- name: check image on device
ios_command:
commands:
- "sh bootflash: | inc {{ verify_os.ar.image }}"
register: image_check
- name: check if available
shell: "printf '{{ image_check.stdout_lines[0][0] }}\n' | grep {{ verify_os.ar.image }} | wc -l"
register: image_available
delegate_to: localhost
- set_fact: { "{{ verify_os.rc }}": "{{ true if image_available.stdout == '1' else false }}" }
...
I can now use the isos_present variable anywhere in the master.yml to access the returned value.

Resources