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" - ubuntu-16.04

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.

Related

List all my hetzner server names and their IPv4 addresses - getting error

I'm trying to receive a list of all my server names and their IPs on Hetzner using ansible and hcloud module however I'm receiving the following error;
ERROR! couldn't resolve module/action 'hcloud'. This often indicates a misspelling, missing collection, or incorrect module path.
The error appears to be in '/home/melvmagr/repos/ansible/server-content/server-content.yml': line 8, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
tasks:
- name: List servers
^ here
Here is my YAML file;
---
- name: List Hetzner server names and IP addresses
hosts: servername_example
gather_facts: false
vars:
hcloud_token: "MY_HETZNER_API_TOKEN"
tasks:
- name: List servers
hcloud:
api_token: "MY_HETZNER_API_TOKEN"
state: present
command: server_list
register: server_list
- name: Print server names and IP addresses
debug:
msg: "Server {{ item.name }} has IP address {{ item.public_net.ipv4.ip }}"
loop: "{{ server_list.servers }}"
More info that could prove to be helpful:
❯ ansible --version
ansible [core 2.12.10]
config file = /home/melvmagr/repos/ansible/ansible.cfg
configured module search path = ['/home/melvmagr/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/melvmagr/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0]
jinja version = 2.10.1
libyaml = True
This is my ansible.cfg file;
[defaults]
inventory=./inventories
host_key_checking = False
log_path=/var/tmp/ansible_history
timeout=300
I've also installed the following collections;
ansible-galaxy collection install hetzner.hcloud
❯ ls ~/.ansible/collections/ansible_collections/hetzner/hcloud/
CHANGELOG.rst COPYING FILES.json MANIFEST.json README.md changelogs meta plugins tests
Any help would be greatly appreciated. Thank you!
Managed to solve it by simplifying my playbook the following way;
---
- name: Get server information from Hetzner Cloud
hosts: myservername
gather_facts: false
tasks:
- name: Print server names and IP addresses
debug:
msg: "{{ inventory_hostname }} IP is {{ ansible_ssh_host }}"

ModuleNotFoundError: No module named 'azure.mgmt.network.version' [duplicate]

After upgrading ansible to version 2.10.5 and python3.8.10 my playbook.yml fails with this error.
ModuleNotFoundError: No module named 'azure.mgmt.monitor.version'
fatal: [localhost]: FAILED! => {"attempts": 1, "changed": false, "msg": "Failed to import the required Python library (ansible[azure] (azure >= 2.0.0)) on certrenewplay's Python /usr/bin/python3`
The module is there if I run python3 -c "import azure.mgmt.monitor" and if I run pip3 list I see it installed as azure-mgmt-monitor==2.0.0
The exact part of the playbook code that is erroring is this:
- name: Create _acme-challenge record for zone "{{ env_name_dot }}"
azure_rm_dnsrecordset:
subscription_id: "{{ mgmt_subscription }}"
client_id: "{{ mgmt_vault_azure_client_id }}"
tenant: "{{ mgmt_vault_azure_tenant_id }}"
secret: "{{ mgmt_vault_azure_client_secret }}"
resource_group: "{{ mgmt_rg }}"
relative_name: "_acme-challenge.{{ env_name }}"
zone_name: "{{ dns_zone_name }}.{{ dns_zone_domain }}"
record_type: TXT
state: present
records:
- entry: "{{ cn_challenge_data }}"
time_to_live: 60
when: dns_zone_name != 'activedrop'
register: add_record
retries: 1
delay: 10
until: add_record is succeeded
I'm not sure what I'm doing wrong-can anyone advise please or help me on this please?
Thanks
This same issue happened to me because Ansible now ships with its own version of the Azure collection and it was conflicting with the version I had manually installed in my own playbook using the "ansible-galaxy collection" command.
What I suggest you do is only use the version that ships with Ansible and then install its requirements like so:
pip install -r /usr/lib/python3/dist-packages/ansible_collections/azure/azcollection/requirements-azure.txt
It is easier to setup correctly on a freshly installed system (e.g in Docker) than it is to fix a broken system.
I think that you did not follow the instruction about installing azure collection from https://github.com/ansible-collections/azure
Installing collection itself does not install python dependencies, these are installed using python pip and you need to be sure you are installing them inside the same python (v)env where ansible is installed, or ansible will give you the error that you seen when trying to load the module.
Unfortunately the azure-mgmt-monitor package is bugged, even on 3.0.0 to not properly create a version submodule. Haven't been able to track down exactly where in the code it's busted, but it is and there is a direct import of that submodule in the Ansible Galaxy module causing it to fail. Unfortunately you should use the Azure CLI at this time and forget about using azure_rm

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"

How to use salt to test out jinja functionality?

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

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}