Ansible: with_sequence variable start and end - ansible

In my playbook I supply a Jenkins build ID as follows:
-e frontend_build_id=43
This ID is used to tag Docker images created during the build process. Later I want to remove old images as follows:
- name: remove old frontend images
docker_image:
state: absent
name: "{{ docker_registry }}/{{ frontend_image_name }}"
tag: "{{ item }}"
force: yes
with_sequence:
start="{{ frontend_build_id }} - 10" end="{{ frontend_build_id }} - 1" stride=1
However I get following error:
TASK [FrontEnd : remove old frontend images] ***********************************
fatal: [10.98.68.116]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to have been in '/home/jenkins/workspace/myproject_development/roles/FrontEnd/tasks/main.yml': line 31, 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: remove old frontend images\n ^ here\n"}
What do I do wrong?
Maybe its better to achieve this with loop somehow?

Is this the sequence you're looking for?
with_sequence:
start="{{ frontend_build_id - 10 }}" end="{{ frontend_build_id - 1 }}" stride=1
The default of 'stride' is 1. For simplicity, it can be removed.
with_sequence:
start="{{ frontend_build_id - 10 }}" end="{{ frontend_build_id - 1 }}"
Loop 'range' will do the same. The end element is not inclusive and shall be incremented.
loop: "{{ range(frontend_build_id - 10, frontend_build_id)|list }}"
The explicit cast of the variable 'frontend_build_id' to the integer will make it more robust. Change each reference to 'frontend_build_id' to 'frontend_build_id|int'. For example:
with_sequence:
start="{{ frontend_build_id|int - 10 }}" end="{{ frontend_build_id|int - 1 }}"
This should probably solve the problem
unsupported operand type(s) for -: 'unicode' and 'int'

Related

Remove last character from variable

I am trying to remove the last character of the below output but I am having trouble doing it:
- debug:
msg: "{{ ansible_mounts|json_query('[?mount == `/`].device') }}"
register: rootpart
The below works with simple text:
- debug:
msg: "{{ '/dev/sda4'[:-1] }}"
But not with a variable:
- debug:
msg: "{{ rootpart[:-1] }}"
Error:
msg: Unexpected templating type error occurred on ({{ rootpart[:-1] }}): unhashable type: 'slice'
There is a big "don't" in your current attempt: you should not register on a debug task.
If you want to create a new variable, then use the set_fact module.
This is not only a better way to do it, it is also saving you from having a dictionary with the keys changed, failed and msg to dive into in order to get the variable you were expecting out of the msg property.
Then, your json_query is going to return you a list of devices, no matter if there is only one match thanks to your filter. So, you also need to get the first element of this list.
So, with all this, here are your two tasks:
- set_fact:
root_part: "{{ ansible_mounts | json_query(_query) }}"
vars:
_query: "[?mount == `/`].device | [0]"
- debug:
var: root_part[:-1]

azure-network_interface says variable is undefined

