Ansible - get list of multiple attributes and do lineinfile - ansible

I've got multiple values under mounts, I want to have all 'mountpoints' of these attributes.
"mounts": {
"/dev/sdb": {
"fstype": "xfs",
"mountpoint": "/my/point1",
"opts": "defaults,_netdev",
"partition": "/dev/sdb1",
"state": "mounted"
},
"/dev/sdc": {
"fstype": "xfs",
"mountpoint": "/my/point2",
"opts": "defaults,_netdev",
"partition": "/dev/sdc1",
"state": "mounted"
},
"/dev/sdd": {
"fstype": "xfs",
"mountpoint": "/my/point3",
"opts": "defaults,_netdev",
"partition": "/dev/sdd1",
"state": "mounted"
How do I register the three mountpoints in memory for later use, so I get:
/my/point1, /my/point2, /my/point3
I want to place the values in /etc/updatedb.conf with lineinfile, so there should be no spacing.
My end result would look like; cat /etc/updatedb.conf
PRUNEPATHS = "/my/point1 /my/point2 /my/point3"
Currently, I use a template to copy pre-defined variables. But this is not dynamic enough.
I'm playing around how to get the right variables, but no success:
- debug: var=mount[all].mountpoints

To get a list:
- debug: msg="{{ mounts.values() | map(attribute='mountpoint') | list }}"
Or a string:
- debug: msg="{{ mounts.values() | map(attribute='mountpoint') | list | join(' ') }}"

EDIT:
You can get the join of the keys from mounts like this:
mounts: {{ mounts.keys()|join(', ') }}
(old answer that is not valid for this question)
as this describes, you can do
---
- hosts: all
tasks:
- set_fact: mounts={{ ansible_mounts | map(attribute='device')|join(',')}}
- debug: var=ansible_mounts
- debug: var=mounts
sample output
ap test.yml -i hosts -l server
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
ok: [server]
TASK [set_fact] ****************************************************************
ok: [server]
TASK [debug] *******************************************************************
ok: [server] => {
"ansible_mounts": [
{
"device": "/dev/sda1",
"fstype": "ext4",
"mount": "/",
"options": "rw,errors=remount-ro",
"size_available": 2890289152,
"size_total": 9376751616,
"uuid": "N/A"
},
{
"device": "/dev/sdb1",
"fstype": "ext4",
"mount": "/mnt/data1",
"options": "rw",
"size_available": 50684461056,
"size_total": 200674758656,
"uuid": "N/A"
}
]
}
TASK [debug] *******************************************************************
ok: [server] => {
"mounts": "/dev/sda1,/dev/sdb1"
}
PLAY RECAP *********************************************************************
server : ok=4 changed=0 unreachable=0 failed=0

Related

Ansible - Extracting a variable from a large JSON output

The gcp_sql_instance_info module does not seem to allow you to specify the name of the database you are trying to get info for. All it does is every detail of every database in that project.
What would be the best way to extract the "ipAddress" of a database based on it's name and register that value to a variable?
{
"resources": [
{
"kind": "sql#instance",
"state": "RUNNABLE",
"databaseVersion": "POSTGRES_13",
"settings": {
"authorizedGaeApplications": [],
"tier": "db-custom-1-3840",
"kind": "sql#settings",
"availabilityType": "ZONAL",
"pricingPlan": "PER_USE",
"replicationType": "SYNCHRONOUS",
"activationPolicy": "ALWAYS",
"ipConfiguration": {
"privateNetwork": "example-network",
"authorizedNetworks": [],
"ipv4Enabled": false
},
"locationPreference": {
"zone": "us-west1-b",
"kind": "sql#locationPreference"
},
"dataDiskType": "PD_SSD",
"maintenanceWindow": {
"kind": "sql#maintenanceWindow",
"hour": 0,
"day": 0
},
"backupConfiguration": {
"startTime": "02:00",
"kind": "sql#backupConfiguration",
"backupRetentionSettings": {
"retentionUnit": "COUNT",
"retainedBackups": 7
},
"enabled": false,
"replicationLogArchivingEnabled": false,
"pointInTimeRecoveryEnabled": false,
"transactionLogRetentionDays": 7
},
"settingsVersion": "3",
"storageAutoResizeLimit": "0",
"storageAutoResize": true,
"dataDiskSizeGb": "100"
},
"ipAddresses": [
{
"type": "PRIVATE",
"ipAddress": "10.10.10.1"
}
],
"instanceType": "CLOUD_SQL_INSTANCE",
"backendType": "SECOND_GEN",
"name": "database-1",
"region": "us-west1",
"gceZone": "us-west1-b",
"databaseInstalledVersion": "POSTGRES_13_7",
"createTime": "2022-07-22T20:20:32.274Z"
},
{
"kind": "sql#instance",
"state": "RUNNABLE",
"databaseVersion": "MYSQL_8_0",
"settings": {
"authorizedGaeApplications": [],
"tier": "db-n1-standard-1",
"kind": "sql#settings",
"availabilityType": "ZONAL",
"pricingPlan": "PER_USE",
"replicationType": "SYNCHRONOUS",
"activationPolicy": "ALWAYS",
"ipConfiguration": {
"privateNetwork": "example-network",
"authorizedNetworks": [],
"ipv4Enabled": false
},
"locationPreference": {
"zone": "us-west1-c",
"kind": "sql#locationPreference"
},
"dataDiskType": "PD_SSD",
"backupConfiguration": {
"startTime": "21:00",
"kind": "sql#backupConfiguration",
"backupRetentionSettings": {
"retentionUnit": "COUNT",
"retainedBackups": 7
},
"enabled": false,
"transactionLogRetentionDays": 7
},
"settingsVersion": "1",
"storageAutoResizeLimit": "0",
"storageAutoResize": true,
"dataDiskSizeGb": "10"
},
"ipAddresses": [
{
"type": "PRIVATE",
"ipAddress": "10.10.10.2"
}
],
"instanceType": "CLOUD_SQL_INSTANCE",
"backendType": "SECOND_GEN",
"name": "database-2",
"region": "us-west1",
"gceZone": "us-west1-c",
"databaseInstalledVersion": "MYSQL_8_0_26",
"createTime": "2022-07-27T19:27:59.235Z"
}
]
Q: "Extract the ipAddress of a database based on its name."
A: Crete a dictionary. For example, select the first item from the list ipAddresses
name_ip: "{{ dict(resources|json_query(name_ip_query)) }}"
name_ip_query: '[].[name, ipAddresses[0].ipAddress]'
give
name_ip:
database-1: 10.10.10.1
database-2: 10.10.10.2
Notes
Example of a complete playbook for testing
- hosts: localhost
vars_files:
- resources.yml
vars:
name_ip: "{{ dict(resources|json_query(name_ip_query)) }}"
name_ip_query: '[].[name, ipAddresses[0].ipAddress]'
name_ver: "{{ dict(resources|json_query(name_ver_query)) }}"
name_ver_query: '[].[name, databaseVersion]'
ip_of_db1: "{{ name_ip['database-1'] }}"
tasks:
- debug:
var: name_ip
- debug:
var: name_ver
- debug:
var: ip_of_db1
gives
TASK [debug] *********************************************************************************
ok: [localhost] =>
name_ip:
database-1: 10.10.10.1
database-2: 10.10.10.2
TASK [debug] *********************************************************************************
ok: [localhost] =>
name_ver:
database-1: POSTGRES_13
database-2: MYSQL_8_0
TASK [debug] *********************************************************************************
ok: [localhost] =>
ip_of_db1: 10.10.10.1
There might be more IP addresses. The variable ipAddresses is a list. An option would be to create a list of all IP addresses. For example,
name_ips: "{{ dict(resources|json_query(name_ips_query)) }}"
name_ips_query: '[].[name, ipAddresses[].ipAddress]'
give
name_ips:
database-1: [10.10.10.1]
database-2: [10.10.10.2]
This is a working playbook to achieve the desired output:
- hosts: localhost
vars:
db_instance_name: instance-1
tasks:
- name: get info on an instance
gcp_sql_instance_info:
project: project_id
auth_kind: serviceaccount
service_account_file: "/path/to/sa/example.json"
register: cloud_sql_resources
- set_fact:
query: "resources[?contains(name,'{{ db_instance_name }}')].ipAddresses[].ipAddress"
- set_fact:
ipAddress: "{{ cloud_sql_resources | to_json | from_json | json_query(query) }}"
- debug:
msg: "{{ ipAddress }}"
You can run your playbook like this: ansible-playbook -v main.yaml --extra-vars "db_instance_name=instance-1", that would print:
TASK [debug] ********************************************************************************************************************
ok: [localhost] => {
"msg": [
"35.224.46.127"
]
}

Touching a file on each mount point declared in `ansible_mounts`

I want to get info about mount points so that I can touch a file on them.
I can get mount points through item.mount but I want to store those mount points inside a variable so I can use it to form a path like {{mountpoint}}/test.txt.
But I don't know how to store that info to variable from the result of my debug task. And even if I get those mount points, I don't know how to create a file inside each mount point directories.
Should I use a loop again for that?
This is the playbook I have so far:
---
- hosts: all
gather_facts: false
tasks:
- setup:
filter: ansible_mounts
- debug:
var: item.mount
loop: "{{ ansible_mounts }}"
register: result
Which gives
TASK [setup] ***********************************************************************************************************
ok: [ambertest]
TASK [debug] ***********************************************************************************************************
ok: [ambertest] => (item={u'block_used': 258025, u'uuid': u'55555-c55c-55-555-0555a', u'size_total': 55584, u'block_total': 13104379, u'mount': u'/', u'block_available': 12846354, u'size_available': 5554, u'fstype': u'xfs', u'inode_total': 25524, u'inode_available': 558, u'device': u'/dev/vda1', u'inode_used': 30796, u'block_size': 4096, u'options': u'rw,seclabel,relatime,attr2,inode64,noquota'}) => {
"item": {
"block_available": 5554,
"block_size": 4096,
"block_total": 13559,
"block_used": 2555,
"device": "/dev/vda1",
"fstype": "xfs",
"inode_available": 2558,
"inode_total": 255824,
"inode_used": 355,
"mount": "/",
"options": "rw,seclabel,relatime,attr2,inode64,noquota",
"size_available": 5554,
"size_total": 5554,
"uuid": "55555"
},
"item.mount": "/"
}
ok: [ambertest] => (item={u'block_used': 672774, u'uuid': u'55dc9f5589e', u'size_total': 55, u'block_total': 155558, u'mount': u'/amber', u'block_available': 554, u'size_available': 49954627584, u'fstype': u'ext4', u'inode_total': 355, u'inode_available': 559, u'device': u'/dev/vdb', u'inode_used': 11, u'block_size': 4096, u'options': u'rw,seclabel,relatime,data=ordered'}) => {
"item": {
"block_available": 1554,
"block_size": 4556,
"block_total": 558,
"block_used": 6554,
"device": "/dev/vdb",
"fstype": "ext4",
"inode_available": 559,
"inode_total": 550,
"inode_used": 11,
"mount": "/amber",
"options": "rw,seclabel,relatime,data=ordered",
"size_available": 45584,
"size_total": 55,
"uuid": "5555"
},
"item.mount": "/amber"
}
PLAY RECAP *************************************************************************************************************
ambertest : ok=2 changed=0 unreachable=0 failed=0
The following is really far from optimized and bullet proofed but will at least give you an idea of how to start. Basically, you don't need to store your mount points inside a variable since the ansible_mounts variable already has them (as brilliantly demonstrated in your question)
---
- hosts: all
tasks:
- name: touch a test.txt file on each existing mountpoint
file:
path: "{{ item.mount }}/test.txt"
state: touch
loop: "{{ ansible_mounts }}"

Ansible - filter list based on other list

Can you please kindly suggest how can I filter one list based on other?
I.e. I have this list (List1)
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1001"
},
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1002"
},
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1020"
}
Also I have the list of versions (List2)
[
"1.2.0.1001"
"1.2.0.1020"
]
I would like the resulting list produced from List1, with all entries where version is in List2
So, in the example final list should be
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1001"
},
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1020"
}
I've already tried different options, but i do not know how to do it yet.
Any help will be extremely helpful!
What you are looking to achieve is a good candidate for the use of the conditional when statement.
And in this case, you can construct a new list with the help of the set_fact module, where the when will test that the current item we are looping on have a version that is contained in your desired list of versions:
- set_fact:
results: "{{ (results|default([])) + [item] }}"
with_items: "{{ applications }}"
when: item.version in versions
So, for a full working example, given the playbook:
- hosts: local
vars:
applications:
- AppName: "My Application"
environment: "DEV"
key: "myapp"
location: "DEV"
status: ""
version: "1.2.0.1001"
- AppName: "My Application"
environment: "DEV"
key: "myapp"
location: "DEV"
status: ""
version: "1.2.0.1002"
- AppName: "My Application"
environment: "DEV"
key: "myapp"
location: "DEV"
status: ""
version: "1.2.0.1020"
versions:
- 1.2.0.1001
- 1.2.0.1020
tasks:
- debug:
msg: "{{ applications }}"
- debug:
msg: "{{ versions }}"
- name: Constructing the resulting list
set_fact:
results: "{{ (results|default([])) + [item] }}"
with_items: "{{ applications }}"
when: item.version in versions
- debug:
msg: "{{ results }}"
The play will look like this
~ # ansible-playbook play.yml -i inventory.yml
PLAY [local] *******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [local]
TASK [debug] *******************************************************************
ok: [local] => {
"msg": [
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1001"
},
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1002"
},
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1020"
}
]
}
TASK [debug] *******************************************************************
ok: [local] => {
"msg": [
"1.2.0.1001",
"1.2.0.1020"
]
}
TASK [Constructing the resulting list] *****************************************
ok: [local] => (item={'AppName': 'My Application', 'environment': 'DEV', 'key': 'myapp', 'location': 'DEV', 'status': '', 'version': '1.2.0.1001'})
skipping: [local] => (item={'AppName': 'My Application', 'environment': 'DEV', 'key': 'myapp', 'location': 'DEV', 'status': '', 'version': '1.2.0.1002'})
ok: [local] => (item={'AppName': 'My Application', 'environment': 'DEV', 'key': 'myapp', 'location': 'DEV', 'status': '', 'version': '1.2.0.1020'})
TASK [debug] *******************************************************************
ok: [local] => {
"msg": [
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1001"
},
{
"AppName": "My Application",
"environment": "DEV",
"key": "myapp",
"location": "DEV",
"status": "",
"version": "1.2.0.1020"
}
]
}
PLAY RECAP *********************************************************************
local : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ansible: Trying to parse out Loopback0 IP Address

