I want to construct the password (ansible_ssh_pass) within the vars section of my playbook from a string passed as an input (pass_var). The problem here is that the actual password should be the first 6 characters from the variable (pass_var). I am not sure how to achieve it. Here is my playbook
- hosts: all
user: "{{username}}"
become: yes
gather_facts: False
vars:
ansible_ssh_pass: <someway to decode string (base64 -d) and get first 6 characters>
I'm running the playbook as:
ansible-playbook test.yml --extra-vars "pass_var=${pass_val} username=${user}"
I also need to do some shell manipulations. For example, my string will be base64 encoded, so I need to decode it as well. Something like: echo ${pass_var} | base64 -d | rev | cut -c1-6
You can use Python-style string slicing in Ansible, so you can just write:
vars:
ansible_ssh_pass: "{{ pass_var[:6] }}"
For example, the following command:
ansible localhost -e pass_var=1234567890 -m debug -a 'msg={{pass_var[:6]}}'
Will output:
localhost | SUCCESS => {
"msg": "123456"
}
If your initial string is base64 encoded, you can use Ansible's b64_decode filter:
ansible_pass: "{{ (pass_var|b64decode)[:6] }}"
And if for some weird reason you need to reverse it, there is a reverse filter:
ansible_pass: "{{ ((pass_var|b64decode)|reverse)[:6] }}"
If we modify my earlier example, we get:
ansible localhost -e pass_var="MTIzNDU2Nzg5MA==" -m debug -a 'msg={{((pass_var|b64decode)|reverse)[:6]}}'
Which produces:
localhost | SUCCESS => {
"msg": "098765"
}
Related
how can I encode a given string using ansible?
I'm trying to do this:
echo -n "mypassword" | sha1sum
Q: "Encode a given string."
A: Use hash filter. For example, the command and the filter
- shell: echo -n "mypassword" | sha1sum
register: result
- debug:
var: result.stdout
- set_fact:
pswd: "{{ 'mypassword' | hash('sha1') }}"
- debug:
var: pswd
give the same results
"result.stdout": "91dfd9ddb4198affc5c194cd8ce6d338fde470e2 -"
"pswd": "91dfd9ddb4198affc5c194cd8ce6d338fde470e2"
Q: "Insert the output string into a file."
A: For example, use the template
shell> cat templates/pswd.j2.txt
pswd: {{ pswd }}
- template:
src: pswd.j2.txt
dest: pswd.txt
give
shell> cat pswd.txt
pswd: 91dfd9ddb4198affc5c194cd8ce6d338fde470e2
How do I get a value from an environment variable, but use a default if the environment variable is unset?
This is an example that does not work
---
- name: a playbook
hosts: all
vars:
build_dir: "{{ lookup('env','BUILD_DIR') | default('builds/1.0.0/LATEST') }}"
tasks:
- debug: msg="{{ build_dir }}"
Running this playbook returns an empty string instead of the default.
$ ansible-playbook build.yml
TASK [debug] ********************
ok: [amber] => {
"msg": ""
}
However, it works as expected to obtain the environment variable.
$ BUILD_DIR=LOL ansible-playbook build.yml
TASK [debug] ****************
ok: [amber] => {
"msg": "LOL"
}
Discovered this that is more concise and easier to read than some other options I have seen
"{{ lookup('env','BUILD_DIR') or 'builds/1.0.0/LATEST' }}"
The last parameter to Jinja's default template built-in function should be true, like this:
vars:
build_dir: "{{ lookup('env','BUILD_DIR')|d('builds/1.0.0/LATEST', true) }}"
Better not to have too many sources of truth, but I always try to set intelligent defaults in defaults/main.yml. I also make frequent use of the default() filter, like this:
db_url : "{{ DB_HOST }}:{{ db_port | default(1521) }}:{{ DB_SVC | default(SID|default('')) }}"
Then a playbook can always overwrite a role's variable with a lookup that defaults to a literal -
vars:
db_port: "{{ lookup('env','db_port')|default('9999') }}"
or with a value dynamically written into a vars_file before the play begins, or into the hosts file or groups file, or on the ansible command-line with --extra-vars, etc.
Look at the variable precedence rules, but be careful not to get too complex if it can be avoided. Flexibility is good, but KISS, else "that way lies madness..."
I have a python script which is returning / print two lists.
test.py
def getHosts():
Pool1=[x.x.x.x, x.x.x.x]
Pool2=[x.x.x.x, x.x.x.x]
Print pool1,pool2
Return pool1,pool2
getHosts()
My playbook looks like:
-task:
name: get the hosts
command: /test.py
register: result
Now, is it possible to fetch out the pool1 and pool2 seperately from the registered variable result ? If yes, please show me an example.
Any help or suggestions will be highly appreciated.
Produce JSON and feed it to Ansible. It will automatically create an appropriate data structure:
---
- hosts: localhost
gather_facts: no
connection: local
tasks:
- command: 'echo { \"Pool1\": \"[x.x.x.x, x.x.x.x]\", \"Pool2\": \"[x.x.x.x, x.x.x.x]\" }'
register: my_output
- set_fact:
my_variable: "{{ my_output.stdout | from_json }}"
- debug:
msg: "Pool1 is {{ my_variable.Pool1 }} and Pool2 is {{ my_variable.Pool2 }}"
Result:
ok: [localhost] => {
"msg": "Pool1 is [x.x.x.x, x.x.x.x] and Pool2 is [x.x.x.x, x.x.x.x]"
}
Depending on how you later use the variable, you might/might not need to from_json filter (see this).
I have an argument that is being passed in the form of foobar-a
ansible-playbook test.yml -e "argument=foobar-a"
- name: whatever
hosts: whatever
tasks:
- name: echo
shell: echo {{ argument }}
#should return foobar-b
I need to manipulate that information to be in the form of foobar-b What is the Ansible way of doing this?
In Chef I would just use ruby gsub to do this
argument.gsub!('-a', '-b')
You should use regex_replace filter, like in the playbook below.
- name: whatever
hosts: whatever
tasks:
- name: echo
shell: echo {{ argument | regex_replace('-a','-b') }}
See filters documentation
Using ansible, I need to put a list of hosts in line in a file like so:
["127.0.0.1", "127.0.0.2", "127.0.0.3"]
But whenever I achieve this format, ansible interprets it as a list and the content of the file is this pythonic version:
['127.0.0.1', '127.0.0.2', '127.0.0.3']
Here's my attempts to get it out thus far:
---
- hosts: all
gather_facts: False
tasks:
- set_fact:
myhosts:
- 127.0.0.1
- 127.0.0.2
- 127.0.0.3
# This comes out as a list, I need a string
- set_fact:
var: "[ \"{{ myhosts | join('\", \"')}}\" ]"
- debug: var=var
# This comes out as a string, but I need no underscore on it
- set_fact:
var: "_[ \"{{ myhosts | join('\", \"')}}\" ]"
- debug: var=var
# This also comes out as a list
- set_fact:
var: >
[ "{{ myhosts | join('", "')}}" ]
- debug: var=var
# Also parsed as a list
- set_fact:
var: "{{ myhosts | to_json }}"
- debug: var=var
# ansible-playbook -i "localhost," this_file.yml
There are some filters that prevent Ansible template engine from doing string evaluation.
This list of filters is stored in STRING_TYPE_FILTERS setting.
In Ansible 2.1 it contains: string, to_json, to_nice_json, to_yaml, ppretty, json.
So, you can do this:
- lineinfile: line="{{ myhosts | to_json }}" dest=output.txt
This will add ["127.0.0.1", "127.0.0.2", "127.0.0.3"] line to the file.
And don't believe debug's output when dealing with exact string formatting.
Always use copy: content="{{ string_output_to_test | string }}" dest=test.txt and check file contents to be sure.
debug: var=myvar will always template with evaluation, so your string will always be printed as a list.
debug: msg="{{ myvar | string }}" will print myvar as JSON encoded string.