diff options
author | Filipe Niero Felisbino <filipenf@gmail.com> | 2016-08-08 12:55:59 -0300 |
---|---|---|
committer | Brian Coca <bcoca@users.noreply.github.com> | 2016-08-08 11:55:59 -0400 |
commit | e54a9d3a514c6fbd0214209a069372af3a2150ed (patch) | |
tree | 64a88bc97546c09b7110518aeedc5cfb003592b8 | |
parent | f21df311bcc71823865f2274b514d5ba437a7c12 (diff) | |
download | ansible-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.py | 48 | ||||
-rw-r--r-- | test/integration/roles/test_filters/tasks/main.yml | 16 | ||||
-rw-r--r-- | test/integration/roles/test_filters/vars/main.yml | 14 | ||||
-rwxr-xr-x | test/utils/shippable/integration.sh | 2 | ||||
-rw-r--r-- | test/utils/shippable/remote-integration.sh | 3 |
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 |