summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipe Niero Felisbino <filipenf@gmail.com>2016-08-08 12:55:59 -0300
committerBrian Coca <bcoca@users.noreply.github.com>2016-08-08 11:55:59 -0400
commite54a9d3a514c6fbd0214209a069372af3a2150ed (patch)
tree64a88bc97546c09b7110518aeedc5cfb003592b8
parentf21df311bcc71823865f2274b514d5ba437a7c12 (diff)
downloadansible-e54a9d3a514c6fbd0214209a069372af3a2150ed.tar.gz
Add generic data structures querying (#13684)
* Query lookup plugin * Add license and docstrings * Add python3-ish imports * Change query plugin type from lookup to filter * Switch from dq to jsonpath_rw * Add integration test for query filter * Rename query filter to json_query * Add jsonpath-rw * Rename query filter to json_query * Switch query implementation from jsonpath-rw to jmespath
-rw-r--r--lib/ansible/plugins/filter/json_query.py48
-rw-r--r--test/integration/roles/test_filters/tasks/main.yml16
-rw-r--r--test/integration/roles/test_filters/vars/main.yml14
-rwxr-xr-xtest/utils/shippable/integration.sh2
-rw-r--r--test/utils/shippable/remote-integration.sh3
5 files changed, 76 insertions, 7 deletions
diff --git a/lib/ansible/plugins/filter/json_query.py b/lib/ansible/plugins/filter/json_query.py
new file mode 100644
index 0000000000..479721e9b7
--- /dev/null
+++ b/lib/ansible/plugins/filter/json_query.py
@@ -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
+ }
diff --git a/test/integration/roles/test_filters/tasks/main.yml b/test/integration/roles/test_filters/tasks/main.yml
index 6d75c0d81c..3e500ae604 100644
--- a/test/integration/roles/test_filters/tasks/main.yml
+++ b/test/integration/roles/test_filters/tasks/main.yml
@@ -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
@@ -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:
@@ -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']"
+
diff --git a/test/integration/roles/test_filters/vars/main.yml b/test/integration/roles/test_filters/vars/main.yml
index 133c2b613b..7b9f609c95 100644
--- a/test/integration/roles/test_filters/vars/main.yml
+++ b/test/integration/roles/test_filters/vars/main.yml
@@ -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
diff --git a/test/utils/shippable/integration.sh b/test/utils/shippable/integration.sh
index eea87b465c..c74ba35883 100755
--- a/test/utils/shippable/integration.sh
+++ b/test/utils/shippable/integration.sh
@@ -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
diff --git a/test/utils/shippable/remote-integration.sh b/test/utils/shippable/remote-integration.sh
index 3f7663029a..b3d7b844ef 100644
--- a/test/utils/shippable/remote-integration.sh
+++ b/test/utils/shippable/remote-integration.sh
@@ -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