ansible

custom filter is not being recognized with the error "template error while templating string: Could not load"


I am trying to develop Custom Filter Plugin. I have a sample one here. I think Ansible is not recognizing the Python class in filter_plugins directory.

this is the error I am getting now

error "fatal: [localhost]: FAILED! => {"msg": "template error while templating string: Could not load \"a_filter\": 'a_filter'. String: {{ my_text | a_filter }}. Could not load \"a_filter\": 'a_filter'"}

Here is the structure

ansible_dir/
├── filter_plugins
│   └── custom_plugins.py
└── my_playbook.yml

and here is that playbook

---
- hosts: localhost
  connection: local

  vars:
    my_text: "hello world"

  tasks:

    - name: Print a message
      debug:
        msg: "{{ my_text | a_filter }}"

and here is the Python class for that filter

#!/usr/bin/python3
class FilterModule(object):

    def a_filter(self, a_variable):
        a_new_variable = a_variable + ' custom filter is working'
        return a_new_variable

This is a new installed Ubuntu machine with Python 3. I do have Ansible at /usr/bin/ansible and Ansible version is

ansible --version
ansible [core 2.16.3]
  config file = None

Anything I need to set at /etc/ansible/ansible.cfg? This file (ansible.cfg) or ansible directory does not exist in /etc directory right now.

I appreciate any inputs.


Solution

  • You're simply missing a structural part of the code. Your FilterModule class has to implement the filters method which returns a mapping of the filter names defined in your file and the corresponding functions. In you're above case, your custom_plugins.py file should look like:

    class FilterModule(object):
    
        def filters(self):
            return {
                'a_filter': self.a_filter
            }
    
        def a_filter(self, a_variable):
            return a_variable + ' custom filter is working'
    

    To go further, if you keep your filtering method as simple as above, it could easily be made static so the following would do the exact same job:

    def a_filter(a_variable):
        return a_variable + ' custom filter is working'
    
    class FilterModule(object):
    
        def filters(self):
            return {
                'a_filter': a_filter
            }