I'm trying to get the pending installed windows update kb using ansible.
- name: Check for missing updates.
win_updates:
state: searched
category_names: "{{ win_updates_categories }}"
register: update_count
ignore_errors: yes
- debug: msg="{{ update_count.updates.kb }}"
but runs in error, could anyone help me, thank you !
Here is the output for register updatte
- debug:
var: update_count
"update_count": {
"changed": false,
"failed": false,
"filtered_updates": {},
"found_update_count": 1,
"installed_update_count": 0,
"reboot_required": false,
"updates": {
"67eab6a6-099b-42c5-86ce-63681f58ebd2": {
"categories": [
"Security Updates",
"Windows Server 2016"
],
"id": "67eab6a6-099b-42c5-86ce-63681f58ebd2",
"installed": false,
"kb": [
"4593226"
],
}
}
}
}
Here is the error if i only want show kb info
- debug:
var: update_count.updates.kb
"update_count.updates.kb": "VARIABLE IS NOT DEFINED!"
Please see below, I used the {{ item.value.id }} to get the ID value (last task) and saving them in an array if they are more than one, same way you should be able to retrieve the KBs. hopefully this explains
install critical updates only - reboot if nece
- name: install category critical updates only
win_updates:
category_names: ['CriticalUpdates']
server_selection: windows_update
state: installed
ignore_errors: yes
register: CriticalUpdateResults
- name: Postgres Column Values assigned
set_fact: UpdateCategory="{{ CriticalUpdateResults }}"
- name: CriticalUpdates Category assigned
set_fact: PatchCategory="CriticalUpdates"
- name: UpdatesArray assigned space
set_fact:
UpdatesArray: ""
- name: UpdatesArray assigned None if no update count
set_fact:
UpdatesArray: "None"
when: UpdateCategory.found_update_count == 0
- name: Updates Array assigned
set_fact:
UpdatesArray: "{{ UpdatesArray }} {{ **item.value.id** }}"
with_items:
- "{{ UpdateCategory.updates | dict2items }}"
when: UpdateCategory.found_update_count != 0
Related
Hej *,
I'm writing a playbook which should set some disk attributes in the Windows registry.
All disk attributes are stored under a specific vendor folder. There is a value under each disk folder that I want to change in the end.
- Disk&Ven_QEMU&Prod_QEMU_HARDDISK
|- 00000
|- 00001
- Disk&Ven_VMware&Prod_Virtual_disk
|- 00000
I'm able to determine the vendor folder as well as the disk folders under the root of HKLM:\SYSTEM\CurrentControlSet\Enum\SCSI:
- hosts: some_host
tasks:
- name: Get vendor folders
win_reg_stat:
path: HKLM:\SYSTEM\CurrentControlSet\Enum\SCSI
register: vendors
- name: Get disk folders
win_reg_stat:
path: "HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\SCSI\\{{ item }}"
with_items:
- "{{ vendors.sub_keys }}"
register: disks
- debug:
var: disks.results
The output looks like this:
ok: [some_host] => {
"disks.results": [
{
"ansible_loop_var": "item",
"changed": false,
"exists": true,
"failed": false,
"item": "CdRom&Ven_QEMU&Prod_QEMU_DVD-ROM",
"properties": {},
"sub_keys": [
"000001"
]
},
{
"ansible_loop_var": "item",
"changed": false,
"exists": true,
"failed": false,
"item": "Disk&Ven_QEMU&Prod_QEMU_HARDDISK",
"properties": {},
"sub_keys": [
"000000",
"000001"
]
},
{
"ansible_loop_var": "item",
"changed": false,
"exists": true,
"failed": false,
"item": "Disk&Ven_VMware&Prod_Virtual_disk",
"properties": {},
"sub_keys": [
"000000"
]
}
]
}
I'm a bit stuck right now. I'm trying to get a dictionary or list for iterating through all those disk folders. Something like that:
Disk&Ven_QEMU&Prod_QEMU_HARDDISK: 000000
Disk&Ven_QEMU&Prod_QEMU_HARDDISK: 000001
Disk&Ven_VMware&Prod_Virtual_disk: 000000
Is there a way to accomplish that?
Thanks and regards
Erik
For example
- set_fact:
my_list: "{{ my_list|default([]) + [{item.0.item:item.1}] }}"
with_subelements:
- "{{ disks.results }}"
- sub_keys
gives
my_list:
- CdRom&Ven_QEMU&Prod_QEMU_DVD-ROM: '000001'
- Disk&Ven_QEMU&Prod_QEMU_HARDDISK: '000000'
- Disk&Ven_QEMU&Prod_QEMU_HARDDISK: '000001'
- Disk&Ven_VMware&Prod_Virtual_disk: '000000'
It's not possible to create a dictionary because, in a dictionary, the keys must be unique.
I want to share my final solution with you. Thanks to Vladimir for the help.
- name: Get vendors
win_reg_stat:
path: HKLM:\SYSTEM\CurrentControlSet\Enum\SCSI
register: os_vendors
- name: Get vendors subfolders
win_reg_stat:
path: "HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\SCSI\\{{ item }}"
loop: "{{ os_vendors.sub_keys }}"
register: os_subfolders
- name: Build registry pathes with vendors and disks
set_fact:
os_regpath_dict: "{{ os_regpath_dict | default({}) | combine ({item.item : item.sub_keys })}}"
loop: "{{ os_subfolders.results }}"
- name: Get disk folders
win_reg_stat:
path: "HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\SCSI\\{{ item.0.key }}\\{{ item.1 }}\\Device Parameters\\Partmgr"
name: "Attributes"
loop: "{{ os_regpath_dict | dict2items | subelements('value') }}"
when: "'Disk' in item.0.key"
register: os_disks
- name: Set value of entry Attributes to 0
win_regedit:
path: "HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\SCSI\\{{ item.item.0.key }}\\{{ item.item.1 }}\\Device Parameters\\Partmgr"
name: Attributes
data: 0
type: dword
loop: "{{ os_disks.results }}"
when: item.value is defined
So I'm working on some audit points using Ansible for many of the servers we support. In most cases, I have had to use the shell modules to get the data I want and then write some files based on pass/fail cases. In a lot of situations, this has been the easier way to work with the output data. First, I realize this isn't necessarily Ansible's forte. I guess at some point it was pitched to the company that it could do this pretty easily, and I would agree - it's easier in many ways than just writing a custom python/BASH script to do the same. So - I do realize I'm bending the concept of Ansible a bit here for reporting, rather than configuration/state management. However; I like the tool and want to show the company we can get a lot of value from it.
While I could do this section easily using the shell module, I would like to learn Ansible a bit better. So thought I would post this question.
I'm using the Yum module to just get a repolist on the target hosts. But I've been running into confusion on just how to extract the list values nested in the output dictionary. I have done some checking on the types and as far as I can tell - the 'results' variable is a dictionary, with the output in in a list. What I want to do, is get the key/values from the list and then perform some other tasks based on that output. But for the life of me - I can't figure out how to do this!
Ideally - I would like to either use some 'when' module statements based on the output (When the repo ID is.. do this.. for example) or at least be able to store them in a variable to work with the data. So from this output, I just want to get the repoid and if it's enabled. How can I get these values from the nested list?
Simple Playbook:
---
- hosts: localhost
become: yes
tasks:
- name: Section 1.1 - Check Yum Repos
yum:
list: repos
register: section1_1
- name: Debug
debug:
var: section1_1
Here is my output from the debug task in this playbook:
TASK [Debug] ****************************************************************************************************************************************************
ok: [localhost] => {
"section1_1": {
"changed": false,
"failed": false,
"results": [
{
"repoid": "ansible",
"state": "enabled"
},
{
"repoid": "epel",
"state": "enabled"
},
{
"repoid": "ol7_UEKR6",
"state": "enabled"
},
{
"repoid": "ol7_latest",
"state": "enabled"
}
]
}
}
I suspect this might be easy for someone out there. I've been trying this and that's for quite a while now and finally got to the point where I thought I would just ask :)
As the output of registered in section1_1 is a list of dictionaries. We can loop through each item, to get the dictionary keys.
Example:
- name: Get the first repo's repoid and state
debug:
msg: "Repo ID: {{ results[0]['repoid'] }}, is {{ results[0]['state'] }}"
# This will show -- Repo ID: ansible, is enabled
Similarly we can access other elements with their number.
Or we can loop through each element of array:
- name: loop through array and conditionally do something
debug:
msg: "Repo ID is {{ item.repoid }}, so I am going to write a playbook."
when: item.repoid == 'ansible'
loop: "{{ results }}"
Q: "Get the key/values from the list."
A: There are more options. Given the data below
section1_1:
changed: false
failed: false
results:
- repoid: ansible
state: enabled
- repoid: epel
state: enabled
- repoid: ol7_UEKR6
state: enabled
- repoid: ol7_latest
state: enabled
- repoid: test
state: disabled
1a) Get the keys and values, and create a dictionary
_keys1: "{{ section1_1.results|map(attribute='repoid')|list }}"
_vals1: "{{ section1_1.results|map(attribute='state')|list }}"
repos1: "{{ dict(_keys1|zip(_vals1)) }}"
gives
_keys1: [ansible, epel, ol7_UEKR6, ol7_latest, test]
_vals1: [enabled, enabled, enabled, enabled, disabled]
repos1:
ansible: enabled
epel: enabled
ol7_UEKR6: enabled
ol7_latest: enabled
test: disabled
1b) The filter items2dict gives the same result
repos2: "{{ section1_1.results|
items2dict(key_name='repoid', value_name='state') }}"
1c) The filter json_query gives also the same result
repos3: "{{ dict(section1_1.results|
json_query('[].[repoid, state]')) }}"
Iterate the dictionary
- debug:
msg: "Repo {{ item.key }} is {{ item.value }}"
loop: "{{ repos1|dict2items }}"
gives (abridged)
msg: Repo ansible is enabled
msg: Repo epel is enabled
msg: Repo ol7_UEKR6 is enabled
msg: Repo ol7_latest is enabled
msg: Repo test is disabled
The next option is the conversion of the values to boolean
_vals4: "{{ section1_1.results|
json_query('[].state.contains(#, `enabled`)') }}"
repos4: "{{ dict(_keys1|zip(_vals4)) }}"
gives
_vals4: [true, true, true, true, false]
repos4:
ansible: true
epel: true
ol7_UEKR6: true
ol7_latest: true
test: false
Iterate the dictionary
- debug:
msg: "Repo {{ item.key }} is enabled: {{ item.value }}"
loop: "{{ repos4|dict2items }}"
gives (abridged)
msg: 'Repo ansible is enabled: True'
msg: 'Repo epel is enabled: True'
msg: 'Repo ol7_UEKR6 is enabled: True'
msg: 'Repo ol7_latest is enabled: True'
msg: 'Repo test is enabled: False'
3a) The list of the enabled repos can be easily selected
- debug:
msg: "Repo {{ item.key }} is enabled"
loop: "{{ repos4|dict2items|selectattr('value') }}"
gives (abridged)
msg: Repo ansible is enabled
msg: Repo epel is enabled
msg: Repo ol7_UEKR6 is enabled
msg: Repo ol7_latest is enabled
3b), or rejected
- debug:
msg: "Repo {{ item.key }} is disabled"
loop: "{{ repos4|dict2items|rejectattr('value') }}"
gives (abridged)
msg: Repo test is disabled
Example of a complete playbook for testing
- hosts: localhost
vars:
section1_1:
changed: false
failed: false
results:
- {repoid: ansible, state: enabled}
- {repoid: epel, state: enabled}
- {repoid: ol7_UEKR6, state: enabled}
- {repoid: ol7_latest, state: enabled}
- {repoid: test, state: disabled}
_keys1: "{{ section1_1.results|map(attribute='repoid')|list }}"
_vals1: "{{ section1_1.results|map(attribute='state')|list }}"
repos1: "{{ dict(_keys1|zip(_vals1)) }}"
repos2: "{{ section1_1.results|
items2dict(key_name='repoid', value_name='state') }}"
repos3: "{{ dict(section1_1.results|
json_query('[].[repoid, state]')) }}"
_vals4: "{{ section1_1.results|
json_query('[].state.contains(#, `enabled`)') }}"
repos4: "{{ dict(_keys1|zip(_vals4)) }}"
tasks:
- debug:
var: section1_1
- debug:
var: _keys1|to_yaml
- debug:
var: _vals1|to_yaml
- debug:
var: repos1
- debug:
var: repos2
- debug:
var: repos3
- debug:
msg: "Repo {{ item.key }} is {{ item.value }}"
loop: "{{ repos1|dict2items }}"
- debug:
var: _vals4|to_yaml
- debug:
var: repos4
- debug:
msg: "Repo {{ item.key }} is enabled: {{ item.value }}"
loop: "{{ repos4|dict2items }}"
- debug:
msg: "Repo {{ item.key }} is enabled"
loop: "{{ repos4|dict2items|selectattr('value') }}"
- debug:
msg: "Repo {{ item.key }} is disabled"
loop: "{{ repos4|dict2items|rejectattr('value') }}"
I am trying to use below ansible module to get vlan_id information.
- name: Get all portgroups in dvswitch vDS
vmware_dvs_portgroup_find:
hostname: "{{ vsphere_host }}"
username: "{{ vcenter_user }}"
password: "{{ vcenter_password }}"
dvswitch: 'test-123' --- dvswitch
validate_certs: no
with_items: "{{ dvswitch_list }}"
register: test
- debug: msg="{{ test }}"
I am getting out in below format.
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"dvs_portgroups": [
{
"dvswitch": "test-123",
"name": "DPortGroup2",
"pvlan": false,
"trunk": false,
"vlan_id": "220"
},
{
"dvswitch": "test-123",
"name": "PP1",
"pvlan": false,
"trunk": false,
"vlan_id": "465"
},
{
"dvswitch": "test-123",
"name": "PP2",
"pvlan": false,
"trunk": false,
"vlan_id": "685"
},
I am using below debug msg to get vlan_id but some how it does not work.
- debug: msg="{{ item.vlan_id }}"
with_items: "{{ test.results.dvs_portgroups }}"
ASK [role_vmware_datastore_size : debug] ********************************************************************************
fatal: [192.168.90.00]: FAILED! => {"msg": "'list object' has no attribute 'dvs_portgroups'"}
test.results is the list of results for each item of the with_items of the vmware_dvs_portgroup_find task. Therefore you have to iterate over this list before accessing a field of each element.
If you want to iterate over all the dvs_portgroups of all the results, you can do that:
- debug: msg="{{ item.vlan_id }}"
with_items: "{{ test.results | map(attribute='dvs_portgroups') | flatten | list }}"
map(attribute='dvs_portgroups') is transforming the list of results into a list of the dvs_portgroups of each result
| flatten is transforming the list of lists (the dvs_portgroups) into a list of all elements of each lists
| list is transforming an iterator back to a list that can be interpreted by with_items
above debug code is working fine. I am getting list of vlan_id. Just to add more details. I have 4 dvswich and getting vlan_id from all dvswtich. I want to make it format like each dvswitch name with there vlan_id.
test-123 -- dvswith name
220
221
222
test-456 -- dvswtich name
300
301
302
I am trying below way but its giving only one vlan_id from each dvswitch.
- name: Final VLAN Details
set_fact:
vlan_details: "{{ vlan_details | default([]) + [dict(name=item[0], size=item[1])] }}"
loop: "{{ dvswitch | zip(vlan_id) | list }}"
loop_control:
label: " "
I'm having an issue with using the package_facts module in Ansible. Basically, I just want to get the version of zabbix-agent installed as I need to do some stuff depending on which version is installed.
Now I got this in a playbook task:
- name: Gather Installed Packages Facts
package_facts:
manager: "auto"
tags:
- zabbix-check
- name: "Zabbix Found test result"
debug: var=ansible_facts.packages['zabbix-agent']
when: "'zabbix-agent' in ansible_facts.packages"
tags:
- zabbix-check
- name: "Zabbix Not-found test result"
debug:
msg: "Zabbix NOT found"
when: "'zabbix-agent' not in ansible_facts.packages"
tags:
- zabbix-check
Which spits out something like this:
ok: [vm3] => {
"ansible_facts.packages['zabbix-agent']": [
{
"arch": "x86_64",
"epoch": null,
"name": "zabbix-agent",
"release": "1.el7",
"source": "rpm",
"version": "4.0.10"
]
}
ok: [vm4] => {
"ansible_facts.packages['zabbix-agent']": [
{
"arch": "x86_64",
"epoch": null,
"name": "zabbix-agent",
"release": "1.el7",
"source": "rpm",
"version": "3.2.11"
}
]
}
I want to get the value of that "Version": "3.2.11" so that I can store that in a variable and use that later. I've seen that post using yum and doing some json query but that won't work for me.
For some reason (probably because of more versions of the same package might be installed), the value of the package dictionary is a list. A simple solution is to take the first element
- set_fact:
za_ver: "{{ ansible_facts.packages['zabbix-agent'][0].version }}"
when: "'zabbix-agent' in ansible_facts.packages"
To take into the account the possibility of more versions installed, use map filter
- set_fact:
za_ver: "{{ ansible_facts.packages['zabbix-agent']|
map(attribute='version')|
list }}"
when: "'zabbix-agent' in ansible_facts.packages"
Below is the equivalent with json_query filter
- set_fact:
za_ver: "{{ ansible_facts.packages['zabbix-agent']|
json_query('[].version') }}"
when: "'zabbix-agent' in ansible_facts.packages"
Is there a way to debug if the version matches a specific value?
- set_fact:
pkg_ver: "{{ ansible_facts.packages['{{ item.package_name }}'][0].version }}"
loop: "{{ lookup('dict', packagesToValidate) }}"
when: "'{{ item.package_name }}' in ansible_facts.packages" and inventory_hostname in item.hosts
being packagesToValidate a dictionary containing hosts, version and package name to validate?
I'm creating some ec2 instances from a specific image, then trying to get a list of disks attached to these instances.
The problem is when I try to loop over the registered variable from the create instance task, I got an error
I have tried the solution from this post but with no luck
ansible get aws ebs volume id which already exist
- name: create instance
ec2:
region: us-east-1
key_name: xxxxxxx
group: xxxxxx
instance_type: "{{ instance_type }}"
image: "{{ instance_ami }}"
wait: yes
wait_timeout: 500
instance_tags:
Name: "{{ item.name }}"
vpc_subnet_id: "{{ item.subnet }}"
register: ec2
loop: "{{ nodes }}"
- name: show attached volumes Ids
debug:
msg: "{{ item.block_device_mapping | map(attribute='volume_id') }}"
loop: "{{ ec2.results[0].instances }}"
while printing only msg: "{{ item.block_device_mapping }}" I get:
"msg": {
"/dev/sda1": {
"delete_on_termination": true,
"status": "attached",
"volume_id": "vol-xxxxxxx"
},
"/dev/xvdb": {
"delete_on_termination": false,
"status": "attached",
"volume_id": "vol-xxxxxx"
},
"/dev/xvdc": {
"delete_on_termination": false,
"status": "attached",
"volume_id": "vol-xxxxxx"
}
}
but when I use
msg: "{{ item.block_device_mapping | map(attribute='volume_id') }}"
I get this error:
"msg": "[AnsibleUndefined, AnsibleUndefined, AnsibleUndefined]"
The task below
- debug:
msg: "{{ item }}: {{ block_device_mapping[item].volume_id }}"
loop: "{{ block_device_mapping.keys() }}"
gives the {device: volume_id} tuples (grep msg):
"msg": "/dev/xvdb: vol-xxxxxx"
"msg": "/dev/xvdc: vol-xxxxxx"
"msg": "/dev/sda1: vol-xxxxxxx"
To iterate instances use json_query. The task below
- debug:
msg: "{{ item.block_device_mapping|json_query('*.volume_id') }}"
loop: "{{ ec2.results[0].instances }}"
gives:
"msg": [
"vol-xxxxxx",
"vol-xxxxxx",
"vol-xxxxxxx"
]
and the task below with zip
- debug:
msg: "{{ item.block_device_mapping.keys()|zip(
item.block_device_mapping|json_query('*.volume_id'))|list }}"
loop: "{{ ec2.results[0].instances }}"
gives the list of lists:
"msg": [
[
"/dev/xvdb",
"vol-xxxxxx"
],
[
"/dev/xvdc",
"vol-xxxxxx"
],
[
"/dev/sda1",
"vol-xxxxxxx"
]
]
and the task below with dict
- debug:
msg: "{{ dict (item.block_device_mapping.keys()|zip(
item.block_device_mapping|json_query('*.volume_id'))) }}"
loop: "{{ ec2.results[0].instances }}"
gives the tuples
"msg": {
"/dev/sda1": "vol-xxxxxxx",
"/dev/xvdb": "vol-xxxxxx",
"/dev/xvdc": "vol-xxxxxx"
}
The mistake:
So the main mistake you made was thinking of item.block_device_mapping as if it was the map you wanted to work with instead of a map within a map. That is, the keys that you have to first find would, according to the msg that you printed /dev/sda, /dev/xvdb and /dev/xvdc.
So first you'd have to make an array with the keys of the parent map. In the question you can see the necessary code to make Jinja get you the necessary strings:
# The necessary filter to get that array should be something along these lines
item['block_device_mapping'] | list() | join(', ')
You should register that to then loop over,giving you the keys you need to access those elements' attributes.