Passing bash variable from gitlab-ci file as an extra argument to ansible job
I have a following problem. I want to pass resolved IP addresses to this j2 template file:
COMMIT
# NAT table
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 636 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination {{ idm_ips[0] }}
-A PREROUTING -p tcp -m tcp --dport 636 -j DNAT --to-destination {{ idm_ips[1] }}
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
So my variables here are idm_ips[0]
and idm_ips[1]
.
They were set statically inside ansible-vars.yaml
file:
idm_ips:
- "192.168.10.25"
- "192.168.10.42"
Now I have to resolve FQDNs to idm_ips dynamically, so I wrote a simple python script:
#!/usr/bin/env python3
import socket
import json
ldap_dev = 'ldap.organisation.com'
resolved = socket.gethostbyname_ex(ldap_dev)
ips_arr = resolved[2]
idm_ips_json = json.dumps(ips_arr)
print(idm_ips_json)
This array of IPs is in JSON format, because I read on SO that if I want to pass a bash array as an extra argument to ansible job, it has to be JSON. So I did so.
- I tried to pass thees values by storing them inside a
.gitlab-ci.yml
file as a bash variable:
- chmod +x ${CI_PROJECT_DIR}/scripts/resolve_idm_dev.py
- idm_ips=`python3 ${CI_PROJECT_DIR}/scripts/resolve_idm_dev.py`
- And finally pass this variable to ansible as an extra argument:
ansible-playbook ${CI_PROJECT_DIR}/ansible/provision.yml --extra-vars "project_path=${CI_PROJECT_DIR} project_environment=${CI_ENVIRONMENT_NAME} '{"idm_ips": ${idm_ips}}'"
And I am struggling with it, because when I am trying to build my environment, I am getting an error:
fatal: [kibana-development]: FAILED! => changed=false
msg: 'AnsibleUndefinedVariable: ''idm_ips'' is undefined'
What am I doing wrong? Could some good soul point me what to do? Sorry for a fuzzy description.
Solution 1:
First, tell python to escape [
, ]
as they have special meaning in SHELL:
>>> print(json.dumps(socket.gethostbyname_ex("stackoverflow.com")[2]).replace("[","\\[").replace("]","\\]"))
\["151.101.193.69", "151.101.129.69", "151.101.1.69", "151.101.65.69"\]
Second, properly handle the JSON
:
ansible-playbook ${CI_PROJECT_DIR}/ansible/provision.yml \
-e "project_path=${CI_PROJECT_DIR} \
-e project_environment=${CI_ENVIRONMENT_NAME} \
-e '{"idm_ips":' "${idm_ips}"'}'
If this does not work, consider outputting idm_ips_json
to a file and pass it with:
... -e @yourfile. # because working with json in the shell is terrible ..
Note, if you choose to work with your file, the content should be:
{"idm_ips": ["192.X.Z.Y", "192."...]}