Stat.exists with list of variables in ansible - variables

I have a problem with checking existing files using dictonary in Ansible.
tasks:
- name: Checking existing file id
stat: path=/tmp/{{ item.id }}.conf
with_items: "{{ file_vars }}"
register: check_file_id
- name: Checking existing file name
stat: path=/tmp/{{ item.name }}.conf
with_items: "{{ file_vars }}"
register: check_file_name
- name: Checking file exists
debug: msg='File_id exists'
when: check_file_id.stat.exists == True
- name: Checking file name exists
debug: msg='File name exists'
when: check_file_name.stat.exists == True
vars:
file_vars:
- { id: 1, name: one }
- { id: 2, name: two }
Then, if I trying to run playbook, I got the error:
FAILED! => {"failed": true, "msg": "The conditional check 'check_file_id.stat.exists == True' failed. The error was: error while evaluating conditional (check_file_id.stat.exists == True): 'dict' object has no attribute 'stat'\n\n
I've tried to debug it:
- debug: var=check_file_id
and got:
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/tmp/1.conf"
},
"module_name": "stat"
},
"item": {
"id": 1,
"name": "one"
},
"stat": {
"exists": false
}
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/tmp/2.conf"
},
"module_name": "stat"
},
"item": {
"id": 2,
"name": "two"
},
"stat": {
"exists": false
}
}
]
Where I am wrong?
Is is possible to use stat.exists with list of variables?
Thanks for answer!

The problem is that you are registering check_file_id in a loop. You need to read the documentation on using register in a loop, which discusses the implications of doing this. Your variable has a results key that contains the result of each iteration of the loop. You can see that in your debug output.
In subsequent tasks, you should iterate over check_file_id.results instead of file_vars, like this:
- hosts: localhost
gather_facts: false
vars:
file_vars:
- {id: 1, name: foo}
- {id: 2, name: bar}
tasks:
- name: Checking existing file id
stat:
path: ./files/{{ item.id }}.conf
with_items: "{{ file_vars }}"
register: check_file_id
- name: Checking existing file name
stat:
path: ./files/{{ item.name }}.conf
with_items: "{{ file_vars }}"
register: check_file_name
- debug:
msg: 'file id {{item.item.id}} (name {{item.item.name}}) exists'
with_items: "{{ check_file_id.results }}"
when: item.stat.exists
- debug:
msg: 'file name {{item.item.name}} (id {{item.item.id}}) exists'
with_items: "{{ check_file_name.results }}"
when: item.stat.exists

Related

Ansible nested variables syntax issue, error "dict object has no attribute"

