1# -*- coding: utf-8 -*- 2# (c) 2015, Filipe Niero Felisbino <filipenf@gmail.com> 3# 4# This file is part of Ansible 5# 6# Ansible is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# Ansible is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 18 19from __future__ import (absolute_import, division, print_function) 20__metaclass__ = type 21 22from ansible.errors import AnsibleError, AnsibleFilterError 23 24try: 25 import jmespath 26 HAS_LIB = True 27except ImportError: 28 HAS_LIB = False 29 30 31def json_query(data, expr): 32 '''Query data using jmespath query language ( http://jmespath.org ). Example: 33 - ansible.builtin.debug: msg="{{ instance | json_query(tagged_instances[*].block_device_mapping.*.volume_id') }}" 34 ''' 35 if not HAS_LIB: 36 raise AnsibleError('You need to install "jmespath" prior to running ' 37 'json_query filter') 38 39 # Hack to handle Ansible Unsafe text, AnsibleMapping and AnsibleSequence 40 # See issue: https://github.com/ansible-collections/community.general/issues/320 41 jmespath.functions.REVERSE_TYPES_MAP['string'] = jmespath.functions.REVERSE_TYPES_MAP['string'] + ('AnsibleUnicode', 'AnsibleUnsafeText', ) 42 jmespath.functions.REVERSE_TYPES_MAP['array'] = jmespath.functions.REVERSE_TYPES_MAP['array'] + ('AnsibleSequence', ) 43 jmespath.functions.REVERSE_TYPES_MAP['object'] = jmespath.functions.REVERSE_TYPES_MAP['object'] + ('AnsibleMapping', ) 44 try: 45 return jmespath.search(expr, data) 46 except jmespath.exceptions.JMESPathError as e: 47 raise AnsibleFilterError('JMESPathError in json_query filter plugin:\n%s' % e) 48 except Exception as e: 49 # For older jmespath, we can get ValueError and TypeError without much info. 50 raise AnsibleFilterError('Error in jmespath.search in json_query filter plugin:\n%s' % e) 51 52 53class FilterModule(object): 54 ''' Query filter ''' 55 56 def filters(self): 57 return { 58 'json_query': json_query 59 } 60