Ansbile issue replacing variables - ansible

I am new to ansible and I am using variables to use awx polls, the case is that when I want to use these variables in the get_url task
- name: Download Artifact
get_url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
username: "{{ username }}"
password: "{{ password }}"
When I launch an ansible-playbook from my local I get this error
The offending line appears to be:
get_url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Does anyone know what can be due?

I think the problem is with the missing url key (docs)
Try the following
- name: Download Artifact
get_url:
url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
username: "{{ username }}"
password: "{{ password }}"

Related

Data from vault with with_items groups

I have a task that generates my configuration from jinja2 to conf.
- name: check password
set_fact:
my_secrets: "{{ lookup('hashi_vault', 'secret=kv/{{ stage }}.d/{{ app }}/{{ item }}/secrets token={{ token }} url={{ url }} validate_certs={{ validate_certs }}')}}"
with_items: "{{ groups['ns'] }}"
- name: copy config powerdns_auth pdns.local.gmysql.conf
template:
src: ../../../update/ns/templates/etc/powerdns/pdns.d/pdns.local.gmysql.conf.j2
dest: ../../../config/{{ stage }}/{{ item }}/etc/powerdns/pdns.d/pdns.local.gmysql.conf
mode: '0644'
with_items: "{{ groups['ns'] }}"
in pdns.local.gmysql.conf.j2
gmysql-password={{ my_secrets.user_password_mysql }}
I have a problem because it saves me the from vault password from the last host to a file.
Is it possible to set the fact depending on the host?
Don't loop over groups, use the "natural" play loop on hosts and delegate the needed tasks to localhost.
Note: I kept your relative paths in the template tasks but it looks ugly and will break one day or an other.
Note2: "moustaches don't stack" => I fixed your code (there are other ways to fix it...) where it was incorrect when fetching from hashicorp vault.
- name: Create config files per hosts
hosts: ns
gather_facts: false
vars:
# All your needed vars that I will not define here for this example
tasks:
- name: check password
vars:
secret: "kv/{{ stage }}.d/{{ app }}/{{ inventory_hostname }}/secrets"
hashi_string: "secret={{ secret }} token={{ token }} url={{ url }} validate_certs={{ validate_certs }}"
set_fact:
my_secrets: "{{ lookup('hashi_vault', hashi_string) }}"
- name: copy config powerdns_auth pdns.local.gmysql.conf
template:
src: ../../../update/ns/templates/etc/powerdns/pdns.d/pdns.local.gmysql.conf.j2
dest: ../../../config/{{ stage }}/{{ inventory_hostname }}/etc/powerdns/pdns.d/pdns.local.gmysql.conf
mode: '0644'
delegate_to: localhost

Can we have 2 with_items in ansible in a single task

Below is the condition
- name: Find the image
slurp:
src: "{{ IMAGE }}"
register: slurp_results
- name: Upload image
shell: |
skopeo copy -docker-archive:{{ item }}.tar docker://{{ URL }}/TESTIMAGE
with_items: "{{ (slurp_results.content|b64decode).splitlines() }}"
The above code works.
But I would need "TESTIMAGE" also to be replaced as {{ item }} like below.
skopeo copy -docker-archive:{{ item }}.tar docker://{{ URL }}/{{ item }}
How to define 2 with_items in a single shell task with 2 different slurp results
I believe you can by using the subelements module. Here is a link. Try going by this example:
- name: Setup MySQL users, given the mysql hosts and privs subkey lists
mysql_user:
name: "{{ item.0.name }}"
password: "{{ item.0.mysql.password }}"
host: "{{ item.1 }}"
priv: "{{ item.0.mysql.privs | join('/') }}"
with_subelements:
- "{{ users }}"
- mysql.hosts
Users is referred to as item.0 and hosts as item.1 and so on.

Ansible - skip undefined variable in dict

