My First Ansible Jinja2 Filter

This tutorial shows how to create a custom Ansible Jinja2 filter by writing Python transformation logic, wiring it into a FilterModule, and loading it with a playbook. It uses an encryption example to demonstrate end-to-end usage from plugin code to rendered template output.

Coveros Staff

May 23, 2016

Why would I want to make a Jinja2 filter?

While Ansible Modules are the main way you accomplish something in Ansible, Jinja2 Filters are the main way you manipulate data.  The first python code you’ll need to write in ansible is probably because you want to transform some data to send to a module or template.

Where do I start?

First research how to accomplish the task in python.  In my case I might want to encrypt a string, so that it is encrypted on disk and my application can read it in and decrypt it in memory.  Then write the function that takes in at least one parameter, and returns one.

So here is my python code:

from base64 import b64encode
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto import Random

pad = lambda s: s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size)
unpad = lambda s: s[:-ord(s[len(s)-1:])]

def encrypt( inString, key ):
 inString = pad(inString)
 iv = Random.new().read( AES.block_size )
 cipher = AES.new( pad(key), AES.MODE_CBC, iv )
 return b64encode( iv + cipher.encrypt( inString ) )

Add in the Jinja2 glue code

Make sure you have the following at the top:

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from jinja2 import Environment, FileSystemLoader
from ansible import errors

And add the mapping of jinja2 filter name to python function to the bottom:

class FilterModule(object):
 ''' adds encrypt filter '''
 def filters(self):
 return {

# filter map
 'encrypt': encrypt

 }

Next save the plugin to a playbook to test it

From the developing plugins page, you can put this .py file in either /usr/share/ansible/plugins/filter_plugins/ or in a filter_plugins/ directory relative to your playbook.

Example Playbook:

Simply use the template module so you can use the custom filter in many ways:

- name: Render Testing Template
  template:
    src: test.j2
    dest: /tmp/test

Example Template:

{{ “Small string” | encrypt(“mypass”) }}
{{ “hello my name is simon, and I like to do drawlings” | encrypt(“mypass”) }}

Result:

y7Ka8/5mK0Xuzd29TAEv4SyAEX8BVkaMN75Z1CjNQso=
YouAtLEWaYlcJbkocbXpqZGmm8OakSiDV11V+Rm/a7vtfmQKw+CbDax25KGpN9ZSMztn2f/gPXkMDFA+tbCuCkFyLQleRauh8wXzZ4Jf10s=

 

Coveros Staff

Coveros Staff

This post represents the collective insights of the Coveros team. Our staff consists of software experts who bring deep experience in secure agile development, DevOps, testing, and software quality. Over the past 20 years, Coveros has trained more than 30,000 professionals and worked with half of the Fortune 100 companies on mission-critical software development challenges. We draw on this extensive experience to share practical insights, proven strategies, and real-world solutions that help organizations build better software faster and more securely.