Consul-template if else condition - if-statement

I have below consul-template.
{{ range service "mysql_slave.mysql" "any" }}
host_name {{.Node}}
command check_nrpe!check_procs_1
{{end}}
I want to add if my hostname match "database-1" then command "check_procs_1" and others command "check_procs_2"
output
host_name node_server
command check_nrpe!check_procs_2
host_name database-1
command check_nrpe!check_procs_1
host_name webserver
command check_nrpe!check_procs_2

To solve this issue we can use below fix.
{{ range service "mysql_slave.mysql" "any" }}
{{ if eq .Node "database-1" }}
host_name {{.Node}}
command check_nrpe!check_procs_1
{{else}}
host_name {{.Node}}
command check_nrpe!check_procs_2
{{end}}
{{end}}

Related

How to concatinate string with star character Ansible?

I have a list of paths stored in files_path variable.
This is a task where I am trying to concatenate paths from variable and adding the rest of the path using join.
- name: Changing supervisor files path
replace:
path: /etc/supervisor/supervisord.conf
regexp: 'files(.*)'
replace: 'files = /etc/supervisor/conf.d/*.conf {{ supervisor_files_path | join(' ')/shared/supervisor/*.conf }}
notify: restart supervisor
when: files_path is defined
The error I get:
fatal: [127.0.0.1]: FAILED! => {"msg": "template error while templating string: unexpected '*'. String: files = /etc/supervisor/conf.d/*.conf {{ files_path | join(' ')/shared/supervisor/*.conf }}"}
The issue is with the second star in code here: /shared/supervisor/*.conf
I was trying to escape using \* or [*], but getting the same error.
How should I change this?
I would try putting {{ }} around it so it becomes {{ /etc/supervisor/conf.d/*.conf }}. Also don't forget to put " " at the beginning and end of the line.

link task depending on content

I have 3 tasks..
first task checks if a file contains <ip> <hostname> pattern
second task adds a line if the sought after string is not present.
third task corrects the line if it is bad.
the 3 tasks run well independently but I want to run them together somehow linked.
I have the following playbook using as model /etc/hosts.
---
- name: check hosts playbook
hosts: centos
tasks:
- name: check whether a line in the form of '<ip> <hostname>' exists
lineinfile:
path: /var/tmp/hosts
regexp: '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s\w+'
state: absent
check_mode: true
register: line_exists
- name: append_host_file
lineinfile:
path: /var/tmp/hosts
insertafter: '^(127\.0\.0\.1|)(?:\d{1,3}\.){3}\d{1,3}'
line: '{{ ansible_default_ipv4.address }} {{ansible_hostname }}'
backup: yes
when: not line_exists.changed
- name: correct_hosts_file
lineinfile:
path: /var/tmp/hosts
regexp: '^(?!{{ ansible_default_ipv4.address }}\s{{ ansible_hostname }})(?:\d{1,3}\.){3}\d{1,3}\s\w+'
line: '{{ ansible_default_ipv4.address }} {{ansible_hostname }}'
when: line_exists.changed
the issue i have is the correct task is running when the line is correct.. so i need to use some other sort of criteria to prevent it from running when the line in the file is correct...if the line in the file is wrong it work because it replaces it.
It's a common problem with lineinfile, it's not that useful as it looks.
My advice: load file content into variable (- command: cat /etc/hosts), register it (register: old_hosts) than iterate over each line of that variable in a template.
- name: get hosts
command: cat /etc/hosts
register: old_hosts
- name: write hosts
template:
src: hosts.j2
dest: /etc/hosts
hosts.j2:
{% for line in old_hosts.stdout_lines %}
{% if line (....) %}
...
{% endif %}
{% endfor %}

Ansible jinja2 template from json file

I have a json host_names.json file with the structure of
{
"host1": "run on host 1",
"host2": "run on host 2",
"host3": "run on host 3"
}
In the same directory, I have a playbook run.yml
---
- name: Run this
connection: local
tasks:
- name: Template
src: "template.j2"
dest: "/my_dest/my_file.txt
I'd like the template to look like this:
#########
# host1 #
#########
run on host 1
end
#########
# host2 #
#########
run on host 2
end
#########
# host3 #
#########
run on host 3
end
How would my template look for this? This is what I currently have
{% for a, b in host_names %}
###########
# {{ a }} #
###########
{{ b }}
end
{% endfor %}
Got it, was just
{% for a, b in host_names.iteritems %}
##########
# {{a}} #
##########
{{ b }}
end
{% endfor %}

ansible parse text string from stdout

My problem is with ansible and parsing stdout. I need to capture the stdout from an ansible play and parse this output for a specific substring within stdout and save into a var. My specific use case is below
- shell: "vault.sh --keystore EAP_HOME/vault/vault.keystore |
--keystore-password vault22 --alias vault --vault-block |
vb --attribute password --sec-attr 0penS3sam3 --enc-dir |
EAP_HOME/vault/ --iteration 120 --salt 1234abcd"
register: results
become: true
This generates an output with the following line, the goal is to capture the masked key that jboss vault generates and save that in an ansible var so I can use it to configure the standalone.xml template:
vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
I need a way parse this string with possibly regex and save the "MASK-5dOaAVafCSd" substring into an ansible var using set_facts module or any other ansible module.
Currently my code looks like this
#example stdout
results: vault-option name=\"KEYSTORE_PASSWORD\" value=\"MASK-5dOaAVafCSd\"/>
- name: JBOSS_VAULT:define keystore password masked value variable
set_fact:
masked_value: |
"{{ results.stdout |
regex_replace('^.+(MASK-.+?)\\.+','\\\1') }}"
This code is defining masked_value as the results.stdout, not the expected capture group.
You are very close. I advice you to use regex101.com to test regular expressions.
Here is my solution:
---
- hosts: localhost
gather_facts: no
tasks:
- shell: echo 'vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"'
register: results
- set_fact:
myvalue: "{{ results.stdout | regex_search(regexp,'\\1') }}"
vars:
regexp: 'value=\"([^"]+)'
- debug:
var: myvalue
result:
ok: [localhost] => {
"myvalue": [
"MASK-5dOaAVafCSd"
]
}
Update:
regex_search returns a list of found matches, so to get only first one use:
{{ results.stdout | regex_search(regexp,'\\1') | first }}
The above solution worked for me, however I had to do some extra logic to filter shell command output to get to the line which contains following
<vault-option name="KEYSTORE_PASSWORD" value="MASK-6qcNdkIprlA"/>
because vault command output has many lines in it. Once this line is captured, the solution given by Konstantin works just fine. Below is the whole thing that needs to done in one place.
- name: Creating jboss vault
shell: |
{{ baseDir }}/bin/vault.sh -e {{ vaultDir }} -k {{ keystoreURL }} -p {{ keystorePassword }} \
-s {{ keystoreSalt }} -i {{ iterationCount }} -v {{ keystoreAlias }} -b {{ vaultBlock }} \
-a {{ attributeName }} -x {{ attributeValue }}
register: vaultResult
- set_fact:
jbossKeystorePassword: "{{ item | regex_search('value=\"([^\"]+)','\\1') | first }}"
when: item | trim | match('.*KEYSTORE_PASSWORD.*')
with_items:
- "{{ vaultResult.stdout_lines }}"
- debug:
var: jbossKeystorePassword
Be sure to replace all variables with your values in above vault.sh command.

How can escape colon in a string within an Ansible YAML file?

I want to change one line of my code in file /var/www/kibana/config.js during installation from
elasticsearch: "http://"+window.location.hostname+":9200"
to
elasticsearch: "http://192.168.1.200:9200"
Here I tried to use lineinfile to do that as show below
- name: Comment out elasticsearch the config.js to ElasticSearch server
lineinfile:
dest=/var/www/kibana/config.js
backrefs=true
regexp="(elasticsearch.* \"http.*)$"
line="elasticsearch\: \" {{ elasticsearch_URL }}:{{ elasticsearch_port }} \" "
state=present
I have set variables of {{elasticsearch_URL}} and {{elasticsearch_port}} to http://192.168.1.200 and 9200, respectively.
Here is the error message I met:
ERROR: Syntax Error while loading YAML script, /Users/shuoy/devops_workspace/ansible_work/logging-for-openstack/roles/kibana/tasks/Debian.yml
Note: The error may actually appear before this position: line 29, column 25
regexp="(elasticsearch.* \"http.*)$"
line="elasticsearch\: \" {{ elasticsearch_URL }}:{{ elasticsearch_port }} \" "
^
The solution that will work in any case no matter how many nested quotes you might have and without forcing you to add more quotes around the whole thing (which can get tricky to impossible depending on the line you want to write) is to output the colon through a Jinja2 expression, which simply returns the colon as a string:
{{ ":" }}
Or in your complete line:
line="elasticsearch\: \" {{ elasticsearch_URL }}{{ ":" }}{{ elasticsearch_port }} \" "
Credit to this goes to github user drewp.
you need to enclose the entire line in ", where : appears.
lineinfile:
'dest=/var/www/kibana/config.js
backrefs=true
regexp="(elasticsearch.* \"http.*)$"
line="elasticsearch\: \ {{ elasticsearch_URL }}:{{ elasticsearch_port }} \ "
state=present'
See these pages:
Link-1 Link-2 Link-3
Just keep the colon in quotes separately -
regexp="(elasticsearch.* \"http.*)$" line="elasticsearch':' \" {{ elasticsearch_URL }}:{{ elasticsearch_port }} \" "
foo=bar is the more suitable format for a one-line directive, but as you're already spanning several lines with your parameters anyway, just change the = to :, and it won't fuss about having a colon in your string.
- name: Comment out elasticsearch the config.js to ElasticSearch server
lineinfile:
dest: /var/www/kibana/config.js
backrefs: true
regexp: 'elasticsearch.* "http.*$'
line: 'elasticsearch: "{{ elasticsearch_URL }}:{{ elasticsearch_port }}"'
state: present
It’s a string already; you don’t have to (and can’t, as seen here) escape colons inside it.
line="elasticsearch: \" {{ elasticsearch_URL }}:{{ elasticsearch_port }} \" "
What I've found to be working consistently in all cases is a variable. For example, vars/main.yml:
fw_zone_str: 'Error: NAME_CONFLICT: new_zone():'
In tasks/foo.yml:
failed_when: fw_zone_str not in fw_new_zone.stderr