I`m using ipa_user module to setup users. There is variable passsword which force new password.
For some users (when var is not in dict) I would like to skip it in iteration, but it always fail.
This is snippet from my playbook. Ansible version is 2.7
task:
- name: adding ipa users
ipa_user:
name: "{{ item.value.login }}"
state: "{{ item.value.state }}"
givenname: "{{ item.value.givenname }}"
sn: "{{ item.value.surname }}"
mail: "{{ item.value.mail }}"
telephonenumber: "{{ item.value.telephonenumber }}"
title: "{{ item.value.title }}"
password: "{{ item.value.password }}" <<- to be skipped if not found
ipa_host: ipa.gdi.telekom.de
ipa_user: admin
ipa_pass: "{{ ipa_pass }}"
with_dict: "{{ipausers}}"
when: item.key in ipausers.keys()
register: output_ipa_users
Log:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'password'\n\nThe error appears to have been in '/builds/gitlab/infra/user-management/roles/free-ipa/tasks/main.yml': line 13, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: adding ipa users\n ^ here\n"}
Note: I tried it with:
with_dict: "{{ipausers|default({})}}"
ignore_errors: yes
without success
Not sure if it'll be much help to you now but for others than stumble on this post, I ended up with something like below for a similar problem. I'm using Ansible 2.7.8.
- name: Creating user accounts...
user:
name: "{{ item.name }}"
state: "{{ item.state }}"
comment: "{{ item.comment | default(omit) }}"
group: "{{ item.groups is defined | ternary((item.groups|default([]))[0], omit) }}"
groups: "{{ item.groups | default(omit) }}"
password: "{{ item.password_hash | default(omit) }}"
uid: "{{ item.uid | default(omit) }}"
with_items: "{{ managed_users }}"
The solution is
group: "{{ item.groups is defined | ternary((item.groups|default([]))[0], omit) }}"
If groups isn't in item then Ansible will omit the group part of this tasks but jinja2 will evaluate item.groups[0] anyway. So to allow for this we have to use item.groups|default([]) so jinja2 uses an empty list when groups isn't defined instead of throwing a 'dict object' has no attribute error. The omit part is similar to the default(omit) filter where Ansible simply omits the option from the task.
Lubo's problem is a little simpler so using just default(omit) filter should work. That said as password is required so the entire task should be skipped with a conditional.
- name: adding ipa users
ipa_user:
name: "{{ item.value.login }}"
state: "{{ item.value.state }}"
givenname: "{{ item.value.givenname }}"
sn: "{{ item.value.surname }}"
mail: "{{ item.value.mail }}"
telephonenumber: "{{ item.value.telephonenumber }}"
title: "{{ item.value.title }}"
password: "{{ item.value.password | default(omit) }}" #<-- would be omitted
ipa_host: ipa.gdi.telekom.de
ipa_user: admin
ipa_pass: "{{ ipa_pass }}"
with_dict: "{{ipausers}}"
when: item.key in ipausers.keys() and item.key.password is defined #<-- second check for when password is not defined.
register: output_ipa_users
If you want to completely skip the ipa_user module execution when password is not defined, check for its presence in your when clause:
when: item.value.password | default('') | length > 0
If you want to execute the ipa_user module without specifying a password for user if it does not exists, use the omit placeholder in your module params:
password: "{{ item.value.password | default(omit) }}"
Note: your current when clause can be removed. It will always return true as you are looping over a dict and later checking if the current key in the loop is part of that dict.
There is a special omit variable to omit module parameters.
password: "{{ item.value.password|default(omit) }}"
To make a playbook or a role reusable it is a good idea to declare all parameters of a module in the task and default(omit) parameters that are not required.

Use Jinja2 dict as part of an Ansible modules options

I have the following dict:
endpoint:
esxi_hostname: servername.domain.com
I'm trying to use it as an option via jinja2 for the vmware_guest but have been unsuccessful. The reason I'm trying to do it this way is because the dict is dynamic...it can either be cluster: clustername or esxi_hostname: hostname, both mutually exclusive in the vmware_guest module.
Here is how I'm presenting it to the module:
- name: Create VM pysphere
vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
validate_certs: no
datacenter: "{{ ansible_host_datacenter }}"
folder: "/DCC/{{ ansible_host_datacenter }}/vm"
"{{ endpoint }}"
name: "{{ guest }}"
state: present
guest_id: "{{ osid }}"
disk: "{{ disks }}"
networks: "{{ niclist }}"
hardware:
memory_mb: "{{ memory_gb|int * 1024 }}"
num_cpus: "{{ num_cpus|int }}"
scsi: "{{ scsi }}"
customvalues: "{{ customvalues }}"
cdrom:
type: client
delegate_to: localhost
And here is the error I'm getting when including the tasks file:
TASK [Preparation : Include VM tasks] *********************************************************************************************************************************************************************************
fatal: [10.10.10.10]: FAILED! => {"reason": "Syntax Error while loading YAML.
The error appears to have been in '/data01/home/hit/tools/ansible/playbooks/roles/Preparation/tasks/prepareVM.yml': line 36, column 4, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
"{{ endpoint }}"
hostname: "{{ vcenter_hostname }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
exception type: <class 'yaml.parser.ParserError'>
exception: while parsing a block mapping
in "<unicode string>", line 33, column 3
did not find expected key
in "<unicode string>", line 36, column 4"}
So in summary, I'm not sure how to format this or if it is even possible.
The post from techraf sums up your problem, but for a possible solution, in the docs, especially regarding Jinja filters, there is the following bit:
Omitting Parameters
As of Ansible 1.8, it is possible to use the default filter to omit
module parameters using the special omit variable:
- name: touch files with an optional mode
file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}} > with_items:
- path: /tmp/foo
- path: /tmp/bar
- path: /tmp/baz
mode: "0444"
For the first two files in the list, the default mode will be
determined by the umask of the system as the mode= parameter will not
be sent to the file module while the final file will receive the
mode=0444 option.
So it looks like what should be tried is:
esxi_hostname: "{{ endpoint.esxi_hostname | default(omit) }}"
# however you want the alternative cluster settings done.
# I dont know this module.
cluster: "{{ cluster | default(omit) }}"
This is obviously reliant on the vars to only have one choice set.
There is no way you could ever use the syntax you tried in the question, because firstly and foremostly Ansible requires a valid YAML file.
The closest workaround would be to use a YAML anchor/alias although it would work only with literals:
# ...
vars:
endpoint: &endpoint
esxi_hostname: servername.domain.com
tasks:
- name: Create VM pysphere
vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
validate_certs: no
datacenter: "{{ ansible_host_datacenter }}"
folder: "/DCC/{{ ansible_host_datacenter }}/vm"
<<: *endpoint
name: "{{ guest }}"
state: present
guest_id: "{{ osid }}"
disk: "{{ disks }}"
networks: "{{ niclist }}"
hardware:
memory_mb: "{{ memory_gb|int * 1024 }}"
num_cpus: "{{ num_cpus|int }}"
scsi: "{{ scsi }}"
customvalues: "{{ customvalues }}"
cdrom:
type: client
delegate_to: localhost

How can i assign a varaible in a variable

Here's my task.
- name: Add A record for "{{ ec2_hostname }}.{{ internal_domain }}"
route53:
command: create
zone: "{{ internal_domain }}"
private_zone: "{{ private_type }}"
record: "{{ ec2_hostname }}.{{ internal_domain }}"
type: A
ttl: 300
value: "{{ ansible_ec2_[ec2_r53_type]_ipv4 }}"
Specifically having trouble with this line:
value: "{{ ansible_ec2_[ec2_r53_type]_ipv4 }}"
I need to insert ec2_r53_type inside a string to create another variable. This should be either "public" or "local".
So the expected result should be
value: "{{ ansible_ec2_local_ipv4 }}"
or
value: "{{ ansible_ec2_public_ipv4 }}"
Whats the logic here, tried all i knew no luck
This should work
value: "{{ vars['ansible_ec2_' + ec2_r53_type + '_ipv4'] }}"
- find: ^CODEDEPLOY_USER=""
replace: CODEDEPLOY_USER=""{{ app_install_user }}""
"/"{{ app_install_user }}/"" something as such, This is on the vars folder of a play
I would require to add the variable in qoutes on the vars of roles.
roles/xxxx/vars/main.yml
app_install_user is added on group_vars of ansible

Resources