From 5d946ec4f2054eb1e204f22a0221546eadff54ef Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Fri, 20 Feb 2015 09:04:00 -0500 Subject: [PATCH] adds cartesian product lookup --- .../runner/lookup_plugins/cartesian.py | 59 +++++++++++++++++++ v2/ansible/plugins/lookup/cartesian.py | 46 +++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 lib/ansible/runner/lookup_plugins/cartesian.py create mode 100644 v2/ansible/plugins/lookup/cartesian.py diff --git a/lib/ansible/runner/lookup_plugins/cartesian.py b/lib/ansible/runner/lookup_plugins/cartesian.py new file mode 100644 index 00000000000..ab7bba0f0f5 --- /dev/null +++ b/lib/ansible/runner/lookup_plugins/cartesian.py @@ -0,0 +1,59 @@ +# (c) 2013, Bradley Young +# +# 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 . + +import ansible.utils as utils +import ansible.errors as errors +from itertools import product + +def flatten(terms): + ret = [] + for term in terms: + if isinstance(term, list): + ret.extend(term) + elif isinstance(term, tuple): + ret.extend(term) + else: + ret.append(term) + return ret + +class LookupModule(object): + """ + Create the cartesian product of lists + [1, 2, 3], [a, b] -> [1, a], [1, b], [2, a], [2, b], [3, a], [3, b] + """ + + def __init__(self, basedir=None, **kwargs): + self.basedir = basedir + + def __lookup_injects(self, terms, inject): + results = [] + for x in terms: + intermediate = utils.listify_lookup_plugin_terms(x, self.basedir, inject) + results.append(intermediate) + return results + + def run(self, terms, inject=None, **kwargs): + + terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) + terms = self.__lookup_injects(terms, inject) + + my_list = terms[:] + if len(my_list) == 0: + raise errors.AnsibleError("with_cartesian requires at least one element in each list") + return [flatten(x) for x in product(*my_list)] + + diff --git a/v2/ansible/plugins/lookup/cartesian.py b/v2/ansible/plugins/lookup/cartesian.py new file mode 100644 index 00000000000..cc74240826a --- /dev/null +++ b/v2/ansible/plugins/lookup/cartesian.py @@ -0,0 +1,46 @@ +# (c) 2013, Bradley Young +# +# 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 . + +from itertools import product + +from ansible.errors import * +from ansible.plugins.lookup import LookupBase +from ansible.utils.listify import listify_lookup_plugin_terms + +class LookupModule(LookupBase): + """ + Create the cartesian product of lists + [1, 2, 3], [a, b] -> [1, a], [1, b], [2, a], [2, b], [3, a], [3, b] + """ + + def __lookup_variabless(self, terms, variables): + results = [] + for x in terms: + intermediate = listify_lookup_plugin_terms(x, variables, loader=self._loader) + results.append(intermediate) + return results + + def run(self, terms, variables=None, **kwargs): + + terms = self.__lookup_variabless(terms, variables) + + my_list = terms[:] + if len(my_list) == 0: + raise errors.AnsibleError("with_cartesian requires at least one element in each list") + + return [self._flatten(x) for x in product(*my_list, fillvalue=None)] +