ansible to pick & iterate the location name from the file sequencly - ansible-2.x

I have written a playbook to install our custom collectd and that's working , where i'm changing the configuration with lineinfile module now i have another situation where i have multiple site names like one i have in my playbook ie richmod as follows:
Prefix "collectd.dns.NA.richmond.physical.
i have multiple site name viz richmond, carry, london, boston hence looking forward to put them into a varible and call that variable to assign the value.
lets suppose when it run the playbook on first Server it should pick up "richmon" for second it should pick up carry, for third it should london and so on.. looking for ideas..
---
- name: Playbook to Install CollectD
#hosts: all[1]
hosts: all
remote_user: root
become: true
tasks:
- name: Downloading collectd
get_url:
url="http://my-dc/collectd-5.7.2.tar.gz"
dest="/opt/"
- name: Extracting collectd archive
unarchive:
src="/opt/collectd-5.7.2.tar.gz"
dest="/opt/"
remote_src=True
- name: Creating soft link to collectd Dir
file:
src: "/opt/collectd-5.7.2"
dest: "/opt/collectd"
state: link
owner: root
group: root
#############################################################################################
# Dont Disable the gather_facts at all as {{ ansible_hostname }} absolutlty depends on facts #
# ###########################################################################################
- name: Committing changes to collectd configuration....
lineinfile:
dest: "{{ item.dest }}"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
backrefs: yes
with_items:
- { dest: '/opt/collectd/etc/collectd.conf', regexp: '#Hostname "collectServer"', line: 'Hostname "{{ ansible_hostname }}"' }
- { dest: '/opt/collectd/etc/collectd.conf', regexp: '# Prefix "collectd.unix."', line: ' Prefix "collectd.dns.NA.richmond.physical."' }
- name: Copy the collectd Daemon to init ..
copy:
src: "/opt/collectd/startup/collectd"
dest: "/etc/init.d/"
remote_src: True
mode: 0755
owner: root
group: root
- name: starting collectd Service
service:
name: collectd
state: started
enabled: yes

Related

Is there any ansible module to change the existing server ip and reboot it

I have a playbook, which replace the IP and hostname. The playbook works fine till it reboots the machine, but unable to connect it back as now the IP of that server is changed to something else.
Is there any better way to handle this problem.
---
- hosts: test
remote_user: root
vars:
IP_TO_REPLACE: '192.168.1.15'
IP_TO_REPLACE_WITH: '192.168.1.16'
HOSTNAME_TO_REPLACE: 'devops-15'
HOSTNAME_TO_REPLACE_WITH: 'devops-16'
tasks:
- name: modifying the ifcfg-BR0 file
replace:
path: "{{ item.path }}"
regexp: "{{ item.regexp1 }}"
replace: "{{ item.replace }}"
backup: yes
with_items:
- { path: '/etc/sysconfig/network/ifcfg-br0', regexp1: "{{ IP_TO_REPLACE }}", replace: "{{ IP_TO_REPLACE_WITH }}" }
- { path: '/etc/hosts', regexp1: "{{ IP_TO_REPLACE }}", replace: "{{ IP_TO_REPLACE_WITH }}" }
- { path: '/etc/hosts', regexp1: "{{ HOSTNAME_TO_REPLACE }}", replace: "{{ HOSTNAME_TO_REPLACE_WITH }}" }
- { path: '/etc/hostname', regexp1: "{{ HOSTNAME_TO_REPLACE }}", replace: "{{ HOSTNAME_TO_REPLACE_WITH }}" }
register: task_result
- name: Reboot immediately the server to take latest changes
shell: "sleep 15 && reboot"
async: 1
poll: 0
when: task_result is changed
- name: Wait for the reboot to complete if there was a changed
wait_for:
port: 22
host: '{{ (ansible_ssh_host |default(ansible_host))|default(inventory_hostname) }}'
search_regex: OpenSSH
delay: 10
timeout: 90
when: task_result is changed
- name: Check the uptime of the server
shell: "uptime"
register: uptime_result
- debug: var=uptime_result
Actual Output
TASK [Reboot immediately the server to take latest changes] *****************************************************************************
fatal: [192.168.1.15]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Shared connection to 192.168.1.15 closed.\r\n", "unreachable": true}
Expected Output
It should connect to the new IP 192.168.1.16
My research lead me to the following solution
Inspire by the suggestion of "drenthe73" here:
https://www.reddit.com/r/ansible/comments/n6xfyv/change_current_ip_address_and_reboot_into_the_new/
playbook with 2 plays
---
# play 1
hosts:
- host_ip_initial
# ...
tasks:
- name: "change ip address"
# ...
- name: "reboot target"
ansible.builtin.shell: "reboot"
async: 1
poll: 0
# play2
gather_facts: no
hosts:
- host_ip_final
# ...
tasks:
- name: "Wait for the target to reboot before probing it is up and running"
ansible.builtin.wait_for:
timeout: 300
delegate_to: localhost
- name: "wait for boot up"
ansible.builtin.wait_for_connection:
connect_timeout: 5
sleep: 5
delay: 30
timeout: 600
You need to know the final IP address and creates in your inventory the proper homolog entries.
Ansible various way to restart target:
https://www.redhat.com/sysadmin/automate-reboot-ansible
I am a bit late, but it might help someone else...

