Add support for Infoblox NIOS (#35097)

* WIP: initial commit

* update documentation in modules

* fix up sanity check issues

* add unit tests for nios api

* fix up sanity check failures

* fix up EXAMPLES in modules

* mock infoblox_client.connector

* remove unsupported assert statement
This commit is contained in:
Peter Sprygada 2018-01-22 09:25:13 -05:00 committed by John R Barker
commit 8d775a332e
13 changed files with 1412 additions and 0 deletions

View file

@ -0,0 +1,131 @@
#!/usr/bin/python
# Copyright (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: nios_dns_view
version_added: "2.5"
author: "Peter Sprygada (@privateip)"
short_description: Configure Infoblox NIOS DNS views
description:
- Adds and/or removes instances of DNS view objects from
Infoblox NIOS servers. This module manages NIOS C(view) objects
using the Infoblox WAPI interface over REST.
requirements:
- infoblox_client
extends_documentation_fragment: nios
options:
name:
description:
- Specifies the name of the DNS view to add and/or remove from the
system configuration based on the setting of the C(state) argument.
required: true
aliases:
- view
network_view:
description:
- Specifies the name of the network view to assign the configured
DNS view to. The network view must already be configured on the
target system.
required: true
default: default
extattrs:
description:
- Allows for the configuration of Extensible Attributes on the
instance of the object. This argument accepts a set of key / value
pairs for configuration.
required: false
comment:
description:
- Configures a text string comment to be associated with the instance
of this object. The provided text string will be configured on the
object instance.
required: false
state:
description:
- Configures the intended state of the instance of the object on
the NIOS server. When this value is set to C(present), the object
is configured on the device and when this value is set to C(absent)
the value is removed (if necessary) from the device.
required: false
default: present
choices:
- present
- absent
'''
EXAMPLES = '''
- name: configure a new dns view instance
nios_dns_view:
name: ansible-dns
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: update the comment for dns view
nios_dns_view:
name: ansible-dns
comment: this is an example comment
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: remove the dns view instance
nios_dns_view:
name: ansible-dns
state: absent
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
'''
RETURN = ''' # '''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.net_tools.nios.api import get_provider_spec, Wapi
def main():
''' Main entry point for module execution
'''
ib_spec = dict(
name=dict(required=True, aliases=['view'], ib_req=True),
network_view=dict(default='default', ib_req=True),
extattrs=dict(type='dict'),
comment=dict()
)
argument_spec = dict(
provider=dict(required=True),
state=dict(default='present', choices=['present', 'absent'])
)
argument_spec.update(ib_spec)
argument_spec.update(get_provider_spec())
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
wapi = Wapi(module)
result = wapi.run('view', ib_spec)
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,219 @@
#!/usr/bin/python
# Copyright (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: nios_host_record
version_added: "2.5"
author: "Peter Sprygada (@privateip)"
short_description: Configure Infoblox NIOS host records
description:
- Adds and/or removes instances of host record objects from
Infoblox NIOS servers. This module manages NIOS C(record:host) objects
using the Infoblox WAPI interface over REST.
requirements:
- infoblox_client
extends_documentation_fragment: nios
options:
name:
description:
- Specifies the fully qualified hostname to add or remove from
the system
required: true
default: null
view:
description:
- Sets the DNS view to associate this host record with. The DNS
view must already be configured on the system
required: true
default: default
aliases:
- dns_view
ipv4addrs:
description:
- Configures the IPv4 addresses for this host record. This argument
accepts a list of values (see suboptions)
required: false
default: null
aliases:
- ipv4
suboptions:
ipv4addr:
description:
- Configures the IPv4 address for the host record
required: true
default: null
aliases:
- address
mac:
description:
- Configures the hardware MAC address for the host record
required: false
ipv6addrs:
description:
- Configures the IPv6 addresses for the host record. This argument
accepts a list of values (see options)
required: false
default: null
aliases:
- ipv6
suboptions:
ipv6addr:
description:
- Configures the IPv6 address for the host record
required: true
default: null
aliases:
- address
ttl:
description:
- Configures the TTL to be associated with this host record
required: false
default: null
extattrs:
description:
- Allows for the configuration of Extensible Attributes on the
instance of the object. This argument accepts a set of key / value
pairs for configuration.
required: false
comment:
description:
- Configures a text string comment to be associated with the instance
of this object. The provided text string will be configured on the
object instance.
required: false
state:
description:
- Configures the intended state of the instance of the object on
the NIOS server. When this value is set to C(present), the object
is configured on the device and when this value is set to C(absent)
the value is removed (if necessary) from the device.
required: false
default: present
choices:
- present
- absent
'''
EXAMPLES = '''
- name: configure an ipv4 host record
nios_host_record:
name: host.ansible.com
ipv4:
address: 192.168.10.1
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: add a comment to an existing host record
nios_host_record:
name: host.ansible.com
ipv4:
address: 192.168.10.1
comment: this is a test comment
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: remove a host record from the system
nios_host_record:
name: host.ansible.com
state: absent
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
'''
RETURN = ''' # '''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems
from ansible.module_utils.net_tools.nios.api import get_provider_spec, Wapi
def ipaddr(module, key, filtered_keys=None):
''' Transforms the input value into a struct supported by WAPI
This function will transform the input from the playbook into a struct
that is valid for WAPI in the form of:
{
ipv4addr: <value>,
mac: <value>
}
This function does not validate the values are properly formatted or in
the acceptable range, that is left to WAPI.
'''
filtered_keys = filtered_keys or list()
objects = list()
for item in module.params[key]:
objects.append(dict([(k, v) for k, v in iteritems(item) if v is not None and k not in filtered_keys]))
return objects
def ipv4addrs(module):
return ipaddr(module, 'ipv4addrs', filtered_keys=['address'])
def ipv6addrs(module):
return ipaddr(module, 'ipv6addrs', filtered_keys=['address'])
def main():
''' Main entry point for module execution
'''
ipv4addr_spec = dict(
ipv4addr=dict(required=True, aliases=['address'], ib_req=True),
mac=dict()
)
ipv6addr_spec = dict(
ipv6addr=dict(required=True, aliases=['address'], ib_req=True)
)
ib_spec = dict(
name=dict(required=True, ib_req=True),
view=dict(default='default', aliases=['dns_view'], ib_req=True),
ipv4addrs=dict(type='list', aliases=['ipv4'], elements='dict', options=ipv4addr_spec, transform=ipv4addrs),
ipv6addrs=dict(type='list', aliases=['ipv6'], elements='dict', options=ipv6addr_spec, transform=ipv6addrs),
ttl=dict(type='int'),
extattrs=dict(type='dict'),
comment=dict(),
)
argument_spec = dict(
provider=dict(required=True),
state=dict(default='present', choices=['present', 'absent'])
)
argument_spec.update(ib_spec)
argument_spec.update(get_provider_spec())
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
wapi = Wapi(module)
result = wapi.run('record:host', ib_spec)
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,215 @@
#!/usr/bin/python
# Copyright (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: nios_network
version_added: "2.5"
author: "Peter Sprygada (@privateip)"
short_description: Configure Infoblox NIOS network object
description:
- Adds and/or removes instances of network objects from
Infoblox NIOS servers. This module manages NIOS C(network) objects
using the Infoblox WAPI interface over REST.
requirements:
- infoblox_client
extends_documentation_fragment: nios
options:
network:
description:
- Specifies the network to add or remove from the system. The value
should use CIDR notation.
required: true
default: null
aliases:
- name
- cidr
network_view:
description:
- Configures the name of the network view to associate with this
configured instance.
required: true
default: default
options:
description:
- Configures the set of DHCP options to be included as part of
the configured network instance. This argument accepts a list
of values (see suboptions). When configuring suboptions at
least one of C(name) or C(num) must be specified.
required: false
default: null
suboptions:
name:
description:
- The name of the DHCP option to configure
required: false
default: null
num:
description:
- The number of the DHCP option to configure
required: false
value:
description:
- The value of the DHCP option specified by C(name)
required: true
default: null
use_option:
description:
- Only applies to a subset of options (see NIOS API documentation)
required: false
type: bool
default: true
vendor_class:
description:
- The name of the space this DHCP option is associated to
required: false
default: DHCP
extattrs:
description:
- Allows for the configuration of Extensible Attributes on the
instance of the object. This argument accepts a set of key / value
pairs for configuration.
required: false
default: null
comment:
description:
- Configures a text string comment to be associated with the instance
of this object. The provided text string will be configured on the
object instance.
required: false
default: null
state:
description:
- Configures the intended state of the instance of the object on
the NIOS server. When this value is set to C(present), the object
is configured on the device and when this value is set to C(absent)
the value is removed (if necessary) from the device.
required: false
default: present
choices:
- present
- absent
'''
EXAMPLES = '''
- name: configure a network
nios_network:
network: 192.168.10.0/24
comment: this is a test comment
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: set dhcp options for a network
nios_network:
network: 192.168.10.0/24
comment: this is a test comment
options:
- name: domain-name
value: ansible.com
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: remove a network
nios_network:
network: 192.168.10.0/24
state: absent
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
'''
RETURN = ''' # '''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems
from ansible.module_utils.net_tools.nios.api import get_provider_spec, Wapi
def options(module):
''' Transforms the module argument into a valid WAPI struct
This function will transform the options argument into a structure that
is a valid WAPI structure in the format of:
{
name: <value>,
num: <value>,
value: <value>,
use_option: <value>,
vendor_class: <value>
}
It will remove any options that are set to None since WAPI will error on
that condition. It will also verify that either `name` or `num` is
set in the structure but does not validate the values are equal.
The remainder of the value validation is performed by WAPI
'''
options = list()
for item in module.params['options']:
opt = dict([(k, v) for k, v in iteritems(item) if v is not None])
if 'name' not in opt and 'num' not in opt:
module.fail_json(msg='one of `name` or `num` is required for option value')
options.append(opt)
return options
def main():
''' Main entry point for module execution
'''
option_spec = dict(
# one of name or num is required; enforced by the function options()
name=dict(),
num=dict(type='int'),
value=dict(required=True),
use_option=dict(type='bool', default=True),
vendor_class=dict(default='DHCP')
)
ib_spec = dict(
network=dict(required=True, aliases=['name', 'cidr'], ib_req=True),
network_view=dict(default='default', ib_req=True),
options=dict(type='list', elements='dict', options=option_spec, transform=options),
extattrs=dict(type='dict'),
comment=dict()
)
argument_spec = dict(
provider=dict(required=True),
state=dict(default='present', choices=['present', 'absent'])
)
argument_spec.update(ib_spec)
argument_spec.update(get_provider_spec())
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
wapi = Wapi(module)
result = wapi.run('network', ib_spec)
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,125 @@
#!/usr/bin/python
# Copyright (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: nios_network_view
version_added: "2.5"
author: "Peter Sprygada (@privateip)"
short_description: Configure Infoblox NIOS network views
description:
- Adds and/or removes instances of network view objects from
Infoblox NIOS servers. This module manages NIOS C(networkview) objects
using the Infoblox WAPI interface over REST.
requirements:
- infoblox_client
extends_documentation_fragment: nios
options:
name:
description:
- Specifies the name of the network view to either add or remove
from the configuration.
required: true
aliases:
- network_view
extattrs:
description:
- Allows for the configuration of Extensible Attributes on the
instance of the object. This argument accepts a set of key / value
pairs for configuration.
required: false
default: null
comment:
description:
- Configures a text string comment to be associated with the instance
of this object. The provided text string will be configured on the
object instance.
required: false
default: null
state:
description:
- Configures the intended state of the instance of the object on
the NIOS server. When this value is set to C(present), the object
is configured on the device and when this value is set to C(absent)
the value is removed (if necessary) from the device.
required: false
default: present
choices:
- present
- absent
'''
EXAMPLES = '''
- name: configure a new network view
nios_network_view:
name: ansible
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: update the comment for network view
nios_network_view:
name: ansible
comment: this is an example comment
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: remove the network view
nios_network_view:
name: ansible
state: absent
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
'''
RETURN = ''' # '''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.net_tools.nios.api import get_provider_spec, Wapi
def main():
''' Main entry point for module execution
'''
ib_spec = dict(
name=dict(required=True, aliases=['network_view'], ib_req=True),
extattrs=dict(type='dict'),
comment=dict(),
)
argument_spec = dict(
provider=dict(required=True),
state=dict(default='present', choices=['present', 'absent'])
)
argument_spec.update(ib_spec)
argument_spec.update(get_provider_spec())
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
wapi = Wapi(module)
result = wapi.run('networkview', ib_spec)
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,162 @@
#!/usr/bin/python
# Copyright (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: nios_zone
version_added: "2.5"
author: "Peter Sprygada (@privateip)"
short_description: Configure Infoblox NIOS DNS zones
description:
- Adds and/or removes instances of DNS zone objects from
Infoblox NIOS servers. This module manages NIOS C(zone_auth) objects
using the Infoblox WAPI interface over REST.
requirements:
- infoblox_client
extends_documentation_fragment: nios
options:
fqdn:
description:
- Specifies the qualified domain name to either add or remove from
the NIOS instance based on the configured C(state) value.
required: true
default: null
aliases:
- name
view:
description:
- Configures the DNS view name for the configured resource. The
specified DNS zone must already exist on the running NIOS instance
prior to configuring zones.
required: true
default: default
aliases:
- dns_view
grid_primary:
description:
- Configures the grid primary servers for this zone.
required: false
suboptions:
name:
description:
- The name of the grid primary server
required: true
default: null
grid_secondaries:
description:
- Configures the grid secondary servers for this zone.
required: false
suboptions:
name:
description:
- The name of the grid secondary server
required: true
extattrs:
description:
- Allows for the configuration of Extensible Attributes on the
instance of the object. This argument accepts a set of key / value
pairs for configuration.
required: false
comment:
description:
- Configures a text string comment to be associated with the instance
of this object. The provided text string will be configured on the
object instance.
required: false
state:
description:
- Configures the intended state of the instance of the object on
the NIOS server. When this value is set to C(present), the object
is configured on the device and when this value is set to C(absent)
the value is removed (if necessary) from the device.
required: false
default: present
choices:
- present
- absent
'''
EXAMPLES = '''
- name: configure a zone on the system
nios_zone:
name: ansible.com
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: update the comment and ext attributes for an existing zone
nios_zone:
name: ansible.com
comment: this is an example comment
extattrs:
Site: west-dc
state: present
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
- name: remove the dns zone
nios_zone:
name: ansible.com
state: absent
provider:
host: "{{ inventory_hostname_short }}"
username: admin
password: admin
'''
RETURN = ''' # '''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.net_tools.nios.api import get_provider_spec, Wapi
def main():
''' Main entry point for module execution
'''
grid_spec = dict(
name=dict(required=True),
)
ib_spec = dict(
fqdn=dict(required=True, aliases=['name'], ib_req=True),
view=dict(default='default', aliases=['dns_view'], ib_req=True),
grid_primary=dict(type='list', elements='dict', options=grid_spec),
grid_secondaries=dict(type='list', elements='dict', options=grid_spec),
extattrs=dict(type='dict'),
comment=dict()
)
argument_spec = dict(
provider=dict(required=True),
state=dict(default='present', choices=['present', 'absent'])
)
argument_spec.update(ib_spec)
argument_spec.update(get_provider_spec())
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
wapi = Wapi(module)
result = wapi.run('zone_auth', ib_spec)
module.exit_json(**result)
if __name__ == '__main__':
main()