Ansible playbook for restic - ansible

i was trying to setup Restic on a remote server using ansible but I keep getting this error
failed: [167.172.31.145] (item={'key': 'remote', 'value': {'location':
'ams3.digitaloceanspaces.com 167.172.31.145', 'password': '',
'aws_access_key': '', 'aws_secret_access_key': '',
'aws_default_region': '', 'init': True}}) => {"ansible_loop_var":
"item", "changed": false, "cmd": ["/usr/local/bin/restic", "init"],
"delta": "0:00:02.769841", "end": "2022-10-15 07:43:42.240541",
"failed_when_result": true, "item": {"key": "remote", "value":
{"aws_access_key": "", "aws_default_region": "",
"aws_secret_access_key": "", "init": true, "location":
"ams3.digitaloceanspaces.com 167.172.31.145", "password": ""}}, "msg":
"non-zero return code", "rc": 1, "start": "2022-10-15
07:43:39.470700", "stderr": "Fatal: create key in repository at
s3:ams3.digitaloceanspaces.com/resticspace/ failed: client.PutObject:
Access Denied.", "stderr_lines": ["Fatal: create key in repository at
s3:ams3.digitaloceanspaces.com/resticspace/ failed: client.PutObject:
Access Denied."], "stdout": "", "stdout_lines": []}
here's my play book
- hosts: testdrops
roles:
- role: do1jlr.restic
vars:
restic_create_schedule: true
restic_create_cron: true
restic_schedule_type: cronjob
restic_repos:
remote:
location: ams3.digitaloceanspaces.com {{ inventory_hostname }}
password: "{{ lookup('env', 'RESTIC_PASSWORD') }}"
aws_access_key: "{{ lookup('env', 'AWS_ACCESS_KEY_ID') }}"
aws_secret_access_key: "{{ lookup('env', 'AWS_SECRET_ACCESS_KEY') }}"
aws_default_region: "{{ lookup('env', 'AWS_DEFAULT_REGION') }}"
init: true
restic_backups:
etc:
name: etc
repo: remote
src: /etc/
scheduled: true
schedule_minute: 0
schedule_hour: 9
schedule_weekday: 1
schedule_month: '*'

Related

ansible: "variable is not defined" even with ignore_erros: True & failed_when: 0 > 1 | How to define variable when task is failed/ignored/skipped?

Trying to get a variable defined when the task is partially failed/ignored. When a VM is not found in Vsphere it throws an error: "msg": "Unable to gather information for non-existing VM vm2"
I tried with and without ignore_errors: True and failed_when: 0 > 1 but no change.
I need the variable vm_fact to be defined even when a non-existing VM is in the decom_list. The plan is to change the list after i have identified which VM's are non-existing.
Please note: this task does work when all vm's are present in the system. When one is missing the task fails. I need the task not to fail so that i can clean the decom_list and then run it again.
- name: check/power(on/off) hosts on vsphere
hosts: localhost
ignore_errors: True
vars:
decom_list:
- vm1
- vm2
- vm3
tasks:
- name: check hosts on vsphere
vmware_guest_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
name: "{{ item }}"
schema: vsphere
datacenter: DC1
loop: "{{ decom_list }}"
register: vm_fact
ignore_errors: True
failed_when: 0 > 1
Whatever i try does not work because my vm_fact is not defined.
- debug:
var: "{{ vm_fact }}"
error:
TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
"<class 'dict'>": "VARIABLE IS NOT DEFINED!"
}
Just to confirm i did try all i know.
When i try it with a loop:
- debug:
var: "{{ item['item'] }}"
loop: "{{ vm_fact['results'] }}"
when: '"Unable to gather information for non-existing VM" in item.msg'
I get error:
ok: [localhost] => (item={'failed': False, 'msg': 'Unable to gather information for non-existing VM vm2', 'invocation': {'module_args': {'hostname': 'hostname.domain', 'username': 'username', 'password': 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER', 'name': 'vm2', 'schema': 'vsphere', 'datacenter': 'DC1', 'port': 443, 'validate_certs': True, 'name_match': 'first', 'use_instance_uuid': False, 'tags': False, 'tag_details': False, 'proxy_host': None, 'proxy_port': None, 'uuid': None, 'moid': None, 'folder': None, 'properties': None}}, 'changed': False, 'failed_when_result': False, 'item': 'vm2', 'ansible_loop_var': 'item'}) => {
"ansible_loop_var": "item",
"item": {
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"failed_when_result": false,
"invocation": {
"module_args": {
"datacenter": "DC1",
"folder": null,
"hostname": "hostname.domain",
"moid": null,
"name": "vm2",
"name_match": "first",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"properties": null,
"proxy_host": null,
"proxy_port": null,
"schema": "vsphere",
"tag_details": false,
"tags": false,
"use_instance_uuid": false,
"username": "username",
"uuid": null,
"validate_certs": true
}
},
"item": "vm2",
"msg": "Unable to gather information for non-existing VM vm2"
},
"vm2": "VARIABLE IS NOT DEFINED!"
}
ok: [localhost] => (item={'failed': False, 'msg': 'Unable to gather information for non-existing VM vm3', 'invocation': {'module_args': {'hostname': 'hostname.domain', 'username': 'username', 'password': 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER', 'name': 'vm3', 'schema': 'vsphere', 'datacenter': 'DC1', 'port': 443, 'validate_certs': True, 'name_match': 'first', 'use_instance_uuid': False, 'tags': False, 'tag_details': False, 'proxy_host': None, 'proxy_port': None, 'uuid': None, 'moid': None, 'folder': None, 'properties': None}}, 'changed': False, 'failed_when_result': False, 'item': 'vm3', 'ansible_loop_var': 'item'}) => {
"ansible_loop_var": "item",
"item": {
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"failed_when_result": false,
"invocation": {
"module_args": {
"datacenter": "DC1",
"folder": null,
"hostname": "hostname.domain",
"moid": null,
"name": "vm3",
"name_match": "first",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"properties": null,
"proxy_host": null,
"proxy_port": null,
"schema": "vsphere",
"tag_details": false,
"tags": false,
"use_instance_uuid": false,
"username": "username",
"uuid": null,
"validate_certs": true
}
},
"item": "vm3",
"msg": "Unable to gather information for non-existing VM vm3"
},
"vm3": "VARIABLE IS NOT DEFINED!"
}
fatal: [localhost]: FAILED! => {"msg": "The conditional check '\"Unable to gather information for non-existing VM\" in item.msg' failed. The error was: error while evaluating conditional (\"Unable to gather information for non-existing VM\" in item.msg): 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'location': line 33, column 24, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n # - debug: var=vm_fact\n ^ here\n\nThere appears to be both 'k=v' shorthand syntax and YAML in this task. Only one syntax may be used.\n"}
Tried:
- debug:
msg: "{{ vm_fact['results']|json_query('msg') }}"
- debug:
msg: "{{ vm_fact['results']|to_json|from_json|map(attribute='msg') }}"
- debug:
msg: "{{ vm_fact['results']|map(attribute='msg') }}"
- debug:
msg: "{{ vm_fact['results']|dict2items|map(attribute='msg') }}"
- debug:
msg: "{{ vm_fact['results']|flatten|map(attribute='msg') }}"
error:
TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
"msg": ""
}
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'location': line 42, 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 - debug:\n ^ here\n"}
...ignoring
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'location': line 45, 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 - debug:\n ^ here\n"}
...ignoring
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{ vm_fact['results']|dict2items|map(attribute='msg') }}): dict2items requires a dictionary, got <class 'list'> instead."}
...ignoring
TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'\n\nThe error appears to be in 'lcoation': line 51, 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 - debug:\n ^ here\n"}
...ignoring
You are, frankly, making things very difficult for yourself. Ansible loops through hosts, use it.
decom.inv:
[decom]
vm1
vm2
vm3
decom.yml:
- name: check/power(on/off) hosts on vsphere
hosts: decom
gather_facts: no
tasks:
- name: check hosts on vsphere
vmware_guest_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
name: "{{ ansible_hostname }}"
schema: vsphere
datacenter: DC1
register: vm_fact
ignore_errors: True
failed_when: false
delegate_to: localhost
- name: Show results
debug:
var: vm_fact

To collect backing_datastore from the vmware_guest_disk_info module output

I'm using the below tasks in the playbook to find the backing datastore in the vmware but I tried various options, which is not helping to gather the backing_datastore name, kindly suggest how to fetch:
- name: Take Snapshot
hosts: patching
serial: 1
vars_files:
- 1credentials.yml
tasks:
- name: Gather data of the registered virtual machines
community.vmware.vmware_vm_info:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
vm_type: vm
validate_certs: no
delegate_to: localhost
register: vminfo
- debug:
msg: "{{ item.datacenter }}"
loop: "{{ vminfo.virtual_machines}}"
when: item.ip_address == inventory_hostname
- name: Gather Disk facts for the server - {{ inventory_hostname }}
vmware_guest_disk_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
datacenter: "{{ item.datacenter }}"
uuid: "{{ item.uuid }}"
validate_certs: False
delegate_to: localhost
register: disk_fact
loop: "{{ vminfo.virtual_machines }}"
when: item.ip_address == inventory_hostname
- debug:
msg: "{{ item.backing_datastore }}"
loop: "{{ disk_fact }}"
The raw output of the registered variable disk_fact is mentioned below:
ok: [172.17.92.62] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"item": {
"allocated": {},
"attributes": {},
"cluster": "Training",
"datacenter": "opendc-rookie",
"datastore_url": [
{
"name": "Rookie-Core",
"url": "/vmfs/volumes/60ebc5fb-2e22fef3-ec42-1402ec6fadc8"
},
{
"name": "ENV08",
"url": "/vmfs/volumes/60ebd414-4e6253d6-7e29-1402ec6fadc8"
}
],
"esxi_hostname": "172.17.138.13",
"folder": "/opendc-rookie/vm/ENV08",
"guest_fullname": "Microsoft Windows 8.x (64-bit)",
"guest_name": "win1",
"ip_address": "172.17.92.43",
"mac_address": [
"00:50:56:81:2e:64"
],
"moid": "vm-968",
"power_state": "poweredOn",
"tags": [],
"uuid": "4201e3dd-0cf5-1027-7eaf-d2b8804761d9",
"vm_network": {
"00:50:56:81:2e:64": {
"ipv4": [
"172.17.92.43"
],
"ipv6": []
}
}
},
"skip_reason": "Conditional result was False",
"skipped": true
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"guest_disk_info": {
"0": {
"backing_datastore": "ENV04",
"backing_disk_mode": "persistent",
"backing_diskmode": "persistent",
"backing_eagerlyscrub": false,
"backing_filename": "[ENV04] ansible_automation_platofrm_RHEL8/ansible_automation_platofrm_RHEL8-000005.vmdk",
"backing_thinprovisioned": false,
"backing_type": "FlatVer2",
"backing_uuid": "6000C294-c77a-56fa-180c-d17ac9693433",
"backing_writethrough": false,
"capacity_in_bytes": 25769803776,
"capacity_in_kb": 25165824,
"controller_bus_number": 0,
"controller_key": 1000,
"controller_type": "paravirtual",
"key": 2000,
"label": "Hard disk 1",
"summary": "25,165,824 KB",
"unit_number": 0
}
},
"invocation": {
"module_args": {
"datacenter": "opendc-rookie",
"folder": null,
"hostname": "172.17.168.212",
"moid": null,
"name": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"proxy_host": null,
"proxy_port": null,
"use_instance_uuid": false,
"username": "Administrator#vsphere.local",
"uuid": "42013f12-5142-2b83-1ce7-6c334958afd5",
"validate_certs": false
}
},
"item": {
"allocated": {},
"attributes": {},
"cluster": "Training",
"datacenter": "opendc-rookie",
"datastore_url": [
{
"name": "Rookie-Core",
"url": "/vmfs/volumes/60ebc5fb-2e22fef3-ec42-1402ec6fadc8"
},
{
"name": "ENV04",
"url": "/vmfs/volumes/60ebd318-7c586ef0-5838-1402ec6fadc8"
}
],
"esxi_hostname": "172.17.138.13",
"folder": "/opendc-rookie/vm/Pugaz",
"guest_fullname": "Red Hat Enterprise Linux 8 (64-bit)",
"guest_name": "ansible_automation_platofrm_RHEL8",
"ip_address": "172.17.92.62",
"mac_address": [
"00:50:56:81:c6:e3"
],
"moid": "vm-836",
"power_state": "poweredOn",
"tags": [],
"uuid": "42013f12-5142-2b83-1ce7-6c334958afd5",
"vm_network": {
"00:50:56:81:c6:e3": {
"ipv4": [
"172.17.92.62"
],
"ipv6": [
"fe80::250:56ff:fe81:c6e3"
]
}
}
}
}
Kindly suggest how can I fetch the backing_datastore from the above mentioned output.
The result is a list because there might be more items with the attribute backing_datastore. For example,
backing_datastores: "{{ disk_fact.results|json_query(_query) }}"
_query: '[].guest_disk_info[].*.backing_datastore'
gives
backing_datastores:
- - ENV04
If you want the first one
backing_datastore: "{{ backing_datastores|flatten|first }}"
gives
backing_datastore: ENV04
If you want to iterate results
- debug:
msg: "{{ item.guest_disk_info['0'].backing_datastore }}"
loop: "{{ disk_fact.results }}"
loop_control:
label: "{{ item.item.ip_address }}"
when: not item.skipped|d(false)
gives the attribute backing_datastore of the disk "0"
TASK [debug] **************************************************
skipping: [localhost] => (item=172.17.92.43)
ok: [localhost] => (item=172.17.92.62) =>
msg: ENV04
If you want to get the list of attributes backing_datastore of all disks use json_query in the loop
- debug:
msg: "{{ item.guest_disk_info|json_query('*.backing_datastore') }}"
loop: "{{ disk_fact.results }}"
loop_control:
label: "{{ item.item.ip_address }}"
when: not item.skipped|d(false)
gives
TASK [debug] **************************************************
skipping: [localhost] => (item=172.17.92.43)
ok: [localhost] => (item=172.17.92.62) =>
msg:
- ENV04
Example of a complete playbook for testing
- hosts: localhost
vars_files:
- disk_fact.json
vars:
backing_datastores: "{{ disk_fact.results|json_query(_query) }}"
_query: '[].guest_disk_info[].*.backing_datastore'
backing_datastore: "{{ backing_datastores|flatten|first }}"
tasks:
- debug:
var: backing_datastores
- debug:
var: backing_datastore
- debug:
msg: "{{ item.guest_disk_info['0'].backing_datastore }}"
loop: "{{ disk_fact.results }}"
loop_control:
label: "{{ item.item.ip_address }}"
when: not item.skipped|d(false)

Need help looping through Ansible msg output

I need help going through the output of this task in ansible and ONLY pulling out the path for the "{{ item }}" being found.
Tried multiple ways and having very little success. Still learning ansible, and in this case, I'm trying to create a new directory based on the output of my inventory file. (the tail command for now because I only need to test it on 10 entries)
Playbook:
'''
- name: Get the inventory file printout.
command: tail "{{ build_dir }}{{ inventory_file }}"
register: command_output
- debug:
msg: "{{ command_output.stdout_lines }}"
- name : Find the RPMs in "{{ build_dir }}"
find:
paths: "{{ build_dir }}"
patterns: "{{ item }}.rpm"
recurse: yes
with_items:
- "{{ command_output.stdout_lines }}"
register: found_pkgs
- name: Just the Path for each Found Pkgs.
debug:
msg: "{{ item }}"
loop:
- "{{ found_pkgs }}"
Output:
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"examined": 15029,
"failed": false,
"files": [
{
"atime": 1629933434.2974539,
"ctime": 1629814445.3359122,
"dev": 64773,
"gid": 70000,
"gr_name": "engineering",
"inode": 469762133,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1629814445.3359122,
"nlink": 1,
"path": "<REDACTED>/newISO/repos/zeek/packages/zeek-btest-4.0.2-1.1.x86_64.rpm",
You could use json_query filter to extract the path of each file from results[]. A set_fact task such as below should do:
- name: save the files path in file_names var
set_fact:
file_paths: "{{ found_pkgs | json_query('results[].files[].path') }}"
- name: show file names
debug:
var: file_paths

Debug not working with_items in ansible play

Need some help in debug the specific value from register task.
- debug:
msg: "{{ item.stdout }}"
with_items: path_result.results
This is not working
{
"changed": false,
"path_result": {
"msg": "All items completed",
"changed": true,
"results": [
{
"_ansible_parsed": true,
"stderr_lines": [],
"_ansible_item_result": true,
"end": "2019-04-10 14:55:18.726270",
"_ansible_no_log": false,
"_ansible_delegated_vars": {
"ansible_delegated_host": "**.***.***.***",
"ansible_host": "**.***.***.***"
},
"cmd": "cat /tmp/abc.conf | grep apple",
"rc": 0,
"stdout": "fruit=apple",
"item": "**.***.***.***",
"delta": "0:00:00.021499",
"stderr": "",
"changed": true,
"invocation": {
"module_args": {
"creates": null,
"executable": null,
"_uses_shell": true,
"_raw_params": "cat /tmp/abc.conf | grep apple",
"removes": null,
"warn": true,
"chdir": null,
"stdin": null
}
},
"stdout_lines": [
"fruit=apple"
],
"start": "2019-04-10 14:55:18.704771",
"_ansible_ignore_errors": null,
"failed": false
}
]
},
"_ansible_verbose_always": true,
"_ansible_no_log": false
}
I would like to debug this particular output:
"stdout": "fruit=apple"
It looks like you have registered the result of a play with: register: path_result. That variable ALSO has path_result inside it. Here's what I think you have:
- command: cat /tmp/abc.conf | grep apple
register: path_result
- debug:
msg: "{{ item.stdout }}"
with_items: "{{ path_result.results }}"
Here's what I think you need:
- command: cat /tmp/abc.conf | grep apple
register: path_result
- debug:
msg: "{{ item.stdout }}"
with_items: "{{ path_result.path_result.results }}"
Notice the added .path_result part in with_items.

ansible V2 -> "skip_reason": "Conditional check failed" with_items

I am getting some errors while doing the following:
group_vars:
tomcat_servers:
- name: tomcat_1
shutdown_port: 8005
connector_port: 8080
ajp_port: 8009
- name: tomcat_2
shutdown_port: 8105
connector_port: 8180
ajp_port: 8109
main code:
- name: "Check if tomcat is already installed"
stat: path={{ tomcat_server_dir }}/{{ item.name }}/RELEASE-NOTES
register: status
with_items: "{{ tomcat_servers }}"
- debug: var=status
- name: "Copy tomcat into folder if it is not installed"
command: /bin/tar -zxvf /tmp/{{ tomcat_catalina_base }} -C {{ tomcat_server_dir }}/{{ item.name }} --strip 2
when: not status.results[0].stat.exists
with_items:
- "{{ tomcat_servers }}"
- "{{ status.results }}"
Debug result:
ok: [VM1] => {
"status": {
"changed": false,
"msg": "All items completed",
"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": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8009,
"connector_port": 8080,
"name": "tomcat_1",
"shutdown_port": 8005
},
"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": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8109,
"connector_port": 8180,
"name": "tomcat_2",
"shutdown_port": 8105
},
"stat": {
"exists": false
}
}
]
}
}
Now unfortunally I seem to get the error
"skip_reason": "Conditional check failed", "skipped": true
I have been around the "have you googled it" many times but cannot seem to find the solution here. Google ansible check if file exists with_items and you will probably see the same results.
Any one got an idea how to get this working?
Correct second loop:
---
- hosts: localhost
vars:
results:
- item:
ajp_port: 8009
connector_port: 8080
name: tomcat_1
shutdown_port: 8005
stat:
exists: false
- item:
ajp_port: 8109
connector_port: 8180
name: tomcat_2
shutdown_port: 8105
stat:
exists: false
- item:
name: tomcat_exist
stat:
exists: true
tasks:
- debug:
msg: "name: {{ item.item.name }}, exists: {{ item.stat.exists }}"
when: not item.stat.exists
with_items: "{{ results }}"
So in your setup you need to loop over status.results and refer to item.item.name and item.stat.exists.

Resources