Ansible - Issue with iterating through items in path

I'm quite new to Ansible and I can't seem to be able to iterate through the items in a path using "with_items".
Below is the sample code which is meant to go through some files in a path and apply the configuration to a Juniper router.
---
- name: Get Juniper Device Facts
hosts: "junos_devices"
gather_facts: false
connection: local
tasks:
- name: Update prefix-lists
junos_config:
src: prefix-lists/{{item}}
with_items: "/home/python/prefix-lists/*"
The error I'm getting is this:
failed: [192.168.216.66] (item=/home/python/prefix-lists/*) => {"changed": false, "failed": true, "item": "/home/python/prefix-lists/*", "msg": "path specified in src not found"}
Does anyone have any idea why I'm unable to do so?
Why with_items? Use with_fileglob.
From examples:
# copy each file over that matches the given pattern
- name: Copy each file over that matches the given pattern
copy:
src: "{{ item }}"
dest: "/etc/fooapp/"
owner: "root"
mode: 0600
with_fileglob:
- "/playbooks/files/fooapp/*"

In Ansible, how can I fetch file from multiple nodes and store this in one file centralized?

All what I need is in title, for example I want to know how I can do somethings like that :
---
- hosts: ansible-clients
tasks:
- name: Fetch source list from clients
fetch: src=/etc/apt/sources.list
dest=/tmp/allnodes.sourcelist
OR in simply way
echo remote#/etc/apt/sources.list >> local#/tmp/allnodes.sourcelist
I can create and run script in local but the only condition I have is to do all actions in one playbook.
You can use this play:
---
- hosts: ansible-clients
tasks:
- name: Fetch source list from clients
fetch:
src: /etc/apt/sources.list
flat: yes
dest: "/tmp/{{ inventory_hostname }}.sourcelist"
- name: Merge files
run_once: yes
delegate_to: localhost
shell: "cat /tmp/{{ item }}.sourcelist >> /tmp/allnodes.sourcelist"
with_items: "{{ groups['ansible-clients'] }}"
First task is used to fetch all files from remotes and store them in /tmp. inventory_hostname is used in filename to be sure it is unique.
Second task is run once on any host, and append all files (get list of hosts linked to group ansible-clients) in final file

Replace several words in matching files using Ansible

The project is to update wildcard certificate paths on many servers, each having a differently-named Vhost-*.conf file.
I would like to search for files that match V*.conf, then grep through them and replace the values for crt, key & ca as indicated below.
The closest answer I've found is this one but I couldn't get it to run as-is. And I think the replace module is better suited than lineinfile since I'd rather not re-write the whole line, and would like to replace any number of occurrences in the file.
After some changes this is the closest I've come, but I haven't figured out why my syntax is off:
---
- hosts: myhost5
become: yes
tasks:
- name: grab conf file names
shell: ls /etc/httpd/conf.d/V*.conf
register: vhost_files
- name: replace text
replace:
dest: '{{ item.0 }}'
regexp: '{{ item.1.regexp }}'
line: '{{ item.1.line}}'
backrefs: yes
backup: yes
with_nested:
- "{{vhost_files}}"
- "{{text_to_replace}}"
vars:
text_to_replace:
- { "regexp: 'mywildcard2014.crt', line: 'mywildcard.2016.crt'" }
- { "regexp: 'mywildcard2048_2014.key', line: 'mywildcard.2016.key'" }
- { "regexp: 'gd_bundle2014.crt', line: 'mywildcard.2016.ca-bundle'" }
handlers:
- name: restart apache
service: name=httpd state=restarted
The response I get is:
the field 'args' has an invalid value, which appears to include a
variable that is undefined. The error was: 'dict object' has no attribute 'regexp'
First of all, you need to remove unnecessary double quotes here:
- { regexp: 'mywildcard2014.crt', line: 'mywildcard.2016.crt' }
But there are number of other tiny bugs in your code.
Also keep in mind that using shell commands instead of modules is not an Ansible way.
Consider using find module instead of shell: ls.
---
- hosts: myhost5
become: yes
vars:
text_to_replace:
- { regexp: 'mywildcard2014.crt', line: 'mywildcard.2016.crt' }
- { regexp: 'mywildcard2048_2014.key', line: 'mywildcard.2016.key' }
- { regexp: 'gd_bundle2014.crt', line: 'mywildcard.2016.ca-bundle' }
tasks:
- name: grab conf file names
find:
pattern: V*.conf
path: /etc/httpd/conf.d/
register: vhost_files
- name: replace text
replace:
dest: '{{ item.0.path }}'
regexp: '{{ item.1.regexp }}'
replace: '{{ item.1.line}}'
backup: yes
with_nested:
- "{{vhost_files.files}}"
- "{{text_to_replace}}"
notify: restart apache
handlers:
- name: restart apache
service: name=httpd state=restarted

Ansible and nested variables in loops

I there a way in Ansible to access variables in variables in a loop? For instance, configuring debconf to install a MySQL/MariaDB server needs two instructions like so:
- name: Define maria root password
shell: echo mysql-server mysql-server/root_password password {{ mysqlRootPass }} | debconf-set-selections
- name: Define maria root password again
shell: echo mysql-server mysql-server/root_password_again password {{ mysqlRootPass }} | debconf-set-selections
But that would be way more compact if I could do that:
- name: Define maria root password
shell: {{ item }}
with_items:
- "{ echo mysql-server mysql-server/root_password password {{ mysqlRootPass }} | debconf-set-selections }"
- "{ echo mysql-server mysql-server/root_password_again password {{ mysqlRootPass }} | debconf-set-selections }"
Obviously, that doesn't work.
so is there a way to make it work? Is there a better way of doing it? Am I missing something?
The {{ }} notation in Ansible comes from Jinja2 templates, it essentially directs Ansible to replace this with the contents of that variable.
with_items introduces the special variable item, which is the particular item of the current loop.
Therefore, you instruct the command module to execute { echo..., namely whatever it is you have in with_items. You only need the command itself: echo....
Reference: Ansible docs: using variables and Jinja2
Here is my complete working MySQL role, that might help you.
vars/main.yml
mysql_root_pass: mypassword #MySQL Root Password
tasks/main.yml
---
- name: Install the MySQL packages
apt:
name: "{{ item }}"
state: installed
update_cache: yes
with_items:
- mysql-server-5.6
- mysql-client-5.6
- python-mysqldb
- libmysqlclient-dev
- name: Update MySQL root password for all root accounts
mysql_user:
name: root
host: "{{ item }}"
password: "{{ mysql_root_pass }}"
state: present
with_items:
- "{{ ansible_hostname }}"
- 127.0.0.1
- ::1
- localhost
- name: Copy the root credentials as .my.cnf file
template:
src: root.cnf.j2
dest: "~/.my.cnf"
mode: 0600
- name: Ensure Anonymous user(s) are not in the database
mysql_user:
name=''
host: "{{ item }}"
state: absent
with_items:
- localhost
- "{{ ansible_hostname }}"
- name: Remove the test database
mysql_db:
name: "test"
state: absent
notify:
- Restart MySQL
templates/root.cnf.j2
[client]
user=root
password={{ mysql_root_pass }}
handlers/main.yml
---
- name: Restart MySQL
service:
name: mysql
state: restarted
My site.yml look like this:
---
- hosts: all
become: yes
gather_facts: yes
roles:
- mysql
If you are just looking to update the password of already configured MySQL:
In vars/main.yml
mysql_old_root_pass: olmysqldpassword
mysql_root_pass: newmysqlpassword
In tasks/main.yml
- name: Set root user password
mysql_user:
name: root
host: "{{ item }}"
password: "{{ mysql_root_pass }}"
check_implicit_admin=yes
login_user: root
login_password: "{{ mysql_old_root_password }}"
state: present
with_items:
- "{{ ansible_hostname }}"
- 127.0.0.1
- ::1
- localhost
Hope this will help you. If you need any help, please check this github link.

Resources