Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generic data structures querying #13684

Merged
merged 10 commits into from
Aug 8, 2016
48 changes: 48 additions & 0 deletions lib/ansible/plugins/filter/json_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# (c) 2015, Filipe Niero Felisbino <filipenf@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.

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

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.utils.listify import listify_lookup_plugin_terms

try:
import jmespath
HAS_LIB = True
except ImportError:
HAS_LIB = False


def json_query(data, expr):
'''Query data using jmespath query language ( http://jmespath.org ). Example:
- debug: msg="{{ instance | json_query(tagged_instances[*].block_device_mapping.*.volume_id') }}"
'''
if not HAS_LIB:
raise AnsibleError('You need to install "jmespath" prior to running '
'json_query filter')

return jmespath.search(expr, data)

class FilterModule(object):
''' Query filter '''

def filters(self):
return {
'json_query': json_query
}
16 changes: 11 additions & 5 deletions test/integration/roles/test_filters/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
register: diff_result_9851

- name: 9851 - verify generated file matches known good
assert:
that:
assert:
that:
- 'diff_result_9851.stdout == ""'

- name: fill in a basic template
Expand All @@ -56,9 +56,9 @@
register: diff_result

- name: verify templated file matches known good
assert:
that:
- 'diff_result.stdout == ""'
assert:
that:
- 'diff_result.stdout == ""'

- name: Verify human_readable
assert:
Expand All @@ -77,3 +77,9 @@
- "31 == ['x','y']|map('extract',{'x':42,'y':31})|list|last"
- "'local' == ['localhost']|map('extract',hostvars,'ansible_connection')|list|first"
- "'local' == ['localhost']|map('extract',hostvars,['ansible_connection'])|list|first"

- name: Test json_query filter
assert:
that:
- "users | json_query('[*].hosts[].host') == ['host_a', 'host_b', 'host_c', 'host_d']"

14 changes: 13 additions & 1 deletion test/integration/roles/test_filters/vars/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
some_structure:
- "this is a list element"
-
-
this: "is a hash element in a list"
warp: 9
where: endor

users:
- name: steve
hosts:
- host: host_a
password: abc
- host: host_b
- name: bill
hosts:
- host: host_c
password: default
- host: host_d
2 changes: 2 additions & 0 deletions test/utils/shippable/integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ container_id=$(docker run -d \

show_environment

docker exec "${container_id}" pip install jmespath

if [ "${copy_source}" ]; then
docker exec "${container_id}" cp -a "${test_shared_dir}" "${test_ansible_dir}"
fi
Expand Down
3 changes: 2 additions & 1 deletion test/utils/shippable/remote-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pkg install -y \
# TODO: bootstrap.sh should install these
pip install \
junit-xml \
virtualenv
virtualenv \
jmespath

# FIXME: tests assume bash is in /bin/bash
if [ ! -f /bin/bash ]; then
Expand Down