I am trying to store the IP address of my loopback0 as variable. I can call the ipv4 information, but it doesn't let me call the address information. [Scrubbed Info for Privacy]
Code:
- name: Configure IPSLA on Americas Router
gather_facts: false
hosts: IP_SLA
connection: local
serial: 1
tasks:
- name: Gather Switch Info
ios_facts:
- name: Debug
debug:
var: ansible_facts["net_interfaces"]["Loopback0"]["ipv4"]
...
Output:
PLAY [Configure IPSLA on Americas Router] ***************************************************************************************************************************************************************************************************
TASK [Gather Switch Info] *******************************************************************************************************************************************************************************************************************
ok: [host] => {"ansible_facts": {"ansible_net_interfaces": {"Loopback0": {"bandwidth": 8000000, "description": null, "duplex": null, "ipv4": [{"address": "10.x.x.x", "subnet": "32"}], "lineprotocol": "up ", "macaddress": null, "mediatype": null, "mtu": 1514, "operstatus": "up", "type": null}
TASK [Debug] ********************************************************************************************************************************************************************************************************************************
ok: [host] => {
"ansible_facts[\"net_interfaces\"][\"Loopback0\"][\"ipv4\"]": [
{
"address": "10.x.x.x",
"subnet": "32"
}
]
}
But when I try and call the address:
- name: Debug
debug:
var: ansible_facts["net_interfaces"]["Loopback0"]["ipv4"]["address"]
I end up with this error:
TASK [Debug] ****************************************************************************************************************************************
ok: [host] => {
"ansible_facts[\"net_interfaces\"][\"Loopback0\"][\"ipv4\"][\"address\"]": "VARIABLE IS NOT DEFINED!: 'list object' has no attribute 'address'"
How do I get the address stored as a variable so I can use it in future tasks?
The square brackets in:
ok: [host] => {
"ansible_facts[\"net_interfaces\"][\"Loopback0\"][\"ipv4\"]": [
{
"address": "10.x.x.x",
"subnet": "32"
}
]
}
Indicate this ["net_interfaces"]["Loopback0"]["ipv4"] is an array with a single element.
Use [0] to indicate the first element of the array, as demonstrated by the following code:
ansible_facts["net_interfaces"]["Loopback0"]["ipv4"][0]["address"]

how to get ec2 instances public dns name by ansible playbook

I am playing with ansible to automate ec2 instances. I created ec2 instance and then m trying to get its public dns name via ec2_remote_facts module. but it is giving variable not defined in output.
playbook:
- hosts: localhost
connection: local
tasks:
- name: ec2 instance facts
ec2_remote_facts:
region: ap-southeast-2
filters:
instance-state-name: running
register: ec2
- debug: var=ec2.instances.public_name
Output:PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [create ec2 instance] *****************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"ec2.instances.public_name": "VARIABLE IS NOT DEFINED!"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
Output for ec2.instances.
ok: [localhost] => {
"ec2.instances": [
{
"ami_launch_index": "0",
"architecture": "x86_64",
"client_token": "",
"ebs_optimized": false,
"groups": [
{
"id": "sg-6c016a08",
"name": "default"
}
],
"hypervisor": "xen",
"id": "i-915b1813",
"image_id": "ami-fedafc9d",
"instance_profile": null,
"interfaces": [
{
"id": "eni-96de4acf",
"mac_address": "0a:14:ac:64:c4:13"
}
],
"kernel": null,
"key_name": "ansible.key",
"launch_time": "2016-08-29T07:32:10.000Z",
"monitoring_state": "disabled",
"persistent": false,
"placement": {
"tenancy": "default",
"zone": "ap-southeast-2c"
},
"private_dns_name": "ip-xx-xx-xx-107.ap-southeast-2.compute.internal",
"private_ip_address": "xx.xx.xx.107",
"public_dns_name": "ec2-xx-xxx-xx-80.ap-southeast-2.compute.amazonaws.com",
"ramdisk": null,
"region": "ap-southeast-2",
"requester_id": null,
"root_device_type": "ebs",
"source_destination_check": "true",
"spot_instance_request_id": null,
"state": "running",
"tags": {
"Name": "Demo"
},
"virtualization_type": "hvm",
"vpc_id": "vpc-abcaf4ce"
}
]
}
what i m missing here?
Thanks
Benjo
If you look closely to ec2.instances you may note that:
it is a list, so you either access items by index ec2.instances[0] or iterate over them with with_items: structure.
there is no public_name attribute, only public_dns_name.

Resources