We switched to ansible 2.10
Before it was azure_rm_networkinterface_facts (working) now is azure_rm_networkinterface_info
- name: "Get facts for network interface by it's name"
azure_rm_networkinterface_facts:
resource_group: "{{ target_resourcegroup }}"
name: "{{ target_nic_name }}"
- name: "Define private IP address"
set_fact:
private_ip_address: "{{ ansible_facts | json_query(query) }}"
vars:
query: "azure_networkinterfaces[0].properties.ipConfigurations[0].properties.privateIPAddress"
when: azure_networkinterfaces|length > 0
Error I get is:
4 TASK [azure_preconditions : Define private IP address] *************************
00:01:38.844 [0;31mfatal: [40.118.86.58]: FAILED! => {"msg": "The conditional check 'azure_networkinterfaces|length > 0' failed. The error was: error while evaluating conditional (azure_networkinterfaces|length > 0): 'azure_networkinterfaces' is undefined\n\nThe error appears to be in '/var/lib/jenkins/workspace/PA-28544-ansible-version-upgrade/roles/azure_preconditions/tasks/main.yml': line 143, 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: \"Define private IP address\"\n ^ here\n"}[0m
00:01:38.844
azure_networkinterfaces seems to be a return value of azure_rm_networkinterface_facts so it's normal that it doesn't exist...
I'd write a playbook like this:
- name: "Get facts for network interface by it's name"
azure_rm_networkinterface_facts:
resource_group: "{{ target_resourcegroup }}"
name: "{{ target_nic_name }}"
register: output
I suggest you debug the output variable to check your return values. I don't know the version of Azure you are using and a lot of changes can exist depending on it.
- name: "Display return value"
debug:
msg: "{{ output }}"
You could play with output.azure_networkinterfaces or output.networkinterfaces
Following the last documentation, its seems azure_rm_networkinterface_fact is deprecated, replaced by azure_rm_networkinterface_info
azure_rm_networkinterface_info

Ansible: how to check if a variable is being loaded in a playbook?

I'm trying to write a playbook that will load vars from a group vars file then check if a variable exists
my playbook is like this:
---
- hosts: "{{ target }}"
roles:
- app
tasks:
- name: alert if variable does not exist
fail:
msg: "{{ item }} is not defined"
when: "{{ item }}" is not defined
with_items:
- country
- city
- street
...
My inventory file contains
[app]
ansible-slave1
ansible-slave2
[db]
ansible-db
[multi:children]
app
db
and I have the roles/app/vars/main.yml containing
country: "France"
city: "Paris"
What I was expecting is the playbook to output "street is not defined" but I have a syntax issue I can't resolve
[vagrant#ansible-master vagrant]$ ansible-playbook --inventory-file=ansible_master_hosts test_variables.yml --extra-vars "target=ansible-slave1" --syntax-check
ERROR! Syntax Error while loading YAML.
The error appears to have been in '/vagrant/test_variables.yml': line 10, column 24, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
msg: "{{ item }} is not defined"
when: "{{ item }}" is not defined
^ 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 }}"
I'd be happy with any hints.
Thanks
You have "" in invalid place of "when" statement. This should be like this:
msg: "{{ item }} is not defined"
when: "{{ item }} is not defined"
So the output will be:
failed: [hostname] (item=street) => {"changed": false, "item": "street", "msg": "street is not defined"}
there is on open issue conditional is defined fails to capture undefined var .
as a workaround I'd suggest to change the where condition to the following:
when: "{{ item }}" == ""

How to register with_items and act on conditional check result for each item

I'd like to register the contents of bashrc for two users and edit as/if required. My play is as follows.
- name: Check bashrc
shell: cat {{ item }}/.bashrc
register: bashrc
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Configure bashrc
shell:
cmd: |
cat >> {{ item }}/.bashrc <<EOF
STUFF
EOF
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
when: '"STUFF" not in bashrc.stdout'
It fails as follows:
fatal: [ca-o3lscizuul]: FAILED! => {"failed": true, "msg": "The conditional check '\"STUFF\" not in bashrc.stdout' failed. The error was: error while evaluating conditional (\"STUFF\" not in bashrc.stdout): Unable to look up a name or access an attribute in template string ({% if \"STUFF\" not in bashrc.stdout %} True {% else %} False {% endif %}).\nMake sure your variable name does not contain invalid characters like '-': argument of type 'StrictUndefined' is not iterable\n\nThe error appears to have been in '/root/openstack-ci/infrastructure-setup/staging/zuul/create-user.yml': line 35, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Configure bashrc\n ^ here\n"}
I think, if I understand your requirement correctly, you can use the 'lineinfile' or 'blockinfile' modules and save yourself the hassle of testing for the existence of the content:
- name: Noddy example data
set_fact:
single_line: "STUFF"
multi_line: |
STUFF
STUFF
profile_dirs:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Ensure STUFF exists in file
lineinfile:
path: "{{ item }}/.bashrc"
line: "{{ single_line }}"
loop: "{{ profile_dirs }}"
- name: Ensure block of STUFF exists in file
blockinfile:
path: "{{ item }}/.bashrc"
block: "{{ multi_line }}"
loop: "{{ profile_dirs }}"
Both modules give a lot more control and you can find their docs here: lineinfile | blockinfile

Ansible errors while using the with_sequence loop

i am testing looping code on ansible my first try worked:
- file:
state: touch
path: /tmp/{{ item }}
with_sequence: start=0 end={{ find_result.examined }}
this works the directorys are created
but if i use the same loop to create users i get an error
- name: User Creation
user:
name: "{{ find_result.files[item].path | regex_replace('/root/00staging/sshkeys/') | regex_replace('_id_rsa.pub')}}"
comment: nameduser
password: "{{ 'Start123' | password_hash('sha512') }}"
update_password: on_create
createhome: true
group: wheel
register: users_added
with_sequence: start=0 end={{ find_result.examined }}
The error:
{"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute u'0'\n\n
it works when i use the loop with_items but this is not dynamic enough
the variable is not empty it gets filled by this code:
- name: finding files
find:
paths: "/root/00staging/sshkeys"
file_type: "file"
register: find_result
Update:
i have the same error with simple sequence numbers the [item] is not getting filled but the {{ item }} gets filled correctly
find_result.files[item].path
with_sequence: start=0 end=1
The error you're seeing:
'list object' has no attribute u'0'
Suggests that the value of the find_result.files key is an empty list. In the first iteration of your loop you're trying to access find_result.files[0], but if that list is empty there is no element 0. You can generate the same error with the following example:
---
- hosts: localhost
gather_facts: false
vars:
empty_list: []
tasks:
- debug:
msg: "item {{ item }} is {{ empty_list[item] }}"
with_sequence: start=0 end=1
You should inspect the contents of the find_result variable (using e.g. a debug task) to confirm that it contains what you think it should contain.

Resources