Ansible regex tomcat version - ansible

I'm struggling with an issue for some hours now, I want in tasks file to do an action only for a specific version of tomcat, exemple :
- name: Copy new context.xml(Manager App) for tomcat8 or 9
template:
src: templates/tomcat8-9/manager/context.xml
dest: /usr/share/tomcat/webapps/manager/META-INF/context.xml
owner: tomcat
group: tomcat
when: "{{ tomcat_ver }}" is match("^[8-9]")
If my tomcat_ver is 9.0.20 then it should match the pattern but I'm getting a strange error, I don't see where I'm missing any quote
fatal: [tomcatbis]: FAILED! => {"reason": "Syntax Error while loading YAML.\n did not find expected key\n\nThe error appears to be in '/projects/ansibles/roles/tomcat/tasks/tomcat-setup-Debian.yml': line 69, column 28, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n group: tomcat\n when: \"{{ tomcat_ver }}\" is match(\"^[8-9]\")\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"}
Thanks for your help.

It should be like below:
---
- hosts: localhost
tasks:
- name: plat
debug:
msg: "Success"
when: '"{{ tomcat_ver }}" is match("^[8-9]")'
single quotes at the start and at the end

Use the version comparison test
when: tomcat_ver is version('8', '==') or
tomcat_ver is version('9', '==')
(not tested)

Related

Check multiple conditions in ansible when

I am giving a condition to my ansible task:
- hosts: "{{ env }}"
user: "{{ us1 }}"
gather_facts: no
tasks:
- name: Deploy Services on "{{ env }}"
shell: sh "{{ script_path }}/test.sh"
when: (package == "abc") and (env.startswith('PA_') or env.startswith('lon'))
I am running the above playbook, when the package=abc and env=PA_, its running. But when env=lon, it is giving error:
fatal: [lonxxx.abc.com]: FAILED! =>
{
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'lonxxx'\n\nThe error appears to be in '/home/dbrun/dbRunPlaybooks/deploy_application.yml': line 25, 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: Deploy Services on \"{{ env }}"\"\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"
}
I tried giving the when condition in below manner:
when: >
(package == "abc") and
(env.startswith('PA_')) or (env.startswith('lon'))
But giving the same error.
Please help.

jinja variable substitution inside blockinfile module

I'm looking to use variables inside blockinfile block and so I made this playbook:
- name: New user
hosts: all
gather_facts: false
become: yes
become_user: root
vars:
nome_utente: pippo
dominio: pluto.it
gruppo: root
tasks:
- name: Add new user
blockinfile:
dest: /root/ansible/users.yml
backup: yes
block: |
'{{ nome_utente }}'#'{{ dominio }}':
gruppo: '{{ gruppo }}'
but I get the following error:
ERROR! Syntax Error while loading YAML.
found character that cannot start any token
The error appears to be in '/home/francesco/test.yml': line 16, column 27, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
block: |
'{{ nome_utente }}'#'{{ dominio }}':
^ 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 }}"
Sorry but I cannot find in any documentation if blockinfile supports jinja templating inside block module.
Do you have any ideas?
The indentation of the block is wrong. See examples and fix it
- name: Add new user
blockinfile:
dest: /root/ansible/users.yml
backup: yes
block: |
'{{ nome_utente }}'#'{{ dominio }}':
gruppo: '{{ gruppo }}'
See Popular Editors that support auto-indentation and syntax highlighting.

Ansible: with_sequence variable start and end

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'

Load Nested Files With host_group_vars Plugin From Custom Locations

