diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index 06445ddb9e..89be6c7ea4 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -1144,6 +1144,12 @@ files: lib/ansible/plugins/filter/network.py: maintainers: $team_networking labels: networking + lib/ansible/plugins/lookup/nios.py: + maintainers: $team_networking + labels: networking + lib/ansible/plugins/lookup/nios_next_ip.py: + maintainers: $team_networking + labels: networking lib/ansible/plugins/lookup/dig: maintainers: jpmens labels: community diff --git a/lib/ansible/module_utils/net_tools/nios/api.py b/lib/ansible/module_utils/net_tools/nios/api.py index 3429ffc00f..fd1689f011 100644 --- a/lib/ansible/module_utils/net_tools/nios/api.py +++ b/lib/ansible/module_utils/net_tools/nios/api.py @@ -25,9 +25,12 @@ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +import os + from functools import partial from ansible.module_utils.six import iteritems +from ansible.module_utils._text import to_text try: from infoblox_client.connector import Connector @@ -46,7 +49,7 @@ nios_provider_spec = { 'http_pool_connections': dict(type='int', default=10), 'http_pool_maxsize': dict(type='int', default=10), 'max_retries': dict(type='int', default=3), - 'wapi_version': dict(default='1.4'), + 'wapi_version': dict(default='1.4') } @@ -54,12 +57,22 @@ def get_provider_spec(): return {'provider': dict(type='dict', options=nios_provider_spec)} -def get_connector(module): +def get_connector(*args, **kwargs): if not HAS_INFOBLOX_CLIENT: - module.fail_json(msg='infoblox-client is required but does not appear ' - 'to be installed. It can be installed using the ' - 'command `pip install infoblox-client`') - return Connector(module.params['provider']) + raise Exception('infoblox-client is required but does not appear ' + 'to be installed. It can be installed using the ' + 'command `pip install infoblox-client`') + + if not set(kwargs.keys()).issubset(nios_provider_spec.keys()): + raise Exception('invalid or unsupported keyword argument for connector') + + for key in nios_provider_spec.keys(): + if key not in kwargs: + env = ('INFOBLOX_%s' % key).upper() + if env in os.environ: + kwargs[key] = os.environ.get(env) + + return Connector(kwargs) class WapiBase(object): @@ -67,7 +80,12 @@ class WapiBase(object): def __init__(self, module): self.module = module - self.connector = get_connector(module) + + try: + provider = module.params['provider'] or {} + self.connector = get_connector(**provider) + except Exception as exc: + module.fail_json(msg=to_text(exc)) def __getattr__(self, name): try: diff --git a/lib/ansible/plugins/lookup/nios.py b/lib/ansible/plugins/lookup/nios.py new file mode 100644 index 0000000000..5236bef492 --- /dev/null +++ b/lib/ansible/plugins/lookup/nios.py @@ -0,0 +1,111 @@ +# +# Copyright 2018 Red Hat | Ansible +# +# 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 __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = """ +--- +lookup: nios +version_added: "2.5" +short_description: Query Infoblox NIOS objects +description: + - Uses the Infoblox WAPI API to fetch NIOS specified objects. This lookup + supports adding additional keywords to filter the return data and specify + the desired set of returned fields. +requirements: + - infoblox_client +extends_documentation_fragment: nios +options: + _terms: + description: The name of the object to return from NIOS + required: True + return_fields: + description: The list of field names to return for the specified object. + required: False + default: null + filter: + description: a dict object that is used to filter the return objects + required: False + default: null +""" + +EXAMPLES = """ +- name: fetch all networkview objects + set_fact: + networkviews: "{{ lookup('nios', 'networkview', provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}" + +- name: fetch the default dns view + set_fact: + dns_views: "{{ lookup('nios', 'view', filter={'view': 'default'}, provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}" + +# all of the examples below use credentials that are set using env variables +# export INFOBLOX_HOST=nios01 +# export INFOBLOX_USERNAME=admin +# export INFOBLOX_PASSWORD=admin + +- name: fetch all host records and include extended attributes + set_fact: + host_records: "{{ lookup('nios', 'record:host', return_fields=['extattrs', 'name', 'view', 'comment']}) }}" + + +- name: use env variables to pass credentials + set_fact: + networkviews: "{{ lookup('nios', 'networkview') }}" + +- name: get a host record + set_fact: + host: "{{ lookup('nios', 'record:host', filter={'name': 'hostname.ansible.com'}) }} + +- name: get the authoritative zone from a non default dns view + set_fact: + host: "{{ lookup('nios', 'zone_auth', filter={'fqdn': 'ansible.com', 'view': 'ansible-dns'}) }}" +""" + +RETURN = """ +obj_type: + description: + - The object type specified in the terms argument + returned: always + type: complex + contains + obj_field: + - One or more obj_type fields as specified by return_fields argument or + the default set of fields as per the object type +""" + +from ansible.plugins.lookup import LookupBase +from ansible.module_utils.net_tools.nios.api import nios_provider_spec +from ansible.module_utils.net_tools.nios.api import get_connector +from ansible.errors import AnsibleError + + +class LookupModule(LookupBase): + + def run(self, terms, variables=None, **kwargs): + try: + obj_type = terms[0] + except IndexError: + raise AnsibleError('the object_type must be specified') + + return_fields = kwargs.pop('return_fields', None) + filter_data = kwargs.pop('filter', {}) + provider = kwargs.pop('provider', {}) + connector = get_connector(**provider) + return connector.get_object(obj_type, filter_data, return_fields=return_fields) diff --git a/lib/ansible/plugins/lookup/nios_next_ip.py b/lib/ansible/plugins/lookup/nios_next_ip.py new file mode 100644 index 0000000000..adfe1e7a2c --- /dev/null +++ b/lib/ansible/plugins/lookup/nios_next_ip.py @@ -0,0 +1,91 @@ +# +# Copyright 2018 Red Hat | Ansible +# +# 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 __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = """ +--- +lookup: nios_next_ip +version_added: "2.5" +short_description: Return the next available IP address for a network +description: + - Uses the Infoblox WAPI API to return the next available IP addresses + for a given network CIDR +requirements: + - infoblox_client +extends_documentation_fragment: nios +options: + _terms: + description: The CIDR network to retrieve the next addresses from + required: True + num: + description: The number of IP addresses to return + required: false + default: 1 +""" + +EXAMPLES = """ +- name: return next available IP address for network 192.168.10.0/24 + set_fact: + ipaddr: "{{ lookup('nios_next_ip', '192.168.10.0/24', provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}" + +- name: return the next 3 available IP addresses for network 192.168.10.0/24 + set_fact: + ipaddr: "{{ lookup('nios_next_ip', '192.168.10.0/24', num=3, provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}" +""" + +RETURN = """ +_list: + description: + - The list of next IP addresses available + returned: always + type: list +""" + +from ansible.plugins.lookup import LookupBase +from ansible.module_utils.net_tools.nios.api import nios_provider_spec +from ansible.module_utils.net_tools.nios.api import get_connector +from ansible.module_utils._text import to_text +from ansible.errors import AnsibleError + + +class LookupModule(LookupBase): + + def run(self, terms, variables=None, **kwargs): + try: + network = terms[0] + except IndexError: + raise AnsibleError('missing argument in the form of A.B.C.D/E') + + provider = kwargs.pop('provider', {}) + connector = get_connector(**provider) + + network_obj = connector.get_object('network', {'network': network}) + if network_obj is None: + raise AnsibleError('unable to find network object %s' % network) + + num = kwargs.get('num', 1) + + try: + ref = network_obj[0]['_ref'] + avail_ips = connector.call_func('next_available_ip', ref, {'num': num}) + return [avail_ips['ips']] + except Exception as exc: + raise AnsibleError(to_text(exc)) diff --git a/lib/ansible/utils/module_docs_fragments/nios.py b/lib/ansible/utils/module_docs_fragments/nios.py index 0496702f38..ede310199e 100644 --- a/lib/ansible/utils/module_docs_fragments/nios.py +++ b/lib/ansible/utils/module_docs_fragments/nios.py @@ -31,35 +31,49 @@ options: description: - Specifies the DNS host name or address for connecting to the remote instance of NIOS WAPI over REST + - Value can also be specified using C(INFOBLOX_HOST) environment + variable. required: true username: description: - Configures the username to use to authenticate the connection to the remote instance of NIOS. + - Value can also be specified using C(INFOBLOX_USERNAME) environment + variable. password: description: - Specifies the password to use to authenticate the connection to the remote instance of NIOS. + - Value can also be specified using C(INFOBLOX_PASSWORD) environment + variable. default: null ssl_verify: description: - Boolean value to enable or disable verifying SSL certificates + - Value can also be specified using C(INFOBLOX_SSL_VERIFY) environment + variable. required: false default: false http_request_timeout: description: - The amount of time before to wait before receiving a response + - Value can also be specified using C(INFOBLOX_HTTP_REQUEST_TIMEOUT) environment + variable. required: false default: 10 max_retries: description: - Configures the number of attempted retries before the connection is declared usable + - Value can also be specified using C(INFOBLOX_MAX_RETRIES) environment + variable. required: false default: 3 wapi_version: description: - Specifies the version of WAPI to use + - Value can also be specified using C(INFOBLOX_WAP_VERSION) environment + variable. required: false default: 1.4 """