I have the following data inside of Ansible variable server_info, set via register at the end of a task;
ok: [server123] => {
"msg": {
"changed": false,
"failed": false,
"instances": [
{
"ami_launch_index": 0,
"architecture": "x86_64",
"block_device_mappings": [
{
"device_name": "/dev/sda1",
"ebs": {
"attach_time": "2021-02-11T11:48:30+00:00",
"delete_on_termination": false,
"status": "attached",
"volume_id": "vol-5436546546"
}
},
{
"device_name": "/dev/sda2",
"ebs": {
"attach_time": "2021-02-11T11:48:30+00:00",
"delete_on_termination": false,
"status": "attached",
"volume_id": "vol-3546456535"
}
}
],
"capacity_reservation_specification": {
"capacity_reservation_preference": "open"
},
"client_token": "",
"cpu_options": {
"core_count": 2,
"threads_per_core": 1
},
"ebs_optimized": false,
"ena_support": true,
"enclave_options": {
"enabled": false
},
"hibernation_options": {
"configured": false
},
"hypervisor": "xen",
"iam_instance_profile": {
"arn": "arn:aws:iam::6346346356:instance-profile/bla",
"id": "SXIUIAHFKBAFIUAEKBADF"
},
"image_id": "ami-65754765475476",
"instance_id": "i-4657654765476547765",
"instance_type": "t2.large",
"key_name": "bla",
"launch_time": "2021-02-15T08:51:44+00:00",
"maintenance_options": {
"auto_recovery": "default"
},
etc... etc...
}
]
}
}
I am attempting to retrieve the value of "instance_id", however I get the following error;
- name: "Instance ID"
debug:
msg: "{{ server_info.instances.instance_id }}"
TASK [Instance ID]
************************************************************************************************************ fatal: [server123]: FAILED! => {"msg": "The task includes an option
with an undefined variable. The error was: 'list object' has no
attribute 'instance_id'\n\nThe error appears to be in
'/ansible/testing.yml': line 38, column 7,
but may\nbe elsewhere in the file depending on the exact syntax
problem.\n\nThe offending line appears to be:\n\n\n - name:
"Instance ID"\n ^ here\n"}
Where am I going wrong in my nested variable retrieval syntax?
Thank you.
See if the below code works
- name: get instance id
set_fact:
new_result: "{{ server_info.instances['instances'] }}"
register: filterd_result
- name: get all ids
vars:
reduce_query: >-
[].{
instance_id: instance_id
}
names: "{{ new_result | json_query(reduce_query)}}"
register: result_names
no_log: true
debug:
var: names
- name: display result
debug:
msg: "{{ result_names.names | map(attribute='instance_id') | flatten }}"
just modify your task:
- name: "Instance ID"
debug:
msg: "{{ server_info.instances.0.instance_id }}"
i suppose instances is an array with only one record ...
if you have more records in array you could use map:
- name: find all instances
debug:
msg:
- "==========================="
- "List of instances id"
- "==========================="
- '{{ server_info.instances | map(attribute="instance_id")|list}}'
- ""

Ansible Register access invocation_module?

I have a playbook that downloads a list of files from S3, this list can be set dynamically by utilizing with_items and |default([]).
After pulling this I need to get a list of destinations of the stored files and perform other actions. I registered the var output and see that invocation module_args has the value "Dest" which is what i want to access.
I've tried things like:
debug: msg="{{ item }}"
with_items: "{{ output.results }}
Or even accessing output.invocation but get undefined variable
Task:
- name: "Download Apps from S3"
aws_s3:
bucket: "{{ resource_bucket_name }}"
object: "{{ s3_apps[item].src }}"
dest: "{{ s3_apps[item].dest }}"
mode: get
with_items: "{{ s3_apps_decl |default([]) }}"
register: output
My output variable with debug:
"msg": [
{
"ansible_loop_var": "item",
"changed": true,
"failed": false,
"invocation": {
"module_args": {
"aws_access_key": null,
"aws_secret_key": null,
"bucket": "bucket-resources",
"debug_botocore_endpoint_logs": false,
"dest": "/tmp/test_app.tgz",
"dualstack": false,
"ec2_url": null,
"encrypt": true,
"encryption_kms_key_id": null,
"encryption_mode": "AES256",
"expiry": 600,
"headers": null,
"ignore_nonexistent_bucket": false,
"marker": "",
"max_keys": 1000,
"metadata": null,
"mode": "get",
"object": "test_app.tgz",
"overwrite": "always",
"permission": [
"private"
],
"prefix": "",
"profile": null,
"region": null,
"retries": 0,
"rgw": false,
"s3_url": null,
"security_token": null,
"src": null,
"validate_certs": true,
"version": null
}
},
"item": "test_app",
"msg": "GET operation complete"
},
{
"ansible_loop_var": "item",
"changed": true,
"failed": false,
"invocation": {
"module_args": {
"aws_access_key": null,
"aws_secret_key": null,
"bucket": "bucket-resources",
"debug_botocore_endpoint_logs": false,
"dest": "/tmp/testanotherapp.spl",
"dualstack": false,
"ec2_url": null,
"encrypt": true,
"encryption_kms_key_id": null,
"encryption_mode": "AES256",
"expiry": 600,
"headers": null,
"ignore_nonexistent_bucket": false,
"marker": "",
"max_keys": 1000,
"metadata": null,
"mode": "get",
"object": "testanotherapp.spl",
"overwrite": "always",
"permission": [
"private"
],
"prefix": "",
"profile": null,
"region": null,
"retries": 0,
"rgw": false,
"s3_url": null,
"security_token": null,
"src": null,
"validate_certs": true,
"version": null
}
},
"item": "testanotherapp",
"msg": "GET operation complete"
}
]
}
My expected output would be to define a variable that outputs:
['/tmp/testanotherapp.spl'.'/tmp/test_app.tgz']
I've tried set_fact with the similar syntax as my task above however that only saves the last value...
What you should expect in output is exactly what you get since you are receiving the return values from an aws_s3 module call which you are registering in a loop.
Now, if you want to get a list of only paths of all dest you have saved on your target host, you have to extract the corresponding attribute from your data structure.
- name: Show a list of dest paths from previous run
debug:
msg: "{{ output.results | map(attribute='invocation.module_args.dest') | list }}"

Error in adding user in RabbitMQ using Ansible