I am trying to create ansible role to generate kubernetes deployment with ansible. I want all customization to be stored in var files and be loaded automatically during group_vars and host_vars loading. I end up with following nested structure of files:
group_vars/my_group.yml:
applications:
application_foo: "{{ lookup('template', inventory_dir + '/applications/application_foo.yml') | from_yaml }}"
applications/application_foo.yml:
deployments:
application_foo:
deployment:
{{ lookup('template', inventory_dir + '/deployment_vars/deployment_foo.yml') | to_nice_yaml | indent(6)}}
replicas: 1
deployment_vars/deployment_foo.yml:
containers:
conteiner_bar:
container:
{{ lookup('template',inventory_dir + '/container_vars/container_bar.yml') | to_nice_yaml | indent(6) }}
container_baz:
container:
{{ lookup('template',inventory_dir + '/container_vars/container_baz.yml') | to_nice_yaml | indent(6) }}
container_vars/container_bar.yml:
container_vars/container_baz.yml:
image_url: "https://example.com/image_bar"
cpu_requests: "1"
memory_requests: "512Mi"
cpu_limit: "2"
memory_limit: "1024Mi"
readinessProbe:
exec:
command:
- "sh"
- "-c"
- "true"
playbooks/test-playbook.yml:
- hosts: my_group
gather_facts: False
tasks:
- debug:
msg: "{{ applications['application_foo']['deployments']['application_foo']['deployment']['containers']['container_bar']['cpu_requests'] }}"
delegate_to: localhost
When I run playbook it complains that deployment var is of str type and therefore can't have children objects:
fatal: [localhost]: FAILED! => {
"msg": "The task includes an option with an undefined variable. The error was: 'str object' has no attribute 'containers'\n\nThe error appears to have been in '/tmp/so_question/playbooks/test-playbook.yml': line 4, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - debug:\n ^ here\n"
}
I want layers to be reusable for cases where container or deployment are required by another application so don't want to put everything in one file.
Any suggestions how to fix this issue or how to achieve same nested loading in other way?
UPD: when I cut string in playbook to end on deployment (like this msg: "{{ applications['application_foo']['deployments']['application_foo']['deployment'] }}") it gives following line which after newline substitution does not look like valid yaml:
containers:
conteiner_bar:
container:
\"image_url: \\\"https://example.com/image_bar\\\"\
cpu_requests: \\\"1\\\"\
memory_requests:\\
\\ \\\"512Mi\\\"\
cpu_limit: \\\"2\\\"\
memory_limit: \\\"1024Mi\\\"\
readinessProbe:\
exec:\
\\
\\ command:\
- \\\"sh\\\"\
- \\\"-c\\\"\
- \\\"true\\\"\
\"
container_baz:
container:
\"image_url: \\\"https://example.com/image_bar\\\"\
cpu_requests: \\\"1\\\"\
memory_requests:\\
\\ \\\"512Mi\\\"\
cpu_limit: \\\"2\\\"\
memory_limit: \\\"1024Mi\\\"\
readinessProbe:\
exec:\
\\
\\ command:\
- \\\"sh\\\"\
- \\\"-c\\\"\
- \\\"true\\\"\
\"
I wondering why indent filter does not indents all lines. Am I using it correctly?
Ended up with following workaround: Moved all files containing defaults to group_vars/all to make them loaded automatically and used vars lookup for nesting:
$ find group_vars/
group_vars/
group_vars/all
group_vars/all/10_container_bar.yml
group_vars/all/20_deployment_foo.yml
group_vars/all/30_application_foo.yml
group_vars/all/10_container_baz.yml
group_vars/my_group.yml
group_vars/my_group.yml:
applications:
application_foo: "{{ lookup('vars', 'defaults_application_application_foo') }}"
group_vars/all/30_application_foo.yml:
defaults_application_application_foo:
deployments:
application_foo:
deployment: "{{ lookup('vars', 'defaults_deployment_deployment_foo') }}"
replicas: 1
And so on...
Still not clear why template thing didn't work. Leaving this question open.

Ansible fileinline not working with loop

I am trying to add or edit multiple lines in a file using lineinfile but not working. I am using below code with no luck Ref: ansible: lineinfile for several lines?
# vim /etc/ansible/playbook/test-play.yml
- hosts: tst.wizvision.com
tasks:
- name: change of line
lineinfile:
dest: /root/test.txt
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
backrefs: yes
with_items:
- { regexp: '^# line one', line: 'NEW LINE ONE' }
- { regexp: '^# line two', line: 'NEW LINE TWO' }
Ansible Error:
# ansible-playbook test-2.yml
TASK [change of line] **********************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'item' is undefined\n\nThe error appears to have been in '/etc/ansible/playbook/test-2.yml': line 3, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: change of line\n ^ here\n"}
Your with_items is not indented correctly within the task.
with_items should be at the level of the module, not as a parameter to the module itself. In your case, you are passing with_items as a parameter to lineinfile module, and ansible is complaining that there is no parameter as with_items for lineinfile module.
Your task should look something like this -
tasks:
- name: change of line
lineinfile:
dest: /root/test.txt
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
backrefs: yes
with_items:
- { regexp: '^# line one', line: 'NEW LINE ONE' }
- { regexp: '^# line two', line: 'NEW LINE TWO' }

Resources