generating a numeric hash for a string in Ansible - ansible

I need to generate a unique TCP port number for a given string (I need this to mock a response from a server, unique for each string).
I want to use a string parameter as a source for this port number. In other words, I need to generate a numeric hash in a given range (1000-32767) from an arbitrary string.
I can do this in Python with no issues, but I don't know how to do it in Ansible.
Is there any way to generate a stable numeric in range hash from a string in Ansible?
An example of a play:
- hosts: localhost
gather_facts: no
tasks:
- debug: msg="Hash for {{ item }} is {{ item |HELP_ME_HERE }}"
with_items:
- string1
- string_two

Is there any way to generate a stable numeric in range hash from a string in Ansible?
- set_fact:
r: "{{ range(1000, 37272) | random(seed=item) }}"
run_once: yes
loop:
- string
- debug:
msg: "{{ r }}"

Related

ansible how to get last 2 digit of number

I have question about how to convert a digit to string and then get last 2 number using filter
For string, it's easy to use like:
vars:
string_1: 'abcd'
number_1: 1234
For string, it's easy:
"{{ string_1[-2:] }}"
But for number then i have to convert to string first but it failed while templating.
"{{ number_1 | string | [-2:] }}
How can I achieve this in single line code?
Close the conversion in parenthesis. The index has higher precedence compared to the filter. (And index can't be used as a filter, of course).
msg: "{{ (number_1|string)[-2:] }}"
The only difference is that modulus % returns an integer. The tasks
- debug:
msg: "{{ (number_1 % 100)|type_debug }}"
- debug:
msg: "{{ (number_1|string)[-2:]|type_debug }}"
give
"msg": "int"
"msg": "str"
You may use a modulus trick here:
{{ number_1 % 100 }}
The modulus dividing by 100 should yield the final two digits of any number input.

Checking the first digit in a number in ansible playbook

I have an ansible playbook that reads in a vars_file containing usernames and uids
users:
- name: josh
uid: 1201
- name: peter
uid: 1202
- name: paul
uid: 2101
- name: ryan
uid: 2102
I have two host groups in my inventory file, db and web. I want users to be created in db if their uid starts with a 1, and web if it starts with 2.
My playbook so far looks like this
---
- name: users playbook
hosts: all
become: yes
vars_files:
- vars/user_list.yml
tasks:
- name: test debug
debug:
msg: "{{ item.username }}, {{ item.uid }}"
loop: "{{ users }}"
when: '{{ item.uid[0] }} == 1'
But my when conditional throws the error
The error was: error while evaluating conditional ({{ item.uid[0] }} == 1)
Is there a better way of doing this for both conditionals?
Several problems.
First, you are not comparing anything. In the expression '{{ item.uid[0] }} == 1' the last part (i.e. == 1) will be literally treated as a string and written as output. If used in a full jinja2 expression, the comparison must be inside the markers: {{ item.uid[0] == 1 }}
Second, when clauses should not contain any jinja2 markers to expand variables. This is also the case for failed_when and changed_when. See the conditionals doc
Lastly, getting the character with an index will only work if the input is a string and not an int. So you first need to make sure or that by casting it correctly with the string filter. The char you will then get will be itself a string. Comparing it to an integer will always return false. So you either have to write the comparison value as a string (i.e. '1') or cast the extracted car to an integer with the int filter.
This is how I would fix your task:
- name: test debug
debug:
msg: "{{ item.username }}, {{ item.uid }}"
loop: "{{ users }}"
when: (item.uid | string)[0] | int == 1

How to convert multiple lines string to dict in Ansible?

I set a fact in Ansible using environment variables with query('env', 'VARIABLE')
My VARIABLE is multiline string (in YAML format):
device: eth0
bootproto: static
address: 192.168.x.x
netmask: 255.255.255.0
gateway: 192.168.x.x
When I print the VARIABLE with Ansible, I get it as a single string with \n between lines
"msg": ["device: eth0\nbootproto: static\naddress:
192.168.x.x\nnetmask: 255.255.255.0\ngateway: 192.168.x.x"]
Is there a convenient way to convert it into dict? I need to use it later in my task, to load the parameters when configuring a machine's NIC.
I have tried to use the Jinja2 filter - debug: msg="{{ network_settings | from_yaml }}" with no success.
There is an important note in the docs:
The difference between lookup and query is largely that query will always return a list.
So:
either replace query('env', 'VARIABLE') with lookup('env', 'VARIABLE'):
- debug:
msg: "{{ lookup('env', 'VARIABLE') | from_yaml }}"
or process the list accordingly (the contents will be in the first-and-only element):
- debug:
msg: "{{ query('env', 'VARIABLE') | first | from_yaml }}"

Splitting a values as list from a string using ansible filter

How to convert the above string to the list of comma separated strings using ansible filter.I need like this var2 , so that i can loop it and use those values.
Expected:
var2: [arn:aws:sds:ABCDEFGHI123456, arn:aws:sds:HRTYUIOPE89012345]"
Input:
var1:"arn:aws:sds:ABCDEFGHI123456arn:aws:sds:HRTYUIOPE89012345"
thansk!!!
Something like this should work:
- name: play1
hosts: all
vars:
x: "arn:aws:sds:ABCDEFGHI123456arn:aws:sds:HRTYUIOPE89012345"
tasks:
- name: task1
debug:
msg: "arn:{{ item }}"
with_items: "{{ x.split('arn:') }}"

Ansible set_fact array and populate it from in loop

I want to create an array and insert value from the the array IP_TO_DNS to reversed IP address.
The idea is to restructure the IP address given in the argument to be matchable later in my code.
Code
- name: create array reversed
set_fact: reversed_ip=[]
- name: set convert ips from cli to matchable reversed ip
set_fact: reversed_ip='{{ item | regex_replace('^(?P<first_range>\d{1,3})\.(?P<second_range>\d{1,3})\.(?P<third_range>\d{1,3})\.', 'named.\\g<third_range>.\\g<second_range>.\\g<first_range>')}}'
with_items: '{{IP_TO_DNS}}'
- name: Match first block of results in path name
debug: var=item
with_items: '{{reversed_ip}}'
Output
TASK [dns : set convert ips from cli to matchable reversed ip] *****************
ok: [10.1.10.5] => (item=10.1.10.1)
ok: [10.1.10.5] => (item=10.1.10.2)
ok: [10.1.10.5] => (item=10.1.10.3)
TASK [dns : Match first block of results in path name] *************************
ok: [10.1.10.5] => (item=named.10.1.103) => {
"item": "named.10.1.103"
}
It look like my variable is not set as an array and only the first value is populate.
Any ideas ?
This is the one of the ways which I used
vars:
my_new_list: []
tasks:
- name: Get list of elements from list_vars
set_fact:
my_new_list: "{{ my_new_list + [item] }}"
with_items: "{{ list_vars }}"
You are setting the same fact three times and it gets overwritten.
You should register the output:
- name: set convert ips from cli to matchable reversed ip
set_fact: reversed_ip='{{ item | regex_replace('^(?P<first_range>\d{1,3})\.(?P<second_range>\d{1,3})\.(?P<third_range>\d{1,3})\.', 'named.\\g<third_range>.\\g<second_range>.\\g<first_range>')}}'
with_items: '{{IP_TO_DNS}}'
register: reversed_ip_results_list
- name: Match first block of results in path name
debug: var=item.ansible_facts.reversed_ip
with_items: '{{reversed_ip_results_list.results}}'
or if you want a list:
- debug: msg="{{ reversed_ip_results_list.results | map(attribute='ansible_facts.reversed_ip') | list }}"
You can assign the default of reversed_ip as a list and append the item to the list.
- name: set convert ips from cli to matchable reversed ip
set_fact: reversed_ip='{{ reversed_ip |default([]) + [item | regex_replace('^(?P<first_range>\d{1,3})\.(?P<second_range>\d{1,3})\.(?P<third_range>\d{1,3})\.', 'named.\\g<third_range>.\\g<second_range>.\\g<first_range>')] }}'
with_items: "{{ IP_TO_DNS }}"
- name: Match first block of results in path name
debug: var=item
with_items: '{{reversed_ip}}'

Resources