I am trying to create a rabbitmq node using terraform and ansible scripts,Other scripts are executing successfully but I am facing a warning while running this script of adding a user in rabbitmq node.
[WARNING]: Module did not set no_log for update_password
failed: [rabbit-node1] (item=admin) => {
"ansible_loop_var": "item",
"changed": false,
"cmd": "/usr/sbin/rabbitmqctl -q -n rabbit list_users",
"invocation": {
"module_args": {
"configure_priv": ".*",
"force": false,
"node": "rabbit",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"permissions": [
{
"configure_priv": ".*",
"read_priv": ".*",
"vhost": "/",
"write_priv": ".*"
}
],
"read_priv": ".*",
"state": "present",
"tags": "administrator,admin",
"update_password": "on_create",
"user": "admin",
"vhost": "/",
"write_priv": ".*"
}
},
"item": "admin",
"msg": "Error:********#rabbit-node1.\n * Suggestion: start it with \"rabbitmqctl start_app\" and try again",
"rc": 70,
"stderr": "Error: rabbit application is not running on node rabbit#rabbit-node1.\n * Suggestion: start it with \"rabbitmqctl start_app\" and try again\n",
"stderr_lines": [
"Error: rabbit application is not running on node rabbit#rabbit-node1.",
" * Suggestion: start it with \"rabbitmqctl start_app\" and try again"
],
"stdout": "",
"stdout_lines": []
}
main.yml file for Creating user in Rabbitmq node using ansible:
- name: add user
rabbitmq_user:
user: "{{ item }}"
password: "{{ ADMIN_PASS }}"
tags: administrator,{{item}}
vhost: /
configure_priv: .*
write_priv: .*
read_priv: .*
state: present
with_items:
- admin

Ansible aws s3 fails on directory checksuom when getting an object

when getting an object from an S3 bucket using the following Ansible command:
- name: "copy object from s3://{{ s3_bucket }}/{{ s3_object }} to {{ dest }}"
s3:
bucket: "{{ s3_bucket }}"
object: "{{ s3_object }}"
dest: "{{ dest }}"
mode: get
I get the following error:
fatal: [som_fake_host]: FAILED! => {
"changed": false,
"failed": true,
"invocation": {
"module_args": {
"aws_access_key": null,
"aws_secret_key": null,
"bucket": "some-fake-bucket",
"dest": "/some-fake-dest/",
"ec2_url": null,
"encrypt": true,
"expiry": "600",
"headers": null,
"ignore_nonexistent_bucket": false,
"marker": null,
"max_keys": "1000",
"metadata": null,
"mode": "get",
"object": "some_fake_file",
"overwrite": "always",
"permission": [
"private"
],
"prefix": null,
"profile": null,
"region": null,
"retries": 0,
"rgw": false,
"s3_url": null,
"security_token": null,
"src": null,
"validate_certs": true,
"version": null
}
},
"msg": "attempted to take checksum of directory: /some-fake-dest/"
}
additional useful information:
The destination directory exists
The user that runs the playbook has permission on the destination directory
The file exists in S3 bucket
Looking at the docs:
dest The destination file path when downloading an object/key with a GET operation.
Try to call module with file path, not directory. E.g.:
dest: "{{ dest }}/{{ s3_object }}"
or something.

Multiple ansible conditionals no longer work with version 1.9

I have the following task file in one of my roles:
- name: check for initalized fixtures
stat: path={{ fixture_init_file }}
register: fixture_init
- name: copy fixtures
copy: src={{ fixture_file }} dest={{ fixture_dest }}
when: fixture_init.stat.exists == False
- name: debug
debug: var=fixture_init
- name: db2
debug: var=database
- name: install fixtures (mysql)
shell: bzcat {{ fixture_dest }} | mysql --user=root {{ database.name }}
when: (fixture_init.stat.exists == False) and (database.type == "mysql")
register: fixture_init_result
- name: install password file (pgsql)
template: src=pgpass.j2 dest=/root/.pgpass mode=0600
when: database.type == "postgres"
- name: fixtures role map (pgsql)
template: src=gls-pgsql.j2 dest={{ fixture_pg_roles }} mode=0644
when: fixture_init_file.exists == False and database.type == "postgres"
- name: install role map (pgsql)
shell: psql -d {{ database.name }} < {{ fixture_pg_roles }}
when: fixture_init_file.exists == False and database.type == "postgres"
sudo_user: postgres
- name: install fixtures (pgsql)
shell: bzcat {{ fixture_dest }} | pg_restore -Fc -d {{ database.name }}
when: fixture_init_file.exists == False and database.type == "postgres"
sudo_user: postgres
register: fixture_init_result
- name: mark fixtured initalized
file: path={{ fixture_init_file }} state=touch
when: fixture_init_result|success
When I upgraded to Ansible 1.9.0.1, I now get the following error:
TASK: [database | install fixtures (pgsql)] ***********************************
fatal: [database] => error while evaluating conditional: fixture_init_file.exists == False and database.type == "postgres"
Those two debug statements show that the variables are properly defined:
TASK: [database | debug] ******************************************************
ok: [database] => {
"var": {
"fixture_init": {
"changed": false,
"invocation": {
"module_args": "path=/opt/bigsense/fixtures-initalized",
"module_name": "stat"
},
"stat": {
"exists": false
}
}
}
}
TASK: [database | db2] ********************************************************
ok: [database] => {
"var": {
"database": {
"ddl_password": "bigsense_ddl",
"ddl_username": "bigsense_ddl",
"name": "bigsense",
"password": "bigsense",
"type": "postgres",
"username": "bigsense"
}
}
}
Why do these conditionals no longer work?
The fixture_init_file.exists needs to be fixture_init_file.stat.exists ;)