Reputation: 3765
I'm trying to run a playbook multiple times in a loop which creates AWS route53 records.
My task to create the route53 record looks like this:
- name: Create Public DNS record
route53:
profile: "{{ route53_profile_id }}"
command: "{{ dns_command }}"
zone: "{{ dns_zone }}"
record: "{{ dns_record_name }}.{{ dns_zone }}"
type: "{{ dns_type }}"
value: "{{ dns_value }}"
overwrite: "{{ dns_overwrite }}"
ttl: "{{ dns_ttl }}"
health_check: "{{ healthcheck.health_check.id | default(omit) }}"
failover: "{{ dns_setting.failover | default(omit) }}"
weight: "{{ dns_setting.weight | default(omit) }}"
region: "{{ region | default(omit) }}"
identifier: "{{ identifier | default(omit) }}"
My problem is that the health check isn't always defined every time.
Creation of the health check looks like this:
- name: Create healthcheck with IP address for EC2 instance
route53_health_check:
state: "{{ healthcheck.state | default( healthcheck_defaults.state ) }}"
profile: "{{ route53_profile_id }}"
region: "{{ vpc.region }}"
ip_address: "{{ dns_value }}"
type: "{{ healthcheck.type | default( healthcheck_defaults.type ) }}"
resource_path: "{{ healthcheck.resource_path | default( omit ) }}"
port: "{{ healthcheck.port | default( omit ) }}"
security_token: "{{ healthcheck.security_token | default( omit ) }}"
validate_certs: "{{ healthcheck.validate_certs | default( omit ) }}"
string_match: "{{ healthcheck.string_match | default( omit ) }}"
request_interval: "{{ healthcheck.request_interval | default( healthcheck_defaults.request_interval ) }}"
failure_threshold: "{{ healthcheck.failure_threshold | default( healthcheck_defaults.failure_threshold ) }}"
register: healthcheck
when:
- dns_type == "A"
- dns_setting.healthcheck is defined
If the loop runs 5 times, it may only be defined in one iteration. If the health check runs then the 'healthcheck' variable contains the details of the health check, e.g. the ID. If it does not run on a given loop, the 'healthcheck' variable contains the following:
"healthcheck": {
"changed": false,
"skip_reason": "Conditional check failed",
"skipped": true
}
In my route53 creation, the health check is omitted if the 'healthcheck' variable is undefined. However if it is defined, ansible attempts to dereference the id parameter of the health_check parameter of healthcheck, which doesn't exist.
If I try to set health check to a default value when not in use, e.g. {} then it is still defined, and my route53 creation fails.
Is there a way to force a variable or fact to be undefined? Something like:
- name: Undefine health check
set_fact:
healthcheck: undef
Upvotes: 0
Views: 886
Reputation: 68269
Try something like this:
- name: Create Public DNS record
route53:
... cut ...
health_check: "{{ healthcheck | skipped | ternary( omit, (healthcheck.health_check | default({})).id ) }}"
... cut ...
This will pass omit
if healthcheck
was skipped and healthcheck.health_check.id
otherwise.
From my experience, default
is not working properly with nested dicts of 2+ levels (i.e. works with mydict.myitem | default('ok')
but fails with mydict.mysubdict.myitem | default('ok')
, so I used the hack to default subdict to {}
first to safely access id
: (healthcheck.health_check | default({})).id
Upvotes: 1