How to use salt to test out jinja functionality? - command-line

I am looking for a way to test if salt would render a jinja template the way I expect it to.
If I have a file template.sls containing:
{% for usr in ['moe','larry','curly'] %}
{{ usr }}:
user.present
{% endfor %}
Can I run a salt command that will show me the rendered template?
NB: I understand that what's happening is Jinja doing the rendering, and I can template it in python. But I want to ensure that I am using the Jinja version used by salt. AFAIK salt embeds the jinja engine.
An example of what I am looking for is a salt command that would function similarly to the following ansible command:
The following was taken from accepted answer to: How can I test jinja2 templates in ansible?
3_Ansible (using --check)
Create test playbook jinja2test.yml:
---
- hosts: 127.0.0.1
tasks:
- name: Test jinja2template
template: src=test.j2 dest=test.conf
and run it:
ansible-playbook jinja2test.yml --check --diff --connection=local
sample output:
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [Test jinja2template] ***************************************************
--- before: test.conf
+++ after: /Users/user/ansible/test.j2
## -0,0 +1,4 ##
+Mike
+Smith
+Klara
+Alex
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0

In order to display the resulting SLS you can use the slsutil.renderer
It's quite easy, and should do the trick.
In my case I'm using it like this:
salt 'test01' slsutil.renderer salt://blabla/test.sls 'jinja|yaml'

Best and simplest way is to use state.show_sls as said here
Please check the official doc here
For your specific case that would be something along this :
salt "your_minion" state.show_sls template.sls

Related

Airflow to pass config from UI manual run

