New Module : aos_blueprint_param as part of network/aos (#21352)

* Add initial version of aos_blueprint_param

* Add a missing hard stop in doc

* Remove type: bool from description
This commit is contained in:
Damien 2017-02-17 17:22:55 -08:00 committed by Peter Sprygada
parent ebd9eca9e1
commit aff83940e2

View file

@ -0,0 +1,378 @@
#!/usr/bin/python
#
# (c) 2017 Apstra Inc, <community@apstra.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/>.
#
ANSIBLE_METADATA = {'status': ['preview'],
'supported_by': 'community',
'version': '1.0'}
DOCUMENTATION = '''
---
module: aos_blueprint_param
author: jeremy@apstra.com (@jeremyschulman)
version_added: "2.3"
short_description: Manage AOS blueprint parameter values
description:
- Apstra AOS Blueprint Parameter module let you manage your Blueprint Parameter easily.
You can create access, define and delete Blueprint Parameter. The list of
Parameters supported is different per Blueprint. The option I(get_param_list)
can help you to access the list of supported Parameters for your blueprint.
This module is idempotent and support the I(check) mode. It's using the AOS REST API.
requirements:
- "aos-pyez >= 0.6.0"
options:
session:
description:
- An existing AOS session as obtained by aos_login module.
required: true
blueprint:
description:
- Blueprint Name or Id as defined in AOS.
required: True
name:
description:
- Name of blueprint parameter, as defined by AOS design template. You can
use the option I(get_param_list) to get the complete list of supported
parameters for your blueprint.
value:
description:
- Blueprint parameter value. This value may be transformed by using the
I(param_map) field; used when the the blueprint parameter requires
an AOS unique ID value.
get_param_list:
description:
- Get the complete list of supported parameters for this blueprint and the
description of those parameters.
state:
description:
- Indicate what is the expected state of the Blueprint Parameter (present or not).
default: present
choices: ['present', 'absent']
param_map:
description:
- Defines the aos-pyez collection that will is used to map the user-defined
item name into the AOS unique ID value. For example, if the caller
provides an IP address pool I(param_value) called "Server-IpAddrs", then
the aos-pyez collection is 'IpPools'. Some I(param_map) are already defined
by default like I(logical_device_maps).
'''
EXAMPLES = '''
- name: Add Logical Device Maps information in a Blueprint
aos_blueprint_param:
session: "{{session_ok}}"
blueprint: "my-blueprint-l2"
name: "logical_device_maps"
value:
spine_1: CumulusVX-Spine-Switch
spine_2: CumulusVX-Spine-Switch
leaf_1: CumulusVX-Leaf-Switch
leaf_2: CumulusVX-Leaf-Switch
leaf_3: CumulusVX-Leaf-Switch
state: present
- name: Access Logical Device Maps information from a Blueprint
aos_blueprint_param:
session: "{{session_ok}}"
blueprint: "my-blueprint-l2"
name: "logical_device_maps"
state: present
- name: Reset Logical Device Maps information in a Blueprint
aos_blueprint_param:
session: "{{session_ok}}"
blueprint: "my-blueprint-l2"
name: "logical_device_maps"
state: absent
- name: Get list of all supported Params for a blueprint
aos_blueprint_param:
session: "{{session_ok}}"
blueprint: "my-blueprint-l2"
get_param_list: yes
register: params_list
- debug: var=params_list
- name: Add Resource Pools information in a Blueprint, by providing a param_map
aos_blueprint_param:
session: "{{session_ok}}"
blueprint: "my-blueprint-l2"
name: "resource_pools"
value:
leaf_loopback_ips: ['Switches-IpAddrs']
spine_loopback_ips: ['Switches-IpAddrs']
spine_leaf_link_ips: ['Switches-IpAddrs']
spine_asns: ['Private-ASN-pool']
leaf_asns: ['Private-ASN-pool']
virtual_network_svi_subnets: ['Servers-IpAddrs']
param_map:
leaf_loopback_ips: IpPools
spine_loopback_ips: IpPools
spine_leaf_link_ips: IpPools
spine_asns: AsnPools
leaf_asns: AsnPools
virtual_network_svi_subnets: IpPools
state: present
'''
RETURNS = '''
blueprint:
description: Name of the Blueprint
returned: always
type: str
sample: Server-IpAddrs
name:
description: Name of the Blueprint Parameter
returned: always
type: str
sample: fcc4ac1c-e249-4fe7-b458-2138bfb44c06
value:
description: Value of the Blueprint Parameter as returned by the AOS Server
returned: always
type: dict
sample: {'...'}
params_list:
description: Value of the Blueprint Parameter as returned by the AOS Server
returned: when I(get_param_list) is defined.
type: dict
sample: {'...'}
'''
import json
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.aos import get_aos_session, find_collection_item, check_aos_version
from ansible.module_utils.pycompat24 import get_exception
try:
import yaml
HAS_YAML = True
except ImportError:
HAS_YAML = False
try:
from apstra.aosom.collection_mapper import CollectionMapper, MultiCollectionMapper
HAS_AOS_PYEZ_MAPPER = True
except ImportError:
HAS_AOS_PYEZ_MAPPER = False
param_map_list = dict(
logical_device_maps='LogicalDeviceMaps',
resource_pools=dict(
spine_asns="AsnPools",
leaf_asns="AsnPools",
virtual_network_svi_subnets="IpPools",
spine_loopback_ips="IpPools",
leaf_loopback_ips="IpPools",
spine_leaf_link_ips="IpPools"
)
)
def get_collection_from_param_map(module, aos):
param_map = None
# Check if param_map is provided
if module.params['param_map'] is not None:
param_map_json = module.params['param_map']
if not HAS_YAML:
module.fail_json(msg="Python library Yaml is mandatory to use 'param_map'")
try:
param_map = yaml.load(param_map_json)
except:
module.fail_json(msg="Unable to parse param_map information")
else:
# search in the param_map_list to find the right one
for key, value in param_map_list.items():
if module.params['name'] == key:
param_map = value
# If param_map is defined, search for a Collection that matches
if param_map:
if isinstance(param_map, dict):
return MultiCollectionMapper(aos, param_map)
else:
return CollectionMapper(getattr(aos, param_map))
return None
def blueprint_param_present(module, aos, blueprint, param, param_value):
margs = module.params
# If param_value is not defined, just return the object
if not param_value:
module.exit_json(changed=False,
blueprint=blueprint.name,
name=param.name,
value=param.value)
# Check if current value is the same or not
elif param.value != param_value:
if not module.check_mode:
try:
param.value = param_value
except:
exc = get_exception()
module.fail_json(msg='unable to write to param %s: %r' %
(margs['name'], exc))
module.exit_json(changed=True,
blueprint=blueprint.name,
name=param.name,
value=param.value)
# If value are already the same, nothing needs to be changed
else:
module.exit_json(changed=False,
blueprint=blueprint.name,
name=param.name,
value=param.value)
def blueprint_param_absent(module, aos, blueprint, param, param_value):
margs = module.params
# Check if current value is the same or not
if param.value != dict():
if not module.check_mode:
try:
param.value = {}
except:
exc = get_exception()
module.fail_json(msg='Unable to write to param %s: %r' % (margs['name'], exc))
module.exit_json(changed=True,
blueprint=blueprint.name,
name=param.name,
value=param.value)
else:
module.exit_json(changed=False,
blueprint=blueprint.name,
name=param.name,
value=param.value)
def blueprint_param(module):
margs = module.params
# --------------------------------------------------------------------
# Get AOS session object based on Session Info
# --------------------------------------------------------------------
try:
aos = get_aos_session(module, margs['session'])
except:
module.fail_json(msg="Unable to login to the AOS server")
# --------------------------------------------------------------------
# Get the blueprint Object based on either name or ID
# --------------------------------------------------------------------
try:
blueprint = find_collection_item(aos.Blueprints,
item_name=margs['blueprint'],
item_id=margs['blueprint'])
except:
module.fail_json(msg="Unable to find the Blueprint based on name or ID, something went wrong")
if blueprint.exists is False:
module.fail_json(msg='Blueprint %s does not exist.\n'
'known blueprints are [%s]'%
(margs['blueprint'],','.join(aos.Blueprints.names)))
# --------------------------------------------------------------------
# If get_param_list is defined, build the list of supported parameters
# and extract info for each
# --------------------------------------------------------------------
if margs['get_param_list']:
params_list = {}
for param in blueprint.params.names:
params_list[param] = blueprint.params[param].info
module.exit_json(changed=False,
blueprint= blueprint.name,
params_list=params_list )
# --------------------------------------------------------------------
# Check Param name, return an error if not supported by this blueprint
# --------------------------------------------------------------------
if margs['name'] in blueprint.params.names:
param = blueprint.params[margs['name']]
else:
module.fail_json(msg='unable to access param %s' % margs['name'] )
# --------------------------------------------------------------------
# Check if param_value needs to be converted to an object
# based on param_map
# --------------------------------------------------------------------
param_value = margs['value']
param_collection = get_collection_from_param_map(module, aos)
# If a collection is find and param_value is defined,
# convert param_value into an object
if param_collection and param_value:
param_value = param_collection.from_label(param_value)
# --------------------------------------------------------------------
# Proceed based on State value
# --------------------------------------------------------------------
if margs['state'] == 'absent':
blueprint_param_absent(module, aos, blueprint, param, param_value)
elif margs['state'] == 'present':
blueprint_param_present(module, aos, blueprint, param, param_value)
def main():
module = AnsibleModule(
argument_spec=dict(
session=dict(required=True, type="dict"),
blueprint=dict(required=True),
get_param_list=dict(required=False, type="bool"),
name=dict(required=False),
value=dict(required=False, type="dict"),
param_map=dict(required=False),
state=dict( choices=['present', 'absent'], default='present')
),
supports_check_mode=True
)
# Check if aos-pyez is present and match the minimum version
check_aos_version(module, '0.6.0')
# aos-pyez availability has been verify already by "check_aos_version"
# but this module requires few more object
if not HAS_AOS_PYEZ_MAPPER:
module.fail_json(msg='unable to load the Mapper library from aos-pyez')
blueprint_param(module)
if __name__ == '__main__':
main()