Reputation: 41
I am ansible beginner and I have a problem with ansible playbook that should gather info about system version from multiple servers.
First step was to gather info about server (if it uses Jboss or Tomcat and where it is) - I was able to do it and store it in list like this:
"server_list": [
{
"hostname": "tst-24.ph.koop.cz",
"path": "/srv/ais/test/knz-batch/eap",
"pid": "14660",
"type": "wildfly/jboss",
"version": "",
"version_cmd": "/srv/ais/test/knz-batch/eap/bin/standalone.sh --version"
},
{
"hostname": "tst-24.ph.koop.cz",
"path": "/srv/ais/test/knz-eap/eap",
"pid": "20153",
"type": "wildfly/jboss",
"version": "",
"version_cmd": "/srv/ais/test/knz-eap/eap/bin/standalone.sh --version"
},
{
"hostname": "tst-24.ph.koop.cz",
"path": "/srv/ais/skoleni/knz-ws-int/eap",
"pid": "24861",
"type": "wildfly/jboss",
"version": "",
"version_cmd": "/srv/ais/skoleni/knz-ws-int/eap/bin/standalone.sh --version"
},
{
"hostname": "tst-24.ph.koop.cz",
"path": "/srv/ais/skoleni/knz-ws/wildfly",
"pid": "25195",
"type": "wildfly/jboss",
"version": "",
"version_cmd": "/srv/ais/skoleni/knz-ws/wildfly/bin/standalone.sh --version"
},
{
"hostname": "tst-24.ph.koop.cz",
"path": "/srv/ais/skoleni/knz-ws/undertow",
"pid": "25667",
"type": "tomcat",
"version": "",
"version_cmd": "/srv/ais/skoleni/knz-ws/undertow/bin/version.sh --version"
},
{
"hostname": "tst-24.ph.koop.cz",
"path": "/srv/ais/skoleni/knz/wildfly",
"pid": "26446",
"type": "wildfly/jboss",
"version": "",
"version_cmd": "/srv/ais/skoleni/knz/wildfly/bin/standalone.sh --version"
}
]
Now I need to run other shell command (that will use version_cmd) to get that version (with use of GREP).
But I don't know how to write into list when looping through. And second problem is how to make more conditions (to use other regex for wildfly/jboss)
- name: Get server version
shell: "{{item.version_cmd}}| grep -Po {{ regexp_tomcat_version }}"
loop: "{{ server_list }}"
loop_control:
label: "Check version for {{ item.path }}"
when: item.type == "tomcat"
register: server_list.version
vars:
regexp_tomcat_version: 'Server version:\s*([^(\n)]*)'
ignore_errors: yes
Is this thing even possible in Ansible?
Upvotes: 2
Views: 91
Reputation: 68004
For example, given the list below for testing
server_list:
- hostname: srv1
path: /usr/bin/cc
type: prod
version_cmd: cc --version
version_parse: awk 'FNR == 1 {print $4}'
- hostname: srv1
path: /usr/local/bin/python
type: devel
version_cmd: python --version
version_parse: awk 'FNR == 1 {print $2}'
- hostname: srv2
path: /usr/bin/cc
type: prod
version_cmd: cc --version
version_parse: awk 'FNR == 1 {print $4}'
- hostname: srv2
path: /usr/local/bin/python
type: devel
version_cmd: python --version
version_parse: awk 'FNR == 1 {print $2}'
Create a dynamic group of hostnames in the first play and run it in the second play. In the second play, register the versions into the variable server_list_versions. Then iterate ansible_play_hosts and create the dictionary versions.
- name: Create group server_group
hosts: localhost
tasks:
- add_host:
name: "{{ item }}"
groups: server_group
server_list: "{{ server_list }}"
loop: "{{ server_list|map(attribute='hostname')|unique }}"
- name: Collect versions
hosts: server_group
gather_facts: false
tasks:
- shell: "{{ item.version_cmd }}|{{ item.version_parse }}"
loop: "{{ server_list|selectattr('hostname', 'eq', inventory_hostname) }}"
loop_control:
label: "Check version for {{ item.path }}"
# when: item.type == "devel"
register: server_list_versions
- set_fact:
versions: "{{ versions|d({})|
combine({item: hostvars[item].server_list_versions.results|
json_query('[].{path: item.path,
version: stdout,
stderr: stderr}')}) }}"
loop: "{{ ansible_play_hosts }}"
run_once: true
gives
versions:
srv1:
- path: /usr/bin/cc
stderr: ''
version: 11.0.1
- path: /usr/local/bin/python
stderr: ''
version: 3.8.12
srv2:
- path: /usr/bin/cc
stderr: ''
version: 11.0.1
- path: /usr/local/bin/python
stderr: '/bin/sh: python: not found'
version: ''
If you want to update the attribute version in server_list create a dictionary
- set_fact:
vers_dict: "{{ vers_dict|d({})|
combine({item: hostvars[item].server_list_versions.results|
json_query('[].{path: item.path,
version: stdout}')|
items2dict(key_name='path',
value_name='version')}) }}"
loop: "{{ ansible_play_hosts }}"
run_once: true
gives
vers_dict:
srv1:
/usr/bin/cc: 11.0.1
/usr/local/bin/python: 3.8.12
srv2:
/usr/bin/cc: 11.0.1
/usr/local/bin/python: ''
Then, use this dictionary to update the attribute version
- set_fact:
server_list_new: "{{ server_list_new|d([]) +
[item|combine({'version': version})] }}"
loop: "{{ server_list }}"
vars:
version: "{{ vers_dict[item.hostname][item.path] }}"
run_once: true
gives
server_list_new:
- hostname: srv1
path: /usr/bin/cc
type: prod
version: 11.0.1
version_cmd: cc --version
version_parse: awk 'FNR == 1 {print $4}'
- hostname: srv1
path: /usr/local/bin/python
type: devel
version: 3.8.12
version_cmd: python --version
version_parse: awk 'FNR == 1 {print $2}'
- hostname: srv2
path: /usr/bin/cc
type: prod
version: 11.0.1
version_cmd: cc --version
version_parse: awk 'FNR == 1 {print $4}'
- hostname: srv2
path: /usr/local/bin/python
type: devel
version: ''
version_cmd: python --version
version_parse: awk 'FNR == 1 {print $2}'
Upvotes: 2