is there any way to pass JSON config from manual DAG run (the one from dag_run.conf['attribute'] to KubernetesPodOperator?
Tried to use the Jinja template on the templated field in YAML, but got an error, dag_run is not defined.
task_parse_raw_data = KubernetesPodOperator(
namespace=NAMESPACE,
image='artifactory/image:tag',
service_account_name='airflow',
cmds=["sh", "/current.sh"],
arguments=[ {{ dag_run.conf['date']}} ],
...)
You need to wrap the Jinja expression in quotes like so:
arguments=[ "{{ dag_run.conf['date'] }}" ]

Ansible IP Adress from Host to Variable and use in Playbook - Save Switch Config with Ansible

I want to save the startup and running config with ansible. My script works but only on one host. I need to change the name from the save file otherwise it will overwrite the old Configuration.
---
- hosts: switches
gather_facts: yes
vars:
ansible_network_os: icx
ansible_become: True
ansible_become_method: enable
tasks:
- name: Backup Config Files
icx_command:
commands:
- copy startup-config tftp 192.168.10.5 Ansible-startup-config.cfg
- copy running-config tftp 192.168.10.5 Ansible-running-config.cfg
Now I want to have the ip address, time and date in the name so that they will not be overwritten when I start the script again.
I think about something like this as filename:
192.168.9.13-2021-04-08-18:25-startup-config.cfg
or an consecutive number
How can I do this?
The rough idea below.
I'm not 100% sure facts gathered on ios populate ansible_default_ipv4. You will have to check that point and find the correct variable if needed. Note also you may have to run explicitly the icx_facts module to get all the info from your device.
You can run the following ad-hoc commands to browse all available facts and choose the correct one if ever:
ansible -i your_inventory some_host -m setup
ansible -i your_inventory some_host -m icx_facts
You can debug the ansible_date_time variable to see if an other key suits your needs better than below to create a time stamp. I reconstructed exactly the pattern in your question.
Of course, you need to gather facts for these vars to be available (gather_facts: true on your play meets that requirement).
And here is the sample task (untested, I don't have an ios device available for that)
- name: Backup Config Files
vars:
ip: "{{ ansible_default_ipv4.address }}"
stamp: "{{ ansible_date_time.date }}-{{ ansible_date_time.hour }}:{{ ansible_date_time.minute }}"
prefix: "{{ ip }}-{{ stamp }}"
icx_command:
commands:
- "copy startup-config tftp 192.168.10.5 {{ prefix }}-startup-config.cfg"
- "copy running-config tftp 192.168.10.5 {{ prefix }}-running-config.cfg"

Using Jinja template "ssh-rsa {{ v1.public_ssh_keys }}" in cloud-config gives a warning "Could not find supported sub-handler for type text/jinja2"

I've started to use cloud-config to initialize my Ubuntu 16.04 VM instances on Cloudstack.
In my cloud-config, I'm trying to use the public key of a key pair created in Cloudstack with this Jinja template :
## template: jinja
#cloud-config
cloud_init_modules:
- users-groups
users:
- default
- name: xyz
ssh-authorized-keys:
- ssh-rsa {{ v1.public_ssh_keys }}
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
I receive the following error message :
2019-07-16 19:27:35,737 - jinja_template.py[WARNING]: Ignoring jinja template for part-001. Could not find supported sub-handler for type text/jinja2
No 'init' modules to run under section 'cloud_init_modules'
The key is however correctly passed in the instance data :
# cloud-init query v1.public_ssh_keys
[
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0EyQVA+A+CnrVBo7psi4XuZIbS6Zxq3JtiJK/wCZoPB3vKdvtDtwYkrFf1gBg4rzLDJiTTbbYZaPDa0IP82jdwSBBTzjJbF9mbeJfG70DbWqgzxzU40/fJibD1GqsEmFGh9jDAyyGLDuYo5o6LEprr3n6WIDbcsIlZFSr648RhpvTT8RmAcBj26/fkLsG2lSsQlNkWelSFj4kTn5FRcEbFb1QwwAwMza4gCqz4x3pmoqB/tSc81YRVDosik972j3+Np7Unz16PBbe6Sri5JYZaT5muS7baY9M87Nu/cOKZkr6kkxpGTHIKv6tW71f/CQVcTLEz9IG55xghAjVq9Kv"
]
I've tried with the package python-jinja2 installed (apt-get install -y python-jinja2) but it doesn't fix my issue.

Ansible passing variables between host contexts

As the title says when I'd like to be able to pass a variable that is registered under one host group to another, but I'm not sure how to do that and I couldn't find anything relevant under the variable documentation http://docs.ansible.com/ansible/playbooks_variables.html
This is a simplified example of what I am trying to see. I have a playbook that calls many different groups and checks where a symlink points. I'd like to be able to report all of the symlink targets to console at the end of the play.
The problem is the registered value is only valid under the host group that it was defined in. Is there a proper way of exporting these variables?
---
- hosts: max_logger
tasks:
- shell: ls -la /home/ubuntu/apps/max-logger/active | awk -F':' '{print $NF}'
register: max_logger_old_active
- hosts: max_data
tasks:
- shell: ls -la /home/ubuntu/apps/max-data/active | awk -F':' '{print $NF}'
register: max_data_old_active
- hosts: "localhost"
tasks:
- debug: >
msg="The old max_logger build is {{ max_logger_old_active.stdout }}
The old max_data build is {{ max_data_old_active.stdout }}"
You don't need to pass anything here (you just need to access). Registered variables are stored as host facts and they are stored in memory for the time the whole playbook is run, so you can access them from all subsequent plays.
This can be achieved using magic variable hostvars.
You need however to refer to a host name, which doesn't necessarily match the host group name (e.g. max_logger) which you posted in the question:
- hosts: "localhost"
tasks:
- debug: >
msg="The old max_logger build is {{ hostvars['max_logger_host'].max_logger_old_active.stdout }}
The old max_data build is {{ hostvars['max_data_host'].max_data_old_active.stdout }}"
You can also write hostvars['max_data_host']['max_data_old_active']['stdout'].

Copy file to ansible host with custom variables substituted

I'm working on an ansible-playbook which should help to generate build agents for a continuous delivery pipeline. Among other issues, I'll need to install an oracle client on such an agent. I want to do something like
- name: "Provide response file"
copy: src=/custom.rsp dest=/opt/oracle
Within the custom.rsp file I've got some variables to be substituted. Normally, one could do it with a separate shell command like this:
- name: "Substitute Vars"
shell: "sed 's|<PARAMETER>|<VALUE>|g' -i /opt/oracle/custom.rsp"
I don't like it, though. There should be a more convinient way to do this. Anybody giving me a hint?
You want to be using a template rather than copying a static file.
Also, when using the copy or template modules, the dest parameter is a full path AND filename, not just a path. So if you want to end up with a copy of custom.rsp in the directory /opt/oracle then you need to do this:
- name: "Provide response file"
template: src=/custom.rsp dest=/opt/oracle/custom.rsp
I'm going to extend Bruce's answer with an example:
This is part of my inventory.yaml:
kafka_stage:
children:
kafka_with_zookeeper_stage:
kafka_only_stage:
vars:
zookeeper_hosts: "kafka-stage01:2181,kafka-stage02:2181,kafka-stage03:2181"
kafka_with_zookeeper_stage:
hosts:
kafka-stage01:
broker_id: 0
kafka-stage02:
broker_id: 1
vars:
services:
kafka:
zookeeper:
This is part of a configuration file:
# The id of the broker. This must be set to a unique integer for each broker.
broker.id={{ broker_id }}
# {{ zookeeper_hosts }}
advertised.listeners=PLAINTEXT://{{ ansible_host }}:9092
# {{ services }}
This command in a playbook:
- name: Copy to Host
ansible.builtin.template:
src: my_configfile.properties
dest: /tmp/hejsan.properties
Gave me this on the remote host kafka-stage02:
# The id of the broker. This must be set to a unique integer for each broker.
broker.id=1
# kafka-stage01:2181,kafka-stage02:2181,kafka-stage03:2181
advertised.listeners=PLAINTEXT://kafka-stage02:9092
# {'kafka': None, 'zookeeper': None}