Skip to content

Instantly share code, notes, and snippets.

@KyleJamesWalker
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KyleJamesWalker/df1d638bb5a26f6ec928 to your computer and use it in GitHub Desktop.
Save KyleJamesWalker/df1d638bb5a26f6ec928 to your computer and use it in GitHub Desktop.

Very quick with_dict_subelements lookup plugin. This is a cross between with_dict and with_subelements The plugin takes a list of two values, First a dictionary, a string with the path in the dictionary to expand (expects a list).

Run the playbook to test with: ansible-playbook -i localhost, playbook.yml

Note: This was thrown togehter very quickly, I'll hopfully have some time to expand this plugin with proper documention and error handling.

'''
Kyle James Walker <KyleJamesWalker@gmail.com>
This file is a lookup plugin for 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/>.
'''
import traceback
from ansible.utils import listify_lookup_plugin_terms
from ansible.errors import AnsibleError
def walk_path(root_node, path):
node = root_node
for p in path.split('.'):
node = node[p]
return node
def flatten_dict_with(terms, lookup_path):
ret = []
for key in terms:
value = walk_path(terms[key], lookup_path)
if not isinstance(value, list):
raise AnsibleError("the path %s should point to a list,"
" got '%s'" % (lookup_path, value))
for i in value:
ret.append({'key': key,
'value': i,
'root': terms[key]})
return ret
def flatten_list_with(terms, lookup_path):
ret = []
for idx, val in enumerate(terms):
value = walk_path(val, lookup_path)
if not isinstance(value, list):
raise AnsibleError("the path %s should point to a list,"
" got '%s'" % (lookup_path, value))
for i in value:
ret.append({'index': idx,
'value': i,
'root': terms[idx]})
return ret
class LookupModule(object):
def __init__(self, basedir=None, **kwargs):
self.basedir = basedir
def run(self, terms, inject=None, **kwargs):
try:
terms = listify_lookup_plugin_terms(terms,
self.basedir,
inject)
if not isinstance(terms, dict) and 'path' not in terms:
raise AnsibleError(
"dict_subelements requires a dict with path key"
)
if 'dict' not in terms and 'items' not in terms:
raise AnsibleError(
"dict_path requires a dict with dict or items key"
)
if 'dict' in terms and 'items' in terms:
raise AnsibleError(
"dict_subelements can't have a dict and items key"
)
root_key = 'dict' if 'dict' in terms else 'items'
root_element = listify_lookup_plugin_terms(terms[root_key],
self.basedir,
inject)
path = terms['path']
if not isinstance(root_element, (dict, list)):
raise AnsibleError("Invalid type for dict/list key")
if not isinstance(path, basestring):
raise AnsibleError("Invalid type for path key "
"basestring required")
if root_key is 'dict':
return flatten_dict_with(root_element, path)
else:
return flatten_list_with(root_element, path)
except Exception as e:
problem = "{}\n{}".format(e, traceback.format_exc())
raise AnsibleError(problem)
---
- name: Example Playbook
hosts: localhost
connection: local
vars:
# Using a Dictionary
run_dict:
hello:
more: here
example:
scripts:
- a
- b
world:
more: here
example:
scripts:
- c
- d
# Using a List
run_list:
- name: hello
more: here
example:
scripts:
- a
- b
- name: world
more: here
example:
scripts:
- c
- d
tasks:
- name: Example Dict
# Available: {{item.key/value/root}}
debug: msg={{item.key}}:{{item.value}}
with_dict_subelements:
dict: run_dict
path: example.scripts
- name: Example List
# Available: {{item.index/value/root}}
debug: msg={{item.root.name}}:{{item.value}}
with_dict_subelements:
items: run_list
path: example.scripts
# Shortened Output:
# TASK: [Example Dict] ********************************************************
# "msg": "world:c"
# "msg": "world:d"
# "msg": "hello:a"
# "msg": "hello:b"
#
# TASK: [Example List] ********************************************************
# "msg": "hello:a"
# "msg": "hello:b"
# "msg": "world:c"
# "msg": "world:d"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment