1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

ACI: Change RETURN output as discussed (#35617)

* ACI: Change result output as discussed

* Update all modules to use new aci.exit_json()

* Update output_level spec and docs

* Fix integration tests

* Small PEP8 fix

* Asorted fixes to tests and aci_rest

* More test fixes and support for ANSIBLE_DEBUG

* Fix another PEP8 issues

* Move response handling inside ACI module

* Reform of ACI error handling and error output

* Diff multiline json output

* Fix a few more tests

* Revert aci_bd tests

* Small correction

* UI change: existing->current, original->previous

* UI change: config->sent

* Update all modules with RETURN values

* Fix a few more tests

* Improve docstring and add 'raw' return value

* Fix thinko

* Fix sanity/pep8 issues

* Rewrite unit tests to comply with new design
This commit is contained in:
Dag Wieers 2018-02-03 00:41:56 +01:00 committed by GitHub
parent 685dd5e8b4
commit bee765fa6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 5733 additions and 747 deletions

View file

@ -70,6 +70,7 @@ def aci_argument_spec():
password=dict(type='str', no_log=True), password=dict(type='str', no_log=True),
private_key=dict(type='path', aliases=['cert_key']), # Beware, this is not the same as client_key ! private_key=dict(type='path', aliases=['cert_key']), # Beware, this is not the same as client_key !
certificate_name=dict(type='str', aliases=['cert_name']), # Beware, this is not the same as client_cert ! certificate_name=dict(type='str', aliases=['cert_name']), # Beware, this is not the same as client_cert !
output_level=dict(type='str', choices=['debug', 'info', 'normal']),
timeout=dict(type='int', default=30), timeout=dict(type='int', default=30),
use_proxy=dict(type='bool', default=True), use_proxy=dict(type='bool', default=True),
use_ssl=dict(type='bool', default=True), use_ssl=dict(type='bool', default=True),
@ -116,56 +117,6 @@ URL_MAPPING = dict(
''' '''
def aci_response_error(result):
''' Set error information when found '''
result['error_code'] = 0
result['error_text'] = 'Success'
# Handle possible APIC error information
if result['totalCount'] != '0':
try:
result['error_code'] = result['imdata'][0]['error']['attributes']['code']
result['error_text'] = result['imdata'][0]['error']['attributes']['text']
except (KeyError, IndexError):
pass
def aci_response_json(result, rawoutput):
''' Handle APIC JSON response output '''
try:
result.update(json.loads(rawoutput))
except Exception as e:
# Expose RAW output for troubleshooting
result.update(raw=rawoutput, error_code=-1, error_text="Unable to parse output as JSON, see 'raw' output. %s" % e)
return
# Handle possible APIC error information
aci_response_error(result)
def aci_response_xml(result, rawoutput):
''' Handle APIC XML response output '''
# NOTE: The XML-to-JSON conversion is using the "Cobra" convention
try:
xml = lxml.etree.fromstring(to_bytes(rawoutput))
xmldata = cobra.data(xml)
except Exception as e:
# Expose RAW output for troubleshooting
result.update(raw=rawoutput, error_code=-1, error_text="Unable to parse output as XML, see 'raw' output. %s" % e)
return
# Reformat as ACI does for JSON API output
try:
result.update(imdata=xmldata['imdata']['children'])
except KeyError:
result['imdata'] = dict()
result['totalCount'] = xmldata['imdata']['attributes']['totalCount']
# Handle possible APIC error information
aci_response_error(result)
class ACIModule(object): class ACIModule(object):
def __init__(self, module): def __init__(self, module):
@ -174,9 +125,36 @@ class ACIModule(object):
self.result = dict(changed=False) self.result = dict(changed=False)
self.headers = dict() self.headers = dict()
# error output
self.error = dict(code=None, text=None)
# normal output
self.existing = None
# info output
self.config = dict()
self.original = None
self.proposed = dict()
# debug output
self.filter_string = ''
self.method = None
self.path = None
self.response = None
self.status = None
self.url = None
# aci_rest output
self.imdata = None
self.totalCount = None
# Ensure protocol is set # Ensure protocol is set
self.define_protocol() self.define_protocol()
if self.module._debug:
self.module.warn('Enable debug output because ANSIBLE_DEBUG was set.')
self.params['output_level'] = 'debug'
if self.params['private_key']: if self.params['private_key']:
# Perform signature-based authentication, no need to log on separately # Perform signature-based authentication, no need to log on separately
if not HAS_OPENSSL: if not HAS_OPENSSL:
@ -260,15 +238,15 @@ class ACIModule(object):
# Handle APIC response # Handle APIC response
if auth['status'] != 200: if auth['status'] != 200:
self.result['response'] = auth['msg'] self.response = auth['msg']
self.result['status'] = auth['status'] self.status = auth['status']
try: try:
# APIC error # APIC error
aci_response_json(self.result, auth['body']) self.response_json(auth['body'])
self.module.fail_json(msg='Authentication failed: %(error_code)s %(error_text)s' % self.result, **self.result) self.fail_json(msg='Authentication failed: %(code)s %(text)s' % self.error)
except KeyError: except KeyError:
# Connection error # Connection error
self.module.fail_json(msg='Authentication failed for %(url)s. %(msg)s' % auth) self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % auth)
# Retain cookie for later use # Retain cookie for later use
self.headers['Cookie'] = resp.headers['Set-Cookie'] self.headers['Cookie'] = resp.headers['Set-Cookie']
@ -281,7 +259,7 @@ class ACIModule(object):
# NOTE: ACI documentation incorrectly uses complete URL # NOTE: ACI documentation incorrectly uses complete URL
if path is None: if path is None:
path = self.result['path'] path = self.path
path = '/' + path.lstrip('/') path = '/' + path.lstrip('/')
if payload is None: if payload is None:
@ -305,61 +283,116 @@ class ACIModule(object):
'APIC-Certificate-Fingerprint=fingerprint; ' +\ 'APIC-Certificate-Fingerprint=fingerprint; ' +\
'APIC-Request-Signature=%s' % sig_signature 'APIC-Request-Signature=%s' % sig_signature
def response_json(self, rawoutput):
''' Handle APIC JSON response output '''
try:
jsondata = json.loads(rawoutput)
except Exception as e:
# Expose RAW output for troubleshooting
self.error = dict(code=-1, text="Unable to parse output as JSON, see 'raw' output. %s" % e)
# self.error = dict(code=str(self.status), text="Request failed: %s (see 'raw' output)" % self.response)
self.result['raw'] = rawoutput
return
# Extract JSON API output
try:
self.imdata = jsondata['imdata']
except KeyError:
self.imdata = dict()
self.totalCount = int(jsondata['totalCount'])
# Handle possible APIC error information
self.response_error()
def response_xml(self, rawoutput):
''' Handle APIC XML response output '''
# NOTE: The XML-to-JSON conversion is using the "Cobra" convention
try:
xml = lxml.etree.fromstring(to_bytes(rawoutput))
xmldata = cobra.data(xml)
except Exception as e:
# Expose RAW output for troubleshooting
self.error = dict(code=-1, text="Unable to parse output as XML, see 'raw' output. %s" % e)
# self.error = dict(code=str(self.status), text="Request failed: %s (see 'raw' output)" % self.response)
self.result['raw'] = rawoutput
return
# Reformat as ACI does for JSON API output
try:
self.imdata = xmldata['imdata']['children']
except KeyError:
self.imdata = dict()
self.totalCount = int(xmldata['imdata']['attributes']['totalCount'])
# Handle possible APIC error information
self.response_error()
def response_error(self):
''' Set error information when found '''
# Handle possible APIC error information
if self.totalCount != '0':
try:
self.error = self.imdata[0]['error']['attributes']
except (KeyError, IndexError):
pass
def request(self, path, payload=None): def request(self, path, payload=None):
''' Perform a REST request ''' ''' Perform a REST request '''
# Ensure method is set (only do this once) # Ensure method is set (only do this once)
self.define_method() self.define_method()
self.result['path'] = path self.path = path
if 'port' in self.params and self.params['port'] is not None: if 'port' in self.params and self.params['port'] is not None:
self.result['url'] = '%(protocol)s://%(host)s:%(port)s/' % self.params + path.lstrip('/') self.url = '%(protocol)s://%(host)s:%(port)s/' % self.params + path.lstrip('/')
else: else:
self.result['url'] = '%(protocol)s://%(host)s/' % self.params + path.lstrip('/') self.url = '%(protocol)s://%(host)s/' % self.params + path.lstrip('/')
# Sign and encode request as to APIC's wishes # Sign and encode request as to APIC's wishes
if self.params['private_key'] is not None: if self.params['private_key'] is not None:
self.cert_auth(path=path, payload=payload) self.cert_auth(path=path, payload=payload)
# Perform request # Perform request
resp, info = fetch_url(self.module, self.result['url'], resp, info = fetch_url(self.module, self.url,
data=payload, data=payload,
headers=self.headers, headers=self.headers,
method=self.params['method'].upper(), method=self.params['method'].upper(),
timeout=self.params['timeout'], timeout=self.params['timeout'],
use_proxy=self.params['use_proxy']) use_proxy=self.params['use_proxy'])
self.result['response'] = info['msg'] self.response = info['msg']
self.result['status'] = info['status'] self.status = info['status']
# Handle APIC response # Handle APIC response
if info['status'] != 200: if info['status'] != 200:
try: try:
# APIC error # APIC error
aci_response_json(self.result, info['body']) self.response_json(info['body'])
self.module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % self.result, **self.result) self.fail_json(msg='Request failed: %(code)s %(text)s' % self.error)
except KeyError: except KeyError:
# Connection error # Connection error
self.module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info) self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
aci_response_json(self.result, resp.read()) self.response_json(resp.read())
def query(self, path): def query(self, path):
''' Perform a query with no payload ''' ''' Perform a query with no payload '''
self.result['path'] = path self.path = path
if 'port' in self.params and self.params['port'] is not None: if 'port' in self.params and self.params['port'] is not None:
self.result['url'] = '%(protocol)s://%(host)s:%(port)s/' % self.params + path.lstrip('/') self.url = '%(protocol)s://%(host)s:%(port)s/' % self.params + path.lstrip('/')
else: else:
self.result['url'] = '%(protocol)s://%(host)s/' % self.params + path.lstrip('/') self.url = '%(protocol)s://%(host)s/' % self.params + path.lstrip('/')
# Sign and encode request as to APIC's wishes # Sign and encode request as to APIC's wishes
if self.params['private_key'] is not None: if self.params['private_key'] is not None:
self.cert_auth(path=path, method='GET') self.cert_auth(path=path, method='GET')
# Perform request # Perform request
resp, query = fetch_url(self.module, self.result['url'], resp, query = fetch_url(self.module, self.url,
data=None, data=None,
headers=self.headers, headers=self.headers,
method='GET', method='GET',
@ -368,15 +401,15 @@ class ACIModule(object):
# Handle APIC response # Handle APIC response
if query['status'] != 200: if query['status'] != 200:
self.result['response'] = query['msg'] self.response = query['msg']
self.result['status'] = query['status'] self.status = query['status']
try: try:
# APIC error # APIC error
aci_response_json(self.result, query['body']) self.response_json(query['body'])
self.module.fail_json(msg='Query failed: %(error_code)s %(error_text)s' % self.result, **self.result) self.fail_json(msg='Query failed: %(code)s %(text)s' % self.error)
except KeyError: except KeyError:
# Connection error # Connection error
self.module.fail_json(msg='Query failed for %(url)s. %(msg)s' % query) self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % query)
query = json.loads(resp.read()) query = json.loads(resp.read())
@ -424,12 +457,12 @@ class ACIModule(object):
else: else:
path, filter_string = self._construct_url_1(root_class, child_includes) path, filter_string = self._construct_url_1(root_class, child_includes)
self.result['path'] = path self.path = path
if 'port' in self.params and self.params['port'] is not None: if 'port' in self.params and self.params['port'] is not None:
self.result['url'] = '{0}://{1}:{2}/{3}'.format(self.module.params['protocol'], self.module.params['host'], self.module.params['port'], path) self.url = '{0}://{1}:{2}/{3}'.format(self.module.params['protocol'], self.module.params['host'], self.module.params['port'], path)
else: else:
self.result['url'] = '{0}://{1}/{2}'.format(self.module.params['protocol'], self.module.params['host'], path) self.url = '{0}://{1}/{2}'.format(self.module.params['protocol'], self.module.params['host'], path)
self.result['filter_string'] = filter_string self.filter_string = filter_string
def _construct_url_1(self, obj, child_includes): def _construct_url_1(self, obj, child_includes):
""" """
@ -616,9 +649,9 @@ class ACIModule(object):
This method is used to handle the logic when the modules state is equal to absent. The method only pushes a change if This method is used to handle the logic when the modules state is equal to absent. The method only pushes a change if
the object exists, and if check_mode is False. A successful change will mark the module as changed. the object exists, and if check_mode is False. A successful change will mark the module as changed.
""" """
self.result['proposed'] = {} self.proposed = dict()
if not self.result['existing']: if not self.existing:
return return
elif not self.module.check_mode: elif not self.module.check_mode:
@ -626,31 +659,31 @@ class ACIModule(object):
if self.params['private_key'] is not None: if self.params['private_key'] is not None:
self.cert_auth(method='DELETE') self.cert_auth(method='DELETE')
resp, info = fetch_url(self.module, self.result['url'], resp, info = fetch_url(self.module, self.url,
headers=self.headers, headers=self.headers,
method='DELETE', method='DELETE',
timeout=self.params['timeout'], timeout=self.params['timeout'],
use_proxy=self.params['use_proxy']) use_proxy=self.params['use_proxy'])
self.result['response'] = info['msg'] self.response = info['msg']
self.result['status'] = info['status'] self.status = info['status']
self.result['method'] = 'DELETE' self.method = 'DELETE'
# Handle APIC response # Handle APIC response
if info['status'] == 200: if info['status'] == 200:
self.result['changed'] = True self.result['changed'] = True
aci_response_json(self.result, resp.read()) self.response_json(resp.read())
else: else:
try: try:
# APIC error # APIC error
aci_response_json(self.result, info['body']) self.response_json(info['body'])
self.module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % self.result, **self.result) self.fail_json(msg='Request failed: %(code)s %(text)s' % self.error)
except KeyError: except KeyError:
# Connection error # Connection error
self.module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info) self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
else: else:
self.result['changed'] = True self.result['changed'] = True
self.result['method'] = 'DELETE' self.method = 'DELETE'
def get_diff(self, aci_class): def get_diff(self, aci_class):
""" """
@ -661,9 +694,9 @@ class ACIModule(object):
:param aci_class: Type str. :param aci_class: Type str.
This is the root dictionary key for the MO's configuration body, or the ACI class of the MO. This is the root dictionary key for the MO's configuration body, or the ACI class of the MO.
""" """
proposed_config = self.result['proposed'][aci_class]['attributes'] proposed_config = self.proposed[aci_class]['attributes']
if self.result['existing']: if self.existing:
existing_config = self.result['existing'][0][aci_class]['attributes'] existing_config = self.existing[0][aci_class]['attributes']
config = {} config = {}
# values are strings, so any diff between proposed and existing can be a straight replace # values are strings, so any diff between proposed and existing can be a straight replace
@ -686,9 +719,9 @@ class ACIModule(object):
config = {aci_class: {'attributes': {}, 'children': children}} config = {aci_class: {'attributes': {}, 'children': children}}
else: else:
config = self.result['proposed'] config = self.proposed
self.result['config'] = config self.config = config
@staticmethod @staticmethod
def get_diff_child(child_class, proposed_child, existing_child): def get_diff_child(child_class, proposed_child, existing_child):
@ -725,10 +758,10 @@ class ACIModule(object):
:return: The list of updated child config dictionaries. None is returned if there are no changes to the child :return: The list of updated child config dictionaries. None is returned if there are no changes to the child
configurations. configurations.
""" """
proposed_children = self.result['proposed'][aci_class].get('children') proposed_children = self.proposed[aci_class].get('children')
if proposed_children: if proposed_children:
child_updates = [] child_updates = []
existing_children = self.result['existing'][0][aci_class].get('children', []) existing_children = self.existing[0][aci_class].get('children', [])
# Loop through proposed child configs and compare against existing child configuration # Loop through proposed child configs and compare against existing child configuration
for child in proposed_children: for child in proposed_children:
@ -755,32 +788,32 @@ class ACIModule(object):
that this method can be used to supply the existing configuration when using the get_diff method. The response, status, that this method can be used to supply the existing configuration when using the get_diff method. The response, status,
and existing configuration will be added to the self.result dictionary. and existing configuration will be added to the self.result dictionary.
""" """
uri = self.result['url'] + self.result['filter_string'] uri = self.url + self.filter_string
# Sign and encode request as to APIC's wishes # Sign and encode request as to APIC's wishes
if self.params['private_key'] is not None: if self.params['private_key'] is not None:
self.cert_auth(path=self.result['path'] + self.result['filter_string'], method='GET') self.cert_auth(path=self.path + self.filter_string, method='GET')
resp, info = fetch_url(self.module, uri, resp, info = fetch_url(self.module, uri,
headers=self.headers, headers=self.headers,
method='GET', method='GET',
timeout=self.params['timeout'], timeout=self.params['timeout'],
use_proxy=self.params['use_proxy']) use_proxy=self.params['use_proxy'])
self.result['response'] = info['msg'] self.response = info['msg']
self.result['status'] = info['status'] self.status = info['status']
self.result['method'] = 'GET' self.method = 'GET'
# Handle APIC response # Handle APIC response
if info['status'] == 200: if info['status'] == 200:
self.result['existing'] = json.loads(resp.read())['imdata'] self.existing = json.loads(resp.read())['imdata']
else: else:
try: try:
# APIC error # APIC error
aci_response_json(self.result, info['body']) self.response_json(info['body'])
self.module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % self.result, **self.result) self.fail_json(msg='Request failed: %(code)s %(text)s' % self.error)
except KeyError: except KeyError:
# Connection error # Connection error
self.module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info) self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
@staticmethod @staticmethod
def get_nested_config(proposed_child, existing_children): def get_nested_config(proposed_child, existing_children):
@ -824,7 +857,7 @@ class ACIModule(object):
MOs should have their own module. MOs should have their own module.
""" """
proposed = dict((k, str(v)) for k, v in class_config.items() if v is not None) proposed = dict((k, str(v)) for k, v in class_config.items() if v is not None)
self.result['proposed'] = {aci_class: {'attributes': proposed}} self.proposed = {aci_class: {'attributes': proposed}}
# add child objects to proposed # add child objects to proposed
if child_configs: if child_configs:
@ -843,7 +876,7 @@ class ACIModule(object):
children.append(child) children.append(child)
if children: if children:
self.result['proposed'][aci_class].update(dict(children=children)) self.proposed[aci_class].update(dict(children=children))
def post_config(self): def post_config(self):
""" """
@ -851,36 +884,90 @@ class ACIModule(object):
the object has differences than what exists on the APIC, and if check_mode is False. A successful change will mark the the object has differences than what exists on the APIC, and if check_mode is False. A successful change will mark the
module as changed. module as changed.
""" """
if not self.result['config']: if not self.config:
return return
elif not self.module.check_mode: elif not self.module.check_mode:
# Sign and encode request as to APIC's wishes # Sign and encode request as to APIC's wishes
if self.params['private_key'] is not None: if self.params['private_key'] is not None:
self.cert_auth(method='POST', payload=json.dumps(self.result['config'])) self.cert_auth(method='POST', payload=json.dumps(self.config))
resp, info = fetch_url(self.module, self.result['url'], resp, info = fetch_url(self.module, self.url,
data=json.dumps(self.result['config']), data=json.dumps(self.config),
headers=self.headers, headers=self.headers,
method='POST', method='POST',
timeout=self.params['timeout'], timeout=self.params['timeout'],
use_proxy=self.params['use_proxy']) use_proxy=self.params['use_proxy'])
self.result['response'] = info['msg'] self.response = info['msg']
self.result['status'] = info['status'] self.status = info['status']
self.result['method'] = 'POST' self.method = 'POST'
# Handle APIC response # Handle APIC response
if info['status'] == 200: if info['status'] == 200:
self.result['changed'] = True self.result['changed'] = True
aci_response_json(self.result, resp.read()) self.response_json(resp.read())
else: else:
try: try:
# APIC error # APIC error
aci_response_json(self.result, info['body']) self.response_json(info['body'])
self.module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % self.result, **self.result) self.fail_json(msg='Request failed: %(code)s %(text)s' % self.error)
except KeyError: except KeyError:
# Connection error # Connection error
self.module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info) self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
else: else:
self.result['changed'] = True self.result['changed'] = True
self.result['method'] = 'POST' self.method = 'POST'
def exit_json(self):
if self.params['output_level'] in ('debug', 'info'):
self.result['previous'] = self.existing
# Return the gory details when we need it
if self.params['output_level'] == 'debug':
self.result['filter_string'] = self.filter_string
self.result['method'] = self.method
# self.result['path'] = self.path # Adding 'path' in result causes state: absent in output
self.result['response'] = self.response
self.result['status'] = self.status
self.result['url'] = self.url
self.original = self.existing
if self.params['state'] in ('absent', 'present'):
self.get_existing()
self.result['current'] = self.existing
# if self.module._diff and self.original != self.existing:
# self.result['diff'] = dict(
# before=json.dumps(self.original, sort_keys=True, indent=4),
# after=json.dumps(self.existing, sort_keys=True, indent=4),
# )
if self.params['output_level'] in ('debug', 'info'):
self.result['sent'] = self.config
self.result['proposed'] = self.proposed
self.module.exit_json(**self.result)
def fail_json(self, msg, **kwargs):
# Return error information, if we have it
if self.error['code'] is not None and self.error['text'] is not None:
self.result['error'] = self.error
# Return the gory details when we need it
if self.params['output_level'] == 'debug':
if self.imdata is not None:
self.result['imdata'] = self.imdata
self.result['totalCount'] = self.totalCount
if self.url is not None:
self.result['filter_string'] = self.filter_string
self.result['method'] = self.method
# self.result['path'] = self.path # Adding 'path' in result causes state: absent in output
self.result['response'] = self.response
self.result['status'] = self.status
self.result['url'] = self.url
self.result.update(**kwargs)
self.module.fail_json(msg=msg, **self.result)

View file

@ -124,7 +124,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: '?rsp-prop-include=config-only'
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -234,7 +337,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -89,7 +89,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -167,7 +270,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -116,7 +116,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -213,7 +314,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -87,7 +87,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -155,7 +256,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -56,7 +56,110 @@ extends_documentation_fragment: aci
EXAMPLES = r''' # ''' EXAMPLES = r''' # '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -150,7 +253,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -87,7 +87,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -157,7 +258,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -206,7 +206,110 @@ EXAMPLES = r'''
bd: web_servers bd: web_servers
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -342,7 +445,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -201,7 +201,110 @@ EXAMPLES = r'''
mask: 24 mask: 24
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
SUBNET_CONTROL_MAPPING = dict(nd_ra='nd', no_gw='no-default-gateway', querier_ip='querier', unspecified='') SUBNET_CONTROL_MAPPING = dict(nd_ra='nd', no_gw='no-default-gateway', querier_ip='querier', unspecified='')
@ -327,7 +430,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -47,7 +47,110 @@ extends_documentation_fragment: aci
EXAMPLES = r''' # ''' EXAMPLES = r''' # '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
SUBNET_CONTROL_MAPPING = dict(nd_ra='nd', no_gw='no-default-gateway', querier_ip='querier', unspecified='') SUBNET_CONTROL_MAPPING = dict(nd_ra='nd', no_gw='no-default-gateway', querier_ip='querier', unspecified='')
@ -122,7 +225,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -127,7 +127,49 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# preview:
description: A preview between two snapshots
returned: when state is preview
type: string
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -221,8 +263,8 @@ def main():
aci.post_config() aci.post_config()
elif state == 'preview': elif state == 'preview':
aci.result['url'] = '%(protocol)s://%(host)s/mqapi2/snapshots.diff.xml' % module.params aci.url = '%(protocol)s://%(host)s/mqapi2/snapshots.diff.xml' % module.params
aci.result['filter_string'] = ( aci.filter_string = (
'?s1dn=uni/backupst/snapshots-[uni/fabric/configexp-%(export_policy)s]/snapshot-%(snapshot)s&' '?s1dn=uni/backupst/snapshots-[uni/fabric/configexp-%(export_policy)s]/snapshot-%(snapshot)s&'
's2dn=uni/backupst/snapshots-[uni/fabric/configexp-%(compare_export_policy)s]/snapshot-%(compare_snapshot)s' 's2dn=uni/backupst/snapshots-[uni/fabric/configexp-%(compare_export_policy)s]/snapshot-%(compare_snapshot)s'
) % module.params ) % module.params
@ -230,25 +272,25 @@ def main():
# Generate rollback comparison # Generate rollback comparison
get_preview(aci) get_preview(aci)
module.exit_json(**aci.result) aci.exit_json()
def get_preview(aci): def get_preview(aci):
''' '''
This function is used to generate a preview between two snapshots and add the parsed results to the aci module return data. This function is used to generate a preview between two snapshots and add the parsed results to the aci module return data.
''' '''
uri = aci.result['url'] + aci.result['filter_string'] uri = aci.url + aci.filter_string
resp, info = fetch_url(aci.module, uri, headers=aci.headers, method='GET', timeout=aci.module.params['timeout'], use_proxy=aci.module.params['use_proxy']) resp, info = fetch_url(aci.module, uri, headers=aci.headers, method='GET', timeout=aci.module.params['timeout'], use_proxy=aci.module.params['use_proxy'])
aci.result['response'] = info['msg'] aci.method = 'GET'
aci.result['status'] = info['status'] aci.response = info['msg']
aci.result['method'] = 'GET' aci.status = info['status']
# Handle APIC response # Handle APIC response
if info['status'] == 200: if info['status'] == 200:
xml_to_json(aci, resp.read()) xml_to_json(aci, resp.read())
else: else:
aci.result['apic_response'] = resp.read() aci.result['raw'] = resp.read()
aci.module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % aci.result, **aci.result) aci.fail_json(msg="Request failed: %(code)s %(text)s (see 'raw' output)" % aci.error)
def xml_to_json(aci, response_data): def xml_to_json(aci, response_data):
@ -258,9 +300,9 @@ def xml_to_json(aci, response_data):
if XML_TO_JSON: if XML_TO_JSON:
xml = lxml.etree.fromstring(to_bytes(response_data)) xml = lxml.etree.fromstring(to_bytes(response_data))
xmldata = cobra.data(xml) xmldata = cobra.data(xml)
aci.result['diff'] = xmldata aci.result['preview'] = xmldata
else: else:
aci.result['diff'] = response_data aci.result['preview'] = response_data
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -102,7 +102,110 @@ EXAMPLES = r'''
snapshot: run-2017-08-24T17-20-05 snapshot: run-2017-08-24T17-20-05
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -140,7 +243,7 @@ def main():
if max_count in range(1, 11): if max_count in range(1, 11):
max_count = str(max_count) max_count = str(max_count)
else: else:
module.fail_json(msg='The "max_count" must be a number between 1 and 10') module.fail_json(msg="Parameter 'max_count' must be a number between 1 and 10")
snapshot = module.params['snapshot'] snapshot = module.params['snapshot']
if snapshot is not None and not snapshot.startswith('run-'): if snapshot is not None and not snapshot.startswith('run-'):
snapshot = 'run-' + snapshot snapshot = 'run-' + snapshot
@ -209,13 +312,13 @@ def main():
), ),
) )
if aci.result['existing']: if aci.existing:
aci.get_diff('configSnapshot') aci.get_diff('configSnapshot')
# Mark Snapshot for Deletion # Mark Snapshot for Deletion
aci.post_config() aci.post_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -81,7 +81,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -162,7 +263,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -127,7 +127,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -233,7 +334,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -74,7 +74,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -169,7 +270,7 @@ def main():
# Remove subject_filter used to build URL from module.params # Remove subject_filter used to build URL from module.params
module.params.pop('subject_filter') module.params.pop('subject_filter')
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -126,7 +126,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -254,7 +357,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -66,7 +66,110 @@ extends_documentation_fragment: aci
EXAMPLES = r''' # ''' EXAMPLES = r''' # '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -196,7 +299,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -125,7 +125,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -231,7 +334,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -91,7 +91,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -185,7 +286,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -124,7 +124,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -303,7 +404,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -159,7 +159,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -255,7 +356,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -62,7 +62,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -131,7 +232,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -69,7 +69,110 @@ extends_documentation_fragment: aci
EXAMPLES = r''' # ''' EXAMPLES = r''' # '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -169,7 +272,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -102,7 +102,110 @@ extends_documentation_fragment: aci
EXAMPLES = r''' # ''' EXAMPLES = r''' # '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -240,7 +343,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -88,7 +88,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -157,7 +258,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -114,7 +114,110 @@ EXAMPLES = r'''
descr: "{{ descr }}" descr: "{{ descr }}"
''' '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -250,7 +353,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -60,7 +60,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
@ -131,7 +232,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -57,7 +57,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -121,7 +222,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -66,7 +66,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -140,7 +241,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -156,7 +156,110 @@ EXAMPLES = r'''
state: absent state: absent
''' '''
RETURN = ''' # ''' RETURN = '''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -389,7 +492,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -76,7 +76,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -134,7 +235,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -65,7 +65,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -132,7 +233,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -57,7 +57,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -121,7 +222,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -112,7 +112,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -209,7 +310,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -56,7 +56,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -122,7 +223,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -73,7 +73,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -138,7 +241,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -65,7 +65,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -136,7 +237,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -246,8 +246,8 @@ try:
except: except:
HAS_YAML = False HAS_YAML = False
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec, aci_response_json, aci_response_xml
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.urls import fetch_url from ansible.module_utils.urls import fetch_url
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
@ -267,34 +267,35 @@ def update_qsl(url, params):
return url + '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()]) return url + '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()])
def aci_changed(d): class ACIRESTModule(ACIModule):
def changed(self, d):
''' Check ACI response for changes ''' ''' Check ACI response for changes '''
if isinstance(d, dict): if isinstance(d, dict):
for k, v in d.items(): for k, v in d.items():
if k == 'status' and v in ('created', 'modified', 'deleted'): if k == 'status' and v in ('created', 'modified', 'deleted'):
return True return True
elif aci_changed(v) is True: elif self.changed(v) is True:
return True return True
elif isinstance(d, list): elif isinstance(d, list):
for i in d: for i in d:
if aci_changed(i) is True: if self.changed(i) is True:
return True return True
return False return False
def response_any(self, rawoutput, rest_type='xml'):
def aci_response(result, rawoutput, rest_type='xml'):
''' Handle APIC response output ''' ''' Handle APIC response output '''
if rest_type == 'json': if rest_type == 'json':
aci_response_json(result, rawoutput) self.response_json(rawoutput)
else: else:
aci_response_xml(result, rawoutput) self.response_xml(rawoutput)
# Use APICs built-in idempotency # Use APICs built-in idempotency
if HAS_URLPARSE: if HAS_URLPARSE:
result['changed'] = aci_changed(result) self.result['changed'] = self.changed(self.imdata)
def main(): def main():
@ -336,7 +337,7 @@ def main():
else: else:
module.fail_json(msg='Failed to find REST API payload type (neither .xml nor .json).') module.fail_json(msg='Failed to find REST API payload type (neither .xml nor .json).')
aci = ACIModule(module) aci = ACIRESTModule(module)
# We include the payload as it may be templated # We include the payload as it may be templated
payload = content payload = content
@ -370,37 +371,45 @@ def main():
module.fail_json(msg='Failed to parse provided XML payload: %s' % to_text(e), payload=payload) module.fail_json(msg='Failed to parse provided XML payload: %s' % to_text(e), payload=payload)
# Perform actual request using auth cookie (Same as aci_request, but also supports XML) # Perform actual request using auth cookie (Same as aci_request, but also supports XML)
aci.result['url'] = '%(protocol)s://%(host)s/' % aci.params + path.lstrip('/') aci.url = '%(protocol)s://%(host)s/' % aci.params + path.lstrip('/')
if aci.params['method'] != 'get': if aci.params['method'] != 'get':
path += '?rsp-subtree=modified' path += '?rsp-subtree=modified'
aci.result['url'] = update_qsl(aci.result['url'], {'rsp-subtree': 'modified'}) aci.url = update_qsl(aci.url, {'rsp-subtree': 'modified'})
# Sign and encode request as to APIC's wishes # Sign and encode request as to APIC's wishes
if aci.params['private_key'] is not None: if aci.params['private_key'] is not None:
aci.cert_auth(path=path, payload=payload) aci.cert_auth(path=path, payload=payload)
# Perform request # Perform request
resp, info = fetch_url(module, aci.result['url'], resp, info = fetch_url(module, aci.url,
data=payload, data=payload,
headers=aci.headers, headers=aci.headers,
method=aci.params['method'].upper(), method=aci.params['method'].upper(),
timeout=aci.params['timeout'], timeout=aci.params['timeout'],
use_proxy=aci.params['use_proxy']) use_proxy=aci.params['use_proxy'])
if aci.params['output_level'] == 'debug':
aci.result['filter_string'] = aci.filter_string
aci.result['method'] = aci.params['method'].upper()
# aci.result['path'] = aci.path # Adding 'path' in result causes state: absent in output
aci.result['response'] = info['msg'] aci.result['response'] = info['msg']
aci.result['status'] = info['status'] aci.result['status'] = info['status']
aci.result['url'] = aci.url
# Report failure # Report failure
if info['status'] != 200: if info['status'] != 200:
try: try:
# APIC error # APIC error
aci_response(aci.result, info['body'], rest_type) aci.response(info['body'], rest_type)
module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % aci.result, **aci.result) aci.fail_json(msg='Request failed: %(code)s %(text)s' % aci.error)
except KeyError: except KeyError:
# Connection error # Connection error
module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info, **aci.result) aci.fail_json(msg='Request connection failed for %(url)s. %(msg)s' % info)
aci_response(aci.result, resp.read(), rest_type) aci.response_any(resp.read(), rest_type)
aci.result['imdata'] = aci.imdata
aci.result['totalCount'] = aci.totalCount
# Report success # Report success
module.exit_json(**aci.result) module.exit_json(**aci.result)

View file

@ -110,7 +110,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = ''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -209,7 +312,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -68,7 +68,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -127,7 +228,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -66,7 +66,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -137,7 +238,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -75,7 +75,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -135,7 +236,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -58,7 +58,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -128,7 +229,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -118,7 +118,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -227,7 +328,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -60,7 +60,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -129,7 +230,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -67,7 +67,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -143,7 +244,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -60,7 +60,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -137,7 +238,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -82,7 +82,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -153,7 +254,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -114,7 +114,108 @@ EXAMPLES = r'''
''' '''
RETURN = r''' RETURN = r'''
# current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
''' '''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
@ -247,7 +348,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -94,7 +94,110 @@ EXAMPLES = r'''
state: query state: query
''' '''
RETURN = r''' # ''' RETURN = r'''
current:
description: The existing configuration from the APIC after the module has finished
returned: success
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
error:
description: The error information as returned from the APIC
returned: failure
type: dict
sample:
{
"code": "122",
"text": "unknown managed object class foo"
}
raw:
description: The raw output returned by the APIC REST API (xml or json)
returned: parse error
type: string
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
sent:
description: The actual/minimal configuration pushed to the APIC
returned: info
type: list
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment"
}
}
}
previous:
description: The original configuration from the APIC before the module has started
returned: info
type: list
sample:
[
{
"fvTenant": {
"attributes": {
"descr": "Production",
"dn": "uni/tn-production",
"name": "production",
"nameAlias": "",
"ownerKey": "",
"ownerTag": ""
}
}
}
]
proposed:
description: The assembled configuration from the user-provided parameters
returned: info
type: dict
sample:
{
"fvTenant": {
"attributes": {
"descr": "Production environment",
"name": "production"
}
}
}
filter_string:
description: The filter string used for the request
returned: failure or debug
type: string
sample: ?rsp-prop-include=config-only
method:
description: The HTTP method used for the request to the APIC
returned: failure or debug
type: string
sample: POST
response:
description: The HTTP response from the APIC
returned: failure or debug
type: string
sample: OK (30 bytes)
status:
description: The HTTP status from the APIC
returned: failure or debug
type: int
sample: 200
url:
description: The HTTP url used for the request to the APIC
returned: failure or debug
type: string
sample: https://10.11.12.13/api/mo/uni/tn-production.json
'''
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -167,7 +270,7 @@ def main():
elif state == 'absent': elif state == 'absent':
aci.delete_config() aci.delete_config()
module.exit_json(**aci.result) aci.exit_json()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -45,15 +45,23 @@ options:
required: yes required: yes
private_key: private_key:
description: description:
- PEM formatted file that contains your private key to be used for client certificate authentication. - PEM formatted file that contains your private key to be used for signature-based authentication.
- The name of the key (without extension) is used as the certificate name in ACI, unless C(certificate_name) is specified. - The name of the key (without extension) is used as the certificate name in ACI, unless C(certificate_name) is specified.
aliases: [ cert_key ] aliases: [ cert_key ]
certificate_name: certificate_name:
description: description:
- The X.509 certificate name attached to the APIC AAA user. - The X.509 certificate name attached to the APIC AAA user used for signature-based authentication.
- It defaults to the C(private_key) basename, without extension. - It defaults to the C(private_key) basename, without extension.
aliases: [ cert_name ] aliases: [ cert_name ]
default: C(private_key) basename default: C(private_key) basename
output_level:
description:
- Influence the output of this ACI module.
- C(normal) means the standard output, incl. C(current) dict
- C(info) means informational output, incl. C(previous), C(proposed) and C(sent) dicts
- C(debug) means debugging output, incl. C(filter_string), C(method), C(response), C(status) and C(url) information
choices: [ debug, info, normal ]
default: normal
timeout: timeout:
description: description:
- The socket level timeout in seconds. - The socket level timeout in seconds.
@ -61,8 +69,8 @@ options:
use_proxy: use_proxy:
description: description:
- If C(no), it will not use a proxy, even if one is defined in an environment variable on the target hosts. - If C(no), it will not use a proxy, even if one is defined in an environment variable on the target hosts.
default: 'yes'
type: bool type: bool
default: 'yes'
use_ssl: use_ssl:
description: description:
- If C(no), an HTTP connection will be used instead of the default HTTPS connection. - If C(no), an HTTP connection will be used instead of the default HTTPS connection.

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
leaf_interface_profile: leafintprftest leaf_interface_profile: leafintprftest
register: leaf_profile_present register: leaf_profile_present
@ -54,12 +55,12 @@
that: that:
- accessport_to_intf_check_mode_present.changed == true - accessport_to_intf_check_mode_present.changed == true
- accessport_to_intf_present.changed == true - accessport_to_intf_present.changed == true
- accessport_to_intf_present.existing == [] - accessport_to_intf_present.previous == []
- 'accessport_to_intf_present.config == {"infraHPortS": {"attributes": {"name": "anstest_accessportselector"}, "children": [{"infraPortBlk": {"attributes": {"fromPort": "13", "name": "anstest_leafportblkname", "toPort": "16"}}}, {"infraRsAccBaseGrp": {"attributes": {"tDn": "uni/infra/funcprof/accportgrp-None"}}}]}}' - 'accessport_to_intf_present.sent == {"infraHPortS": {"attributes": {"name": "anstest_accessportselector"}, "children": [{"infraPortBlk": {"attributes": {"fromPort": "13", "name": "anstest_leafportblkname", "toPort": "16"}}}, {"infraRsAccBaseGrp": {"attributes": {"tDn": "uni/infra/funcprof/accportgrp-None"}}}]}}'
- accessport_to_intf_idempotent.changed == false - accessport_to_intf_idempotent.changed == false
- accessport_to_intf_idempotent.config == {} - accessport_to_intf_idempotent.sent == {}
- accessport_to_intf_update.changed == true - accessport_to_intf_update.changed == true
- 'accessport_to_intf_update.config == {"infraHPortS": {"attributes": {},"children": [{"infraRsAccBaseGrp": {"attributes": {"tDn": "uni/infra/funcprof/accportgrp-anstest_policygroupname"}}}]}}' - 'accessport_to_intf_update.sent == {"infraHPortS": {"attributes": {},"children": [{"infraRsAccBaseGrp": {"attributes": {"tDn": "uni/infra/funcprof/accportgrp-anstest_policygroupname"}}}]}}'
- name: Query Specific access_port_selector and leaf_interface_profile binding - name: Query Specific access_port_selector and leaf_interface_profile binding
aci_access_port_to_interface_policy_leaf_profile: aci_access_port_to_interface_policy_leaf_profile:
@ -72,7 +73,7 @@
assert: assert:
that: that:
- binding_query.changed == false - binding_query.changed == false
- binding_query.existing | length >= 1 - binding_query.previous | length >= 1
- '"api/mo/uni/infra/accportprof-leafintprftest/hports-anstest_accessportselector-typ-range.json" in binding_query.url' - '"api/mo/uni/infra/accportprof-leafintprftest/hports-anstest_accessportselector-typ-range.json" in binding_query.url'
- name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
@ -105,11 +106,11 @@
assert: assert:
that: that:
- accessport_to_intf_check_mode_absent.changed == true - accessport_to_intf_check_mode_absent.changed == true
- accessport_to_intf_check_mode_absent.existing != [] - accessport_to_intf_check_mode_absent.previous != []
- accessport_to_intf_absent.changed == true - accessport_to_intf_absent.changed == true
- accessport_to_intf_absent.existing == accessport_to_intf_check_mode_absent.existing - accessport_to_intf_absent.previous == accessport_to_intf_check_mode_absent.previous
- accessport_to_intf_absent_idempotent.changed == false - accessport_to_intf_absent_idempotent.changed == false
- accessport_to_intf_absent_idempotent.existing == [] - accessport_to_intf_absent_idempotent.previous == []
- accessport_to_intf_absent_missing_param.failed == true - accessport_to_intf_absent_missing_param.failed == true
- 'accessport_to_intf_absent_missing_param.msg == "state is absent but all of the following are missing: access_port_selector"' - 'accessport_to_intf_absent_missing_param.msg == "state is absent but all of the following are missing: access_port_selector"'

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -60,14 +61,14 @@
that: that:
- ap_present_check_mode.changed == true - ap_present_check_mode.changed == true
- ap_present.changed == true - ap_present.changed == true
- ap_present.existing == [] - ap_present.previous == []
- ap_present.config == ap_present_check_mode.config - ap_present.sent == ap_present_check_mode.sent
- 'ap_present.config == {"fvAp": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' - 'ap_present.sent == {"fvAp": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}'
- ap_present_idempotent.changed == false - ap_present_idempotent.changed == false
- ap_present_idempotent.existing != [] - ap_present_idempotent.previous != []
- ap_present_idempotent.config == {} - ap_present_idempotent.sent == {}
- ap_present_update.changed == true - ap_present_update.changed == true
- 'ap_present_update.config.fvAp.attributes == {"descr": "Ansible Test Update"}' - 'ap_present_update.sent.fvAp.attributes == {"descr": "Ansible Test Update"}'
- ap_present_missing_param.failed == true - ap_present_missing_param.failed == true
- 'ap_present_missing_param.msg == "state is present but all of the following are missing: ap"' - 'ap_present_missing_param.msg == "state is present but all of the following are missing: ap"'
@ -100,21 +101,21 @@
assert: assert:
that: that:
- query_ap.changed == false - query_ap.changed == false
- query_ap.existing | length == 1 - query_ap.previous | length == 1
- 'query_ap.existing.0.fvAp.attributes.name == "anstest"' - 'query_ap.previous.0.fvAp.attributes.name == "anstest"'
- '"tn-anstest/ap-anstest.json" in query_ap.url' - '"tn-anstest/ap-anstest.json" in query_ap.url'
- query_ap_tenant.changed == false - query_ap_tenant.changed == false
- query_ap_tenant.existing | length == 1 - query_ap_tenant.previous | length == 1
- query_ap_tenant.existing.0.fvTenant.children | length == 2 - query_ap_tenant.previous.0.fvTenant.children | length == 2
- '"rsp-subtree-class=fvAp" in query_ap_tenant.filter_string' - '"rsp-subtree-class=fvAp" in query_ap_tenant.filter_string'
- '"tn-anstest.json" in query_ap_tenant.url' - '"tn-anstest.json" in query_ap_tenant.url'
- query_ap_ap.changed == false - query_ap_ap.changed == false
- query_ap_ap.existing != [] - query_ap_ap.previous != []
- query_ap_ap.existing.0.fvAp is defined - query_ap_ap.previous.0.fvAp is defined
- '"query-target-filter=eq(fvAp.name, \"anstest\")" in query_ap_ap.filter_string' - '"query-target-filter=eq(fvAp.name, \"anstest\")" in query_ap_ap.filter_string'
- '"class/fvAp.json" in query_ap_ap.url' - '"class/fvAp.json" in query_ap_ap.url'
- query_all.changed == false - query_all.changed == false
- query_all.existing | length > 1 - query_all.previous | length > 1
- '"class/fvAp.json" in query_all.url' - '"class/fvAp.json" in query_all.url'
- name: delete ap - check_mode works - name: delete ap - check_mode works
@ -150,12 +151,12 @@
assert: assert:
that: that:
- ap_delete_check_mode.changed == true - ap_delete_check_mode.changed == true
- ap_delete_check_mode.existing != [] - ap_delete_check_mode.previous != []
- '"tn-anstest/ap-anstest.json" in ap_delete_check_mode.url' - '"tn-anstest/ap-anstest.json" in ap_delete_check_mode.url'
- ap_delete.changed == true - ap_delete.changed == true
- ap_delete.existing == ap_delete_check_mode.existing - ap_delete.previous == ap_delete_check_mode.previous
- ap_delete_idempotent.changed == false - ap_delete_idempotent.changed == false
- ap_delete_idempotent.existing == [] - ap_delete_idempotent.previous == []
- ap_delete_missing_param.failed == true - ap_delete_missing_param.failed == true
- 'ap_delete_missing_param.msg == "state is absent but all of the following are missing: tenant"' - 'ap_delete_missing_param.msg == "state is absent but all of the following are missing: tenant"'

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -74,17 +75,17 @@
assert: assert:
that: that:
- bd_present_check_mode.changed == true - bd_present_check_mode.changed == true
- 'bd_present_check_mode.config == {"fvBD": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' - 'bd_present_check_mode.sent == {"fvBD": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}'
- bd_present.changed == true - bd_present.changed == true
- bd_present.config == bd_present_check_mode.config - bd_present.sent == bd_present_check_mode.sent
- bd_present.existing == [] - bd_present.previous == []
- bd_present_idempotent.changed == false - bd_present_idempotent.changed == false
- bd_present_idempotent.existing != [] - bd_present_idempotent.previous != []
- bd_update.changed == true - bd_update.changed == true
- bd_update.existing != [] - bd_update.previous != []
- bd_update.changed != bd_update.proposed - bd_update.changed != bd_update.proposed
- 'bd_update.config == {"fvBD": {"attributes": {"descr": "Ansible Test Update"}, "children": [{"fvRsCtx": {"attributes": {"tnFvCtxName": "anstest"}}}]}}' - 'bd_update.sent == {"fvBD": {"attributes": {"descr": "Ansible Test Update"}, "children": [{"fvRsCtx": {"attributes": {"tnFvCtxName": "anstest"}}}]}}'
- 'bd_present_2.config.fvBD.attributes == {"arpFlood": "yes", "descr": "Ansible Test", "ipLearning": "no", "multiDstPktAct": "drop", "name": "anstest2", - 'bd_present_2.sent.fvBD.attributes == {"arpFlood": "yes", "descr": "Ansible Test", "ipLearning": "no", "multiDstPktAct": "drop", "name": "anstest2",
"unicastRoute": "no", "unkMacUcastAct": "flood", "unkMcastAct": "opt-flood"}' "unicastRoute": "no", "unkMacUcastAct": "flood", "unkMcastAct": "opt-flood"}'
- bd_present_missing_param.failed == true - bd_present_missing_param.failed == true
- 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"' - 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"'
@ -118,23 +119,23 @@
assert: assert:
that: that:
- query_all.changed == false - query_all.changed == false
- query_all.existing | length > 1 - query_all.previous | length > 1
- query_all.existing.0.fvBD is defined - query_all.previous.0.fvBD is defined
- '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_all.filter_string' - '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_all.filter_string'
- '"class/fvBD.json" in query_all.url' - '"class/fvBD.json" in query_all.url'
- query_tenant.changed == false - query_tenant.changed == false
- query_tenant.existing | length == 1 - query_tenant.previous | length == 1
- query_tenant.existing.0.fvTenant.children | length == 2 - query_tenant.previous.0.fvTenant.children | length == 2
- '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet,fvBD" in query_tenant.filter_string' - '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet,fvBD" in query_tenant.filter_string'
- '"tn-anstest.json" in query_tenant.url' - '"tn-anstest.json" in query_tenant.url'
- query_bd_bd.changed == false - query_bd_bd.changed == false
- query_bd_bd.existing != [] - query_bd_bd.previous != []
- '"query-target-filter=eq(fvBD.name, \"anstest\")" in query_bd_bd.filter_string' - '"query-target-filter=eq(fvBD.name, \"anstest\")" in query_bd_bd.filter_string'
- '"rsp-subtree=full&rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_bd_bd.filter_string' - '"rsp-subtree=full&rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_bd_bd.filter_string'
- '"class/fvBD.json" in query_bd_bd.url' - '"class/fvBD.json" in query_bd_bd.url'
- query_bd.changed == false - query_bd.changed == false
- query_bd.existing | length == 1 - query_bd.previous | length == 1
- 'query_bd.existing.0.fvBD.attributes.name == "anstest"' - 'query_bd.previous.0.fvBD.attributes.name == "anstest"'
- '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_bd.filter_string' - '"rsp-subtree-class=fvRsCtx,fvRsIgmpsn,fvRsBDToNdP,fvRsBdToEpRet" in query_bd.filter_string'
- '"tn-anstest/BD-anstest.json" in query_bd.url' - '"tn-anstest/BD-anstest.json" in query_bd.url'
@ -173,9 +174,9 @@
- bd_absent_check_mode.changed == true - bd_absent_check_mode.changed == true
- bd_absent_check_mode.proposed == {} - bd_absent_check_mode.proposed == {}
- bd_absent.changed == true - bd_absent.changed == true
- bd_absent.existing != [] - bd_absent.previous != []
- bd_absent_idempotent.changed == false - bd_absent_idempotent.changed == false
- bd_absent_idempotent.existing == [] - bd_absent_idempotent.previous == []
- bd_absent_missing_param.failed == true - bd_absent_missing_param.failed == true
- 'bd_absent_missing_param.msg == "state is absent but all of the following are missing: bd"' - 'bd_absent_missing_param.msg == "state is absent but all of the following are missing: bd"'

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -93,20 +94,20 @@
assert: assert:
that: that:
- create_check_mode.changed == true - create_check_mode.changed == true
- 'create_check_mode.config == {"fvSubnet": {"attributes": {"descr": "Ansible Test", "ip": "10.100.100.1/24", "name": "anstest"}}}' - 'create_check_mode.sent == {"fvSubnet": {"attributes": {"descr": "Ansible Test", "ip": "10.100.100.1/24", "name": "anstest"}}}'
- create_subnet.changed == true - create_subnet.changed == true
- 'create_subnet.config == {"fvSubnet": {"attributes": {"descr": "Ansible Test", "ip": "10.100.100.1/24", "name": "anstest"}}}' - 'create_subnet.sent == {"fvSubnet": {"attributes": {"descr": "Ansible Test", "ip": "10.100.100.1/24", "name": "anstest"}}}'
- 'create_subnet.existing == []' - 'create_subnet.previous == []'
- create_subnet2.changed == true - create_subnet2.changed == true
- create_subnet2.config == create_subnet2.proposed - create_subnet2.sent == create_subnet2.proposed
- 'create_subnet2.config.fvSubnet.attributes.scope == "private,shared"' - 'create_subnet2.sent.fvSubnet.attributes.scope == "private,shared"'
- 'create_subnet2.config.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes == {"tnL3extOutName": "default", "tnRtctrlProfileName": "default"}' - 'create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes == {"tnL3extOutName": "default", "tnRtctrlProfileName": "default"}'
- create_idempotency.changed == false - create_idempotency.changed == false
- create_idempotency.existing != [] - create_idempotency.previous != []
- modify_subnet.changed == true - modify_subnet.changed == true
- modify_subnet.existing != [] - modify_subnet.previous != []
- modify_subnet.changed != modify_subnet.proposed - modify_subnet.changed != modify_subnet.proposed
- 'modify_subnet.config == {"fvSubnet": {"attributes": {"ctrl": "querier", "scope": "public,shared"}}}' - 'modify_subnet.sent == {"fvSubnet": {"attributes": {"ctrl": "querier", "scope": "public,shared"}}}'
- create_bad_scope.failed == true - create_bad_scope.failed == true
- 'create_bad_scope.msg.startswith("value of scope must be one of")' - 'create_bad_scope.msg.startswith("value of scope must be one of")'
- create_incomplete_data.failed == true - create_incomplete_data.failed == true
@ -169,7 +170,7 @@
assert: assert:
that: that:
- get_all.changed == false - get_all.changed == false
- get_all.existing | length > 1 - get_all.previous | length > 1
- get_all_tenant.changed == false - get_all_tenant.changed == false
- '"tn-anstest.json" in get_all_tenant.url' - '"tn-anstest.json" in get_all_tenant.url'
- get_all_bd.changed == false - get_all_bd.changed == false
@ -177,7 +178,7 @@
- '"class/fvBD.json" in get_all_bd.url' - '"class/fvBD.json" in get_all_bd.url'
- get_all_tenant_bd.changed == false - get_all_tenant_bd.changed == false
- '"tn-anstest/BD-anstest.json" in get_all_tenant_bd.url' - '"tn-anstest/BD-anstest.json" in get_all_tenant_bd.url'
- get_all_tenant_bd.existing.0.fvBD.children | length > 1 - get_all_tenant_bd.previous.0.fvBD.children | length > 1
- get_subnet_tenant.changed == false - get_subnet_tenant.changed == false
- '"rsp-subtree-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnet_tenant.filter_string' - '"rsp-subtree-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnet_tenant.filter_string'
- '"tn-anstest.json" in get_subnet_tenant.url' - '"tn-anstest.json" in get_subnet_tenant.url'
@ -185,7 +186,7 @@
- '"query-target-filter=eq(fvBD.name, \"anstest\")" and "rsp-subtree-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnet_bd.filter_string' - '"query-target-filter=eq(fvBD.name, \"anstest\")" and "rsp-subtree-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnet_bd.filter_string'
- '"class/fvBD.json" in get_subnet_bd.url' - '"class/fvBD.json" in get_subnet_bd.url'
- get_subnet.changed == false - get_subnet.changed == false
- get_subnet.existing | length == 1 - get_subnet.previous | length == 1
- '"tn-anstest/BD-anstest/subnet-[10.100.100.1/24].json" in get_subnet.url' - '"tn-anstest/BD-anstest/subnet-[10.100.100.1/24].json" in get_subnet.url'
- get_subnets_gateway.changed == false - get_subnets_gateway.changed == false
- '"query-target-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnets_gateway.filter_string' - '"query-target-filter=eq(fvSubnet.ip, \"10.100.100.1/24\")" in get_subnets_gateway.filter_string'
@ -217,10 +218,10 @@
- delete_check_mode.changed == true - delete_check_mode.changed == true
- delete_check_mode.proposed == {} - delete_check_mode.proposed == {}
- delete_subnet.changed == true - delete_subnet.changed == true
- delete_subnet.existing != [] - delete_subnet.previous != []
- 'delete_subnet.method == "DELETE"' - 'delete_subnet.method == "DELETE"'
- delete_idempotency.changed == false - delete_idempotency.changed == false
- delete_idempotency.existing == [] - delete_idempotency.previous == []
- name: delete bd - cleanup before ending tests - name: delete bd - cleanup before ending tests
aci_bd: aci_bd:

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: absent state: absent
tenant: anstest tenant: anstest
@ -48,15 +49,15 @@
<<: *create_snapshot <<: *create_snapshot
state: preview state: preview
compare_export_policy: anstest compare_export_policy: anstest
compare_snapshot: "{{ snapshots.existing.0.configSnapshotCont.children[-1].configSnapshot.attributes.name }}" compare_snapshot: "{{ snapshots.previous.0.configSnapshotCont.children[-1].configSnapshot.attributes.name }}"
snapshot: "{{ snapshots.existing.0.configSnapshotCont.children[-2].configSnapshot.attributes.name }}" snapshot: "{{ snapshots.previous.0.configSnapshotCont.children[-2].configSnapshot.attributes.name }}"
register: rollback_preview register: rollback_preview
- name: rollback to snapshot - name: rollback to snapshot
aci_config_rollback: &aci_rollback aci_config_rollback: &aci_rollback
<<: *create_snapshot <<: *create_snapshot
state: rollback state: rollback
snapshot: "{{ snapshots.existing.0.configSnapshotCont.children[-1].configSnapshot.attributes.name }}" snapshot: "{{ snapshots.previous.0.configSnapshotCont.children[-1].configSnapshot.attributes.name }}"
ignore_errors: yes ignore_errors: yes
register: rollback_missing_param register: rollback_missing_param
@ -86,8 +87,8 @@
- rollback_missing_param.failed == true - rollback_missing_param.failed == true
- 'rollback_missing_param.msg == "state is rollback but all of the following are missing: import_policy"' - 'rollback_missing_param.msg == "state is rollback but all of the following are missing: import_policy"'
- rollback_rollback.changed == true - rollback_rollback.changed == true
- '"ce2_" in rollback_rollback.config.configImportP.attributes.fileName' - '"ce2_" in rollback_rollback.sent.configImportP.attributes.fileName'
- '".tar.gz" in rollback_rollback.config.configImportP.attributes.fileName' - '".tar.gz" in rollback_rollback.sent.configImportP.attributes.fileName'
- '"fabric/configimp-anstest.json" in rollback_rollback.url' - '"fabric/configimp-anstest.json" in rollback_rollback.url'
- tenant_removed.changed == false - tenant_removed.changed == false
- tenant_removed.existing == [] - tenant_removed.previous == []

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
export_policy: anstest export_policy: anstest
max_count: 10 max_count: 10
include_secure: no include_secure: no
@ -26,7 +27,7 @@
- name: update snapshot to include secure and use xml - update works - name: update snapshot to include secure and use xml - update works
aci_config_snapshot: aci_config_snapshot:
<<: *create_snapshot <<: *create_snapshot
include_secure: "yes" include_secure: yes
format: xml format: xml
register: create_update register: create_update
@ -49,12 +50,12 @@
that: that:
- create.failed == false - create.failed == false
- create.changed == true - create.changed == true
- 'create.config.configExportP.attributes.adminSt == "triggered"' - 'create.sent.configExportP.attributes.adminSt == "triggered"'
- create_update.failed == false - create_update.failed == false
- create_update.changed == true - create_update.changed == true
- 'create_update.config == {"configExportP": {"attributes": {"adminSt": "triggered", "format": "xml", "includeSecureFields": "yes"}}}' - 'create_update.sent == {"configExportP": {"attributes": {"adminSt": "triggered", "format": "xml", "includeSecureFields": "yes"}}}'
- invalid_max_count.failed == true - invalid_max_count.failed == true
- 'invalid_max_count.msg == "The \"max_count\" must be a number between 1 and 10"' - invalid_max_count.msg == "Parameter 'max_count' must be a number between 1 and 10"
- missing_param.failed == true - missing_param.failed == true
- 'missing_param.msg == "state is present but all of the following are missing: export_policy"' - 'missing_param.msg == "state is present but all of the following are missing: export_policy"'
@ -66,7 +67,7 @@
- name: generate snapshot name - name: generate snapshot name
set_fact: set_fact:
test_snapshot: "{{ query_export.existing.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}" test_snapshot: "{{ query_export.previous.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}"
- name: query with export_policy and snapshot - name: query with export_policy and snapshot
aci_config_snapshot: &query_both aci_config_snapshot: &query_both
@ -93,12 +94,12 @@
- query_export.failed == false - query_export.failed == false
- query_export.changed == false - query_export.changed == false
- '"snapshots-[uni/fabric/configexp-anstest].json" in query_export.url' - '"snapshots-[uni/fabric/configexp-anstest].json" in query_export.url'
- 'query_export.existing.0.configSnapshotCont.attributes.name == "anstest"' - query_export.previous.0.configSnapshotCont.attributes.name == "anstest"
- query_export.existing.0.configSnapshotCont.children | length > 1 - query_export.previous.0.configSnapshotCont.children | length > 1
- query_export_snapshot.failed == false - query_export_snapshot.failed == false
- query_export_snapshot.changed == false - query_export_snapshot.changed == false
- '"snapshots-[uni/fabric/configexp-anstest]/snapshot-{{ test_snapshot }}.json" in query_export_snapshot.url' - '"snapshots-[uni/fabric/configexp-anstest]/snapshot-{{ test_snapshot }}.json" in query_export_snapshot.url'
- query_export_snapshot.existing | length == 1 - query_export_snapshot.previous | length == 1
- query_snapshot.failed == false - query_snapshot.failed == false
- query_snapshot.changed == false - query_snapshot.changed == false
- '"class/configSnapshot.json" in query_snapshot.url' - '"class/configSnapshot.json" in query_snapshot.url'
@ -106,7 +107,7 @@
- query_all.failed == false - query_all.failed == false
- query_all.changed == false - query_all.changed == false
- '"class/configSnapshot.json" in query_all.url' - '"class/configSnapshot.json" in query_all.url'
- query_all.existing | length > 1 - query_all.previous | length > 1
- name: delete works - name: delete works
aci_config_snapshot: &delete aci_config_snapshot: &delete
@ -131,11 +132,11 @@
that: that:
- delete_snapshot.failed == false - delete_snapshot.failed == false
- delete_snapshot.changed == true - delete_snapshot.changed == true
- 'delete_snapshot.config == {"configSnapshot": {"attributes": {"retire": "yes"}}}' - 'delete_snapshot.sent == {"configSnapshot": {"attributes": {"retire": "yes"}}}'
- delete_snapshot.existing != [] - delete_snapshot.previous != []
- delete_snapshot.existing.0.configSnapshot.attributes.name == test_snapshot - delete_snapshot.previous.0.configSnapshot.attributes.name == test_snapshot
- delete_idempotent.failed == false - delete_idempotent.failed == false
- delete_idempotent.changed == false - delete_idempotent.changed == false
- delete_idempotent.existing == [] - delete_idempotent.previous == []
- delete_missing_param.failed == true - delete_missing_param.failed == true
- 'delete_missing_param.msg == "state is absent but all of the following are missing: snapshot"' - 'delete_missing_param.msg == "state is absent but all of the following are missing: snapshot"'

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -59,14 +60,14 @@
assert: assert:
that: that:
- present_check_mode.changed == true - present_check_mode.changed == true
- present_check_mode.existing == [] - present_check_mode.previous == []
- 'present_check_mode.config == {"vzBrCP": {"attributes": {"name": "anstest", "descr": "Ansible Test"}}}' - 'present_check_mode.sent == {"vzBrCP": {"attributes": {"name": "anstest", "descr": "Ansible Test"}}}'
- contract_present.changed == true - contract_present.changed == true
- contract_present.config == present_check_mode.config - contract_present.sent == present_check_mode.sent
- present_idempotent.changed == false - present_idempotent.changed == false
- present_update.changed == true - present_update.changed == true
- present_update.config != present_update.proposed - present_update.sent != present_update.proposed
- 'present_update.config.vzBrCP.attributes.scope == "application-profile"' - 'present_update.sent.vzBrCP.attributes.scope == "application-profile"'
- present_missing_param.failed == true - present_missing_param.failed == true
- 'present_missing_param.msg == "state is present but all of the following are missing: contract"' - 'present_missing_param.msg == "state is present but all of the following are missing: contract"'
@ -99,19 +100,19 @@
assert: assert:
that: that:
- query_contract.changed == false - query_contract.changed == false
- query_contract.existing | length == 1 - query_contract.previous | length == 1
- '"tn-anstest/brc-anstest.json" in query_contract.url' - '"tn-anstest/brc-anstest.json" in query_contract.url'
- query_tenant.changed == false - query_tenant.changed == false
- query_tenant.existing | length == 1 - query_tenant.previous | length == 1
- query_tenant.existing.0.fvTenant.children | length > 1 - query_tenant.previous.0.fvTenant.children | length > 1
- '"rsp-subtree-class=vzBrCP" in query_tenant.filter_string' - '"rsp-subtree-class=vzBrCP" in query_tenant.filter_string'
- '"tn-anstest.json" in query_tenant.url' - '"tn-anstest.json" in query_tenant.url'
- query_name.changed == false - query_name.changed == false
- query_name.existing != [] - query_name.previous != []
- '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_name.filter_string' - '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_name.filter_string'
- '"class/vzBrCP.json" in query_name.url' - '"class/vzBrCP.json" in query_name.url'
- query_all.changed == false - query_all.changed == false
- query_all.existing | length > 1 - query_all.previous | length > 1
- '"class/vzBrCP.json" in query_all.url' - '"class/vzBrCP.json" in query_all.url'
- name: delete contract - check mode works - name: delete contract - check mode works
@ -147,11 +148,11 @@
assert: assert:
that: that:
- absent_check_mode.changed == true - absent_check_mode.changed == true
- absent_check_mode.existing != [] - absent_check_mode.previous != []
- contract_absent.changed == true - contract_absent.changed == true
- contract_absent.existing == absent_check_mode.existing - contract_absent.previous == absent_check_mode.previous
- absent_idempotent.changed == false - absent_idempotent.changed == false
- absent_idempotent.existing == [] - absent_idempotent.previous == []
- absent_missing_param.failed == true - absent_missing_param.failed == true
- 'absent_missing_param.msg == "state is absent but all of the following are missing: tenant"' - 'absent_missing_param.msg == "state is absent but all of the following are missing: tenant"'

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -72,17 +73,17 @@
assert: assert:
that: that:
- subject_present_check_mode.changed == true - subject_present_check_mode.changed == true
- 'subject_present_check_mode.config == {"vzSubj": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' - 'subject_present_check_mode.sent == {"vzSubj": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}'
- subject_present.changed == true - subject_present.changed == true
- subject_present.existing == [] - subject_present.previous == []
- subject_present.config == subject_present_check_mode.config - subject_present.sent == subject_present_check_mode.sent
- subject_present_idempotent.changed == false - subject_present_idempotent.changed == false
- subject_present_idempotent.existing != [] - subject_present_idempotent.previous != []
- subject_update.changed == true - subject_update.changed == true
- subject_update.config != subject_update.proposed - subject_update.sent != subject_update.proposed
- 'subject_update.config.vzSubj.attributes == {"prio": "level2", "provMatchT": "AtmostOne"}' - 'subject_update.sent.vzSubj.attributes == {"prio": "level2", "provMatchT": "AtmostOne"}'
- subject_present_2.changed == true - subject_present_2.changed == true
- 'subject_present_2.config.vzSubj.attributes == {"consMatchT": "All", "name": "anstest2", "prio": "level3", "revFltPorts": "no"}' - 'subject_present_2.sent.vzSubj.attributes == {"consMatchT": "All", "name": "anstest2", "prio": "level3", "revFltPorts": "no"}'
- present_missing_param.failed == true - present_missing_param.failed == true
- 'present_missing_param.msg == "state is present but all of the following are missing: contract, subject"' - 'present_missing_param.msg == "state is present but all of the following are missing: contract, subject"'
@ -141,48 +142,48 @@
assert: assert:
that: that:
- query_tenant_contract_subject.changed == false - query_tenant_contract_subject.changed == false
- query_tenant_contract_subject.existing | length == 1 - query_tenant_contract_subject.previous | length == 1
- 'query_tenant_contract_subject.existing.0.vzSubj.attributes.name == "anstest"' - 'query_tenant_contract_subject.previous.0.vzSubj.attributes.name == "anstest"'
- '"tn-anstest/brc-anstest/subj-anstest.json" in query_tenant_contract_subject.url' - '"tn-anstest/brc-anstest/subj-anstest.json" in query_tenant_contract_subject.url'
- query_tenant_contract.changed == false - query_tenant_contract.changed == false
- query_tenant_contract.existing | length == 1 - query_tenant_contract.previous | length == 1
- 'query_tenant_contract.existing.0.vzBrCP.attributes.name == "anstest"' - 'query_tenant_contract.previous.0.vzBrCP.attributes.name == "anstest"'
- query_tenant_contract.existing.0.vzBrCP.children | length == 2 - query_tenant_contract.previous.0.vzBrCP.children | length == 2
- '"rsp-subtree-class=vzSubj" in query_tenant_contract.filter_string' - '"rsp-subtree-class=vzSubj" in query_tenant_contract.filter_string'
- '"tn-anstest/brc-anstest.json" in query_tenant_contract.url' - '"tn-anstest/brc-anstest.json" in query_tenant_contract.url'
- query_tenant_subject.changed == false - query_tenant_subject.changed == false
- query_tenant_subject.existing | length == 1 - query_tenant_subject.previous | length == 1
- 'query_tenant_subject.existing.0.fvTenant.attributes.name == "anstest"' - 'query_tenant_subject.previous.0.fvTenant.attributes.name == "anstest"'
- query_tenant_subject.existing.0.fvTenant.children.0.vzBrCP.children | length == 1 - query_tenant_subject.previous.0.fvTenant.children.0.vzBrCP.children | length == 1
- 'query_tenant_subject.existing.0.fvTenant.children.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"' - 'query_tenant_subject.previous.0.fvTenant.children.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"'
- '"rsp-subtree-filter=eq(vzSubj.name, \"anstest\")" in query_tenant_subject.filter_string' - '"rsp-subtree-filter=eq(vzSubj.name, \"anstest\")" in query_tenant_subject.filter_string'
- '"rsp-subtree-class=vzSubj" in query_tenant_subject.filter_string' - '"rsp-subtree-class=vzSubj" in query_tenant_subject.filter_string'
- '"tn-anstest.json" in query_tenant_subject.url' - '"tn-anstest.json" in query_tenant_subject.url'
- query_contract_subject.changed == false - query_contract_subject.changed == false
- 'query_contract_subject.existing.0.vzBrCP.attributes.name == "anstest"' - 'query_contract_subject.previous.0.vzBrCP.attributes.name == "anstest"'
- query_contract_subject.existing.0.vzBrCP.children | length == 1 - query_contract_subject.previous.0.vzBrCP.children | length == 1
- 'query_contract_subject.existing.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"' - 'query_contract_subject.previous.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"'
- '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_contract_subject.filter_string' - '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_contract_subject.filter_string'
- '"rsp-subtree-filter=eq(vzSubj.name, \"anstest\")" in query_contract_subject.filter_string' - '"rsp-subtree-filter=eq(vzSubj.name, \"anstest\")" in query_contract_subject.filter_string'
- '"rsp-subtree-class=vzSubj" in query_contract_subject.filter_string' - '"rsp-subtree-class=vzSubj" in query_contract_subject.filter_string'
- '"class/vzBrCP.json" in query_contract_subject.url' - '"class/vzBrCP.json" in query_contract_subject.url'
- query_tenant.changed == false - query_tenant.changed == false
- query_tenant.existing | length == 1 - query_tenant.previous | length == 1
- 'query_tenant.existing.0.fvTenant.attributes.name == "anstest"' - 'query_tenant.previous.0.fvTenant.attributes.name == "anstest"'
- '"rsp-subtree-class=vzBrCP,vzSubj" in query_tenant.filter_string' - '"rsp-subtree-class=vzBrCP,vzSubj" in query_tenant.filter_string'
- '"tn-anstest.json" in query_tenant.url' - '"tn-anstest.json" in query_tenant.url'
- query_contract.changed == false - query_contract.changed == false
- 'query_contract.existing.0.vzBrCP.attributes.name == "anstest"' - 'query_contract.previous.0.vzBrCP.attributes.name == "anstest"'
- '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_contract.filter_string' - '"query-target-filter=eq(vzBrCP.name, \"anstest\")" in query_contract.filter_string'
- '"rsp-subtree-class=vzSubj" in query_contract.filter_string' - '"rsp-subtree-class=vzSubj" in query_contract.filter_string'
- '"class/vzBrCP.json" in query_contract.url' - '"class/vzBrCP.json" in query_contract.url'
- query_subject.changed == false - query_subject.changed == false
- 'query_subject.existing.0.vzSubj.attributes.name == "anstest"' - 'query_subject.previous.0.vzSubj.attributes.name == "anstest"'
- '"query-target-filter=eq(vzSubj.name, \"anstest\")" in query_subject.filter_string' - '"query-target-filter=eq(vzSubj.name, \"anstest\")" in query_subject.filter_string'
- '"class/vzSubj.json" in query_subject.url' - '"class/vzSubj.json" in query_subject.url'
- query_all.changed == false - query_all.changed == false
- query_all.existing > 1 - query_all.previous > 1
- query_all.existing.0.vzSubj is defined - query_all.previous.0.vzSubj is defined
- '"class/vzSubj.json" in query_all.url' - '"class/vzSubj.json" in query_all.url'
- name: delete subject - check mode works - name: delete subject - check mode works
@ -218,12 +219,12 @@
assert: assert:
that: that:
- subject_absent_check_mode.changed == true - subject_absent_check_mode.changed == true
- subject_absent_check_mode.existing != [] - subject_absent_check_mode.previous != []
- subject_absent_check_mode.proposed == {} - subject_absent_check_mode.proposed == {}
- subject_absent.changed == true - subject_absent.changed == true
- subject_absent.existing == subject_absent_check_mode.existing - subject_absent.previous == subject_absent_check_mode.previous
- subject_absent_idempotent.changed == false - subject_absent_idempotent.changed == false
- subject_absent_idempotent.existing == [] - subject_absent_idempotent.previous == []
- absent_missing_param.failed == true - absent_missing_param.failed == true
- 'absent_missing_param.msg == "state is absent but all of the following are missing: subject"' - 'absent_missing_param.msg == "state is absent but all of the following are missing: subject"'

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: info
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -84,16 +85,16 @@
assert: assert:
that: that:
- subject_filter_present_check_mode.changed == true - subject_filter_present_check_mode.changed == true
- subject_filter_present_check_mode.existing == [] - subject_filter_present_check_mode.previous == []
- 'subject_filter_present_check_mode.config == {"vzRsSubjFiltAtt": {"attributes": {"directives": "log", "tnVzFilterName": "anstest"}}}' - 'subject_filter_present_check_mode.sent == {"vzRsSubjFiltAtt": {"attributes": {"directives": "log", "tnVzFilterName": "anstest"}}}'
- subject_filter_present.changed == true - subject_filter_present.changed == true
- subject_filter_present.existing == [] - subject_filter_present.previous == []
- subject_filter_present.config == subject_filter_present_check_mode.config - subject_filter_present.sent == subject_filter_present_check_mode.sent
- subject_filter_present_2.changed == true - subject_filter_present_2.changed == true
- subject_filter_present_idempotent.changed == false - subject_filter_present_idempotent.changed == false
- subject_filter_present_idempotent.existing != [] - subject_filter_present_idempotent.previous != []
- subject_filter_update.changed == true - subject_filter_update.changed == true
- 'subject_filter_update.config.vzRsSubjFiltAtt.attributes == {"directives": ""}' - 'subject_filter_update.sent.vzRsSubjFiltAtt.attributes == {"directives": ""}'
- present_missing_param.failed == true - present_missing_param.failed == true
- 'present_missing_param.msg == "state is present but all of the following are missing: contract, filter, subject"' - 'present_missing_param.msg == "state is present but all of the following are missing: contract, filter, subject"'
@ -114,10 +115,10 @@
assert: assert:
that: that:
- query_all.changed == false - query_all.changed == false
- query_all.existing | length > 1 - query_all.previous | length > 1
- query_all.existing.0.vzRsSubjFiltAtt is defined - query_all.previous.0.vzRsSubjFiltAtt is defined
- query_binding.changed == false - query_binding.changed == false
- query_binding.existing != [] - query_binding.previous != []
- name: delete subject filter binding - check mode works - name: delete subject filter binding - check mode works
aci_contract_subject_to_filter: &aci_subject_filter_absent aci_contract_subject_to_filter: &aci_subject_filter_absent
@ -153,11 +154,11 @@
that: that:
- subject_filter_absent_check_mode.changed == true - subject_filter_absent_check_mode.changed == true
- subject_filter_absent_check_mode.proposed == {} - subject_filter_absent_check_mode.proposed == {}
- subject_filter_absent_check_mode.existing != [] - subject_filter_absent_check_mode.previous != []
- subject_filter_absent.changed == true - subject_filter_absent.changed == true
- subject_filter_absent.existing != [] - subject_filter_absent.previous != []
- subject_filter_absent_idempotent.changed == false - subject_filter_absent_idempotent.changed == false
- subject_filter_absent_idempotent.existing == [] - subject_filter_absent_idempotent.previous == []
- absent_missing_param.failed == true - absent_missing_param.failed == true
- 'absent_missing_param.msg == "state is absent but all of the following are missing: filter"' - 'absent_missing_param.msg == "state is absent but all of the following are missing: filter"'

View file

@ -7,6 +7,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: absent state: absent
pool: anstest pool: anstest
pool_type: vlan pool_type: vlan
@ -29,7 +30,7 @@
assert: assert:
that: that:
- create_check_mode.changed == true - create_check_mode.changed == true
- 'create_check_mode.config == {"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "name": "anstest"}}}' - 'create_check_mode.sent == {"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "name": "anstest"}}}'
- name: create static vlan pool - creation works - name: create static vlan pool - creation works
aci_encap_pool: aci_encap_pool:
@ -40,8 +41,8 @@
assert: assert:
that: that:
- create_static.changed == true - create_static.changed == true
- create_static.existing == [] - create_static.previous == []
- create_static.config == create_check_mode.config - create_static.sent == create_check_mode.sent
- name: create dynamic vlan pool - creation works - name: create dynamic vlan pool - creation works
aci_encap_pool: &aci_pool_present_dynamic aci_encap_pool: &aci_pool_present_dynamic
@ -54,8 +55,8 @@
assert: assert:
that: that:
- create_dynamic.changed == true - create_dynamic.changed == true
- create_dynamic.existing == [] - create_dynamic.previous == []
- 'create_dynamic.config == {"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "name": "anstest"}}}' - 'create_dynamic.sent == {"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "name": "anstest"}}}'
- name: create static vlan pool again - idempotency works - name: create static vlan pool again - idempotency works
aci_encap_pool: aci_encap_pool:
@ -66,8 +67,8 @@
assert: assert:
that: that:
- idempotent_static.changed == false - idempotent_static.changed == false
- 'idempotent_static.existing == [{"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-static", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]' - 'idempotent_static.previous == [{"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-static", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]'
- idempotent_static.config == {} - idempotent_static.sent == {}
- name: create dynamic vlan pool again - idempotency works - name: create dynamic vlan pool again - idempotency works
aci_encap_pool: aci_encap_pool:
@ -78,8 +79,8 @@
assert: assert:
that: that:
- idempotent_dynamic.changed == false - idempotent_dynamic.changed == false
- 'idempotent_dynamic.existing == [{"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-dynamic", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]' - 'idempotent_dynamic.previous == [{"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-dynamic", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]'
- idempotent_dynamic.config == {} - idempotent_dynamic.sent == {}
- name: update static vlan pool - update works - name: update static vlan pool - update works
aci_encap_pool: aci_encap_pool:
@ -91,7 +92,7 @@
assert: assert:
that: that:
- update_static.changed == true - update_static.changed == true
- 'update_static.config == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}' - 'update_static.sent == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}'
- name: update dynamic vlan pool - update works - name: update dynamic vlan pool - update works
aci_encap_pool: aci_encap_pool:
@ -103,7 +104,7 @@
assert: assert:
that: that:
- update_dynamic.changed == true - update_dynamic.changed == true
- 'update_dynamic.config == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}' - 'update_dynamic.sent == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}'
- name: missing param - failure message works - name: missing param - failure message works
aci_encap_pool: aci_encap_pool:
@ -157,7 +158,7 @@
that: that:
- get_all_pools.changed == false - get_all_pools.changed == false
- get_all_pools.method == "GET" - get_all_pools.method == "GET"
- get_all_pools.existing | length > 1 - get_all_pools.previous | length > 1
- name: get created static vlan pool - get mo works - name: get created static vlan pool - get mo works
aci_encap_pool: aci_encap_pool:
@ -170,9 +171,9 @@
that: that:
- get_static_pool.changed == false - get_static_pool.changed == false
- get_static_pool.method == "GET" - get_static_pool.method == "GET"
- get_static_pool.existing | length == 1 - get_static_pool.previous | length == 1
- get_static_pool.existing.0.fvnsVlanInstP.attributes.allocMode == "static" - get_static_pool.previous.0.fvnsVlanInstP.attributes.allocMode == "static"
- get_static_pool.existing.0.fvnsVlanInstP.attributes.name == "anstest" - get_static_pool.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: get created dynamic vlan pool - get mo works - name: get created dynamic vlan pool - get mo works
aci_encap_pool: aci_encap_pool:
@ -185,9 +186,9 @@
that: that:
- get_dynamic_pool.changed == false - get_dynamic_pool.changed == false
- get_dynamic_pool.method == "GET" - get_dynamic_pool.method == "GET"
- get_dynamic_pool.existing | length == 1 - get_dynamic_pool.previous | length == 1
- get_dynamic_pool.existing.0.fvnsVlanInstP.attributes.allocMode == "dynamic" - get_dynamic_pool.previous.0.fvnsVlanInstP.attributes.allocMode == "dynamic"
- get_dynamic_pool.existing.0.fvnsVlanInstP.attributes.name == "anstest" - get_dynamic_pool.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: get created dynamic vlan pool - get mo works - name: get created dynamic vlan pool - get mo works
aci_encap_pool: aci_encap_pool:
@ -213,8 +214,8 @@
that: that:
- delete_static.changed == true - delete_static.changed == true
- delete_static.method == "DELETE" - delete_static.method == "DELETE"
- delete_static.existing.0.fvnsVlanInstP.attributes.allocMode == "static" - delete_static.previous.0.fvnsVlanInstP.attributes.allocMode == "static"
- delete_static.existing.0.fvnsVlanInstP.attributes.name == "anstest" - delete_static.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: delete dynamic vlan pool - check mode works - name: delete dynamic vlan pool - check mode works
aci_encap_pool: aci_encap_pool:
@ -237,8 +238,8 @@
that: that:
- delete_dynamic.changed == true - delete_dynamic.changed == true
- delete_dynamic.method == "DELETE" - delete_dynamic.method == "DELETE"
- delete_dynamic.existing.0.fvnsVlanInstP.attributes.allocMode == "dynamic" - delete_dynamic.previous.0.fvnsVlanInstP.attributes.allocMode == "dynamic"
- delete_dynamic.existing.0.fvnsVlanInstP.attributes.name == "anstest" - delete_dynamic.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: delete static vlan pool again - idempotency works - name: delete static vlan pool again - idempotency works
aci_encap_pool: aci_encap_pool:
@ -249,7 +250,7 @@
assert: assert:
that: that:
- idempotent_delete_static.changed == false - idempotent_delete_static.changed == false
- idempotent_delete_static.existing == [] - idempotent_delete_static.previous == []
- name: delete dynamic vlan pool again - idempotency works - name: delete dynamic vlan pool again - idempotency works
aci_encap_pool: aci_encap_pool:
@ -260,4 +261,4 @@
assert: assert:
that: that:
- idempotent_delete_dynamic.changed == false - idempotent_delete_dynamic.changed == false
- idempotent_delete_dynamic.existing == [] - idempotent_delete_dynamic.previous == []

View file

@ -7,6 +7,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: absent state: absent
pool: anstest pool: anstest
pool_type: vxlan pool_type: vxlan
@ -23,7 +24,7 @@
assert: assert:
that: that:
- create_vxlan_check_mode.changed == true - create_vxlan_check_mode.changed == true
- 'create_vxlan_check_mode.config == {"fvnsVxlanInstP": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' - 'create_vxlan_check_mode.sent == {"fvnsVxlanInstP": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}'
- name: create vxlan pool - creation works - name: create vxlan pool - creation works
aci_encap_pool: aci_encap_pool:
@ -34,8 +35,8 @@
assert: assert:
that: that:
- create_vxlan.changed == true - create_vxlan.changed == true
- create_vxlan.existing == [] - create_vxlan.previous == []
- create_vxlan.config == create_vxlan_check_mode.config - create_vxlan.sent == create_vxlan_check_mode.sent
- name: create vxlan pool again - idempotency works - name: create vxlan pool again - idempotency works
aci_encap_pool: aci_encap_pool:
@ -46,8 +47,8 @@
assert: assert:
that: that:
- idempotent_vxlan.changed == false - idempotent_vxlan.changed == false
- 'idempotent_vxlan.existing.0.fvnsVxlanInstP.attributes.name == "anstest"' - 'idempotent_vxlan.previous.0.fvnsVxlanInstP.attributes.name == "anstest"'
- idempotent_vxlan.config == {} - idempotent_vxlan.sent == {}
- name: update vxlan pool - update works - name: update vxlan pool - update works
aci_encap_pool: aci_encap_pool:
@ -59,7 +60,7 @@
assert: assert:
that: that:
- update_vxlan.changed == true - update_vxlan.changed == true
- 'update_vxlan.config == {"fvnsVxlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}' - 'update_vxlan.sent == {"fvnsVxlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}'
- name: create vxlan pool - used for query - name: create vxlan pool - used for query
aci_encap_pool: aci_encap_pool:
@ -96,7 +97,7 @@
assert: assert:
that: that:
- query_vxlan.changed == false - query_vxlan.changed == false
- query_vxlan.existing | length == 1 - query_vxlan.previous | length == 1
- '"infra/vxlanns-anstest.json" in query_vxlan.url' - '"infra/vxlanns-anstest.json" in query_vxlan.url'
- name: get created static vlan pool - get class works - name: get created static vlan pool - get class works
@ -109,7 +110,7 @@
assert: assert:
that: that:
- query_vxlan_all.changed == false - query_vxlan_all.changed == false
- query_vxlan_all.existing | length > 1 - query_vxlan_all.previous | length > 1
- '"class/fvnsVxlanInstP.json" in query_vxlan_all.url' - '"class/fvnsVxlanInstP.json" in query_vxlan_all.url'
- name: delete vxlan pool - check mode works - name: delete vxlan pool - check mode works
@ -122,7 +123,7 @@
assert: assert:
that: that:
- delete_vxlan_check_mode.changed == true - delete_vxlan_check_mode.changed == true
- delete_vxlan_check_mode.existing != [] - delete_vxlan_check_mode.previous != []
- name: delete vxlan pool - deletion works - name: delete vxlan pool - deletion works
aci_encap_pool: aci_encap_pool:
@ -133,8 +134,8 @@
assert: assert:
that: that:
- delete_vxlan.changed == true - delete_vxlan.changed == true
- delete_vxlan.existing == delete_vxlan_check_mode.existing - delete_vxlan.previous == delete_vxlan_check_mode.previous
- delete_vxlan.existing.0.fvnsVxlanInstP.attributes.name == "anstest" - delete_vxlan.previous.0.fvnsVxlanInstP.attributes.name == "anstest"
- name: delete vxlan pool again - idempotency works - name: delete vxlan pool again - idempotency works
aci_encap_pool: aci_encap_pool:
@ -152,7 +153,7 @@
assert: assert:
that: that:
- delete_vxlan_idempotent.changed == false - delete_vxlan_idempotent.changed == false
- delete_vxlan_idempotent.existing == [] - delete_vxlan_idempotent.previous == []
- name: delete vxlan pool - cleanup - name: delete vxlan pool - cleanup
aci_encap_pool: aci_encap_pool:

View file

@ -20,6 +20,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
pool: anstest pool: anstest
pool_type: vlan pool_type: vlan
@ -44,7 +45,7 @@
assert: assert:
that: that:
- range_present_check_mode.changed == true - range_present_check_mode.changed == true
- 'range_present_check_mode.config == {"fvnsEncapBlk": {"attributes": {"allocMode": "inherit", "descr": "Ansible Test", "from": "vlan-20", "name": "anstest", "to": "vlan-40"}}}' - 'range_present_check_mode.sent == {"fvnsEncapBlk": {"attributes": {"allocMode": "inherit", "descr": "Ansible Test", "from": "vlan-20", "name": "anstest", "to": "vlan-40"}}}'
- name: create vlan pool range - creation works - name: create vlan pool range - creation works
aci_encap_pool_range: aci_encap_pool_range:
@ -55,9 +56,9 @@
assert: assert:
that: that:
- range_present.changed == true - range_present.changed == true
- range_present.existing == [] - range_present.previous == []
- range_present.config == range_present_check_mode.config - range_present.sent == range_present_check_mode.sent
- range_present.config == range_present.proposed - range_present.sent == range_present.proposed
- name: create vlan pool range - idempotency works - name: create vlan pool range - idempotency works
aci_encap_pool_range: aci_encap_pool_range:
@ -68,7 +69,7 @@
assert: assert:
that: that:
- range_present_idempotent.changed == false - range_present_idempotent.changed == false
- 'range_present_idempotent.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'range_present_idempotent.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- name: update vlan pool range - update works - name: update vlan pool range - update works
aci_encap_pool_range: aci_encap_pool_range:
@ -81,8 +82,8 @@
assert: assert:
that: that:
- range_present_update.changed == true - range_present_update.changed == true
- range_present_update.existing != [] - range_present_update.previous != []
- range_present_update.config != range_present.config - range_present_update.sent != range_present.sent
- name: create vlan pool range - used for query - name: create vlan pool range - used for query
aci_encap_pool_range: &aci_range_present_2 aci_encap_pool_range: &aci_range_present_2
@ -96,7 +97,7 @@
assert: assert:
that: that:
- range_present_2.changed == true - range_present_2.changed == true
- range_present_2.existing == [] - range_present_2.previous == []
- name: invalid range_start - error message works - name: invalid range_start - error message works
aci_encap_pool_range: aci_encap_pool_range:
@ -212,8 +213,8 @@
that: that:
- range_query.changed == false - range_query.changed == false
- range_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json") - range_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json")
- range_query.existing | length == 1 - range_query.previous | length == 1
- 'range_query.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'range_query.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- name: query vlan pool range - from, to, and name are filtered - name: query vlan pool range - from, to, and name are filtered
aci_encap_pool_range: &aci_range_query_filter aci_encap_pool_range: &aci_range_query_filter
@ -227,9 +228,9 @@
- range_query_from_to_name.changed == false - range_query_from_to_name.changed == false
- 'range_query_from_to_name.url.endswith("class/fvnsEncapBlk.json")' - 'range_query_from_to_name.url.endswith("class/fvnsEncapBlk.json")'
- '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in range_query_from_to_name.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in range_query_from_to_name.filter_string'
- 'range_query_from_to_name.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'range_query_from_to_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- 'range_query_from_to_name.existing.0.fvnsEncapBlk.attributes.from == "vlan-20"' - 'range_query_from_to_name.previous.0.fvnsEncapBlk.attributes.from == "vlan-20"'
- 'range_query_from_to_name.existing.0.fvnsEncapBlk.attributes.to == "vlan-40"' - 'range_query_from_to_name.previous.0.fvnsEncapBlk.attributes.to == "vlan-40"'
- name: query vlan pool range - from and name are filtered - name: query vlan pool range - from and name are filtered
aci_encap_pool_range: aci_encap_pool_range:
@ -243,8 +244,8 @@
- range_query_from_name.changed == false - range_query_from_name.changed == false
- 'range_query_from_name.url.endswith("class/fvnsEncapBlk.json")' - 'range_query_from_name.url.endswith("class/fvnsEncapBlk.json")'
- '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.name, \"anstest\"))" in range_query_from_name.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.name, \"anstest\"))" in range_query_from_name.filter_string'
- 'range_query_from_name.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'range_query_from_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- 'range_query_from_name.existing.0.fvnsEncapBlk.attributes.from == "vlan-20"' - 'range_query_from_name.previous.0.fvnsEncapBlk.attributes.from == "vlan-20"'
- name: query vlan pool range - to and name are filtered - name: query vlan pool range - to and name are filtered
aci_encap_pool_range: aci_encap_pool_range:
@ -258,8 +259,8 @@
- range_query_to_name.changed == false - range_query_to_name.changed == false
- 'range_query_to_name.url.endswith("class/fvnsEncapBlk.json")' - 'range_query_to_name.url.endswith("class/fvnsEncapBlk.json")'
- '"query-target-filter=and(eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in range_query_to_name.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in range_query_to_name.filter_string'
- 'range_query_to_name.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'range_query_to_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- 'range_query_to_name.existing.0.fvnsEncapBlk.attributes.to == "vlan-40"' - 'range_query_to_name.previous.0.fvnsEncapBlk.attributes.to == "vlan-40"'
- name: query vlan pool range - name is filtered - name: query vlan pool range - name is filtered
aci_encap_pool_range: aci_encap_pool_range:
@ -274,7 +275,7 @@
- range_query_name.changed == false - range_query_name.changed == false
- 'range_query_name.url.endswith("class/fvnsEncapBlk.json")' - 'range_query_name.url.endswith("class/fvnsEncapBlk.json")'
- '"query-target-filter=eq(fvnsEncapBlk.name, \"anstest\")" in range_query_name.filter_string' - '"query-target-filter=eq(fvnsEncapBlk.name, \"anstest\")" in range_query_name.filter_string'
- 'range_query_name.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'range_query_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- name: query vlan pool range - from and to are filtered - name: query vlan pool range - from and to are filtered
aci_encap_pool_range: aci_encap_pool_range:
@ -288,8 +289,8 @@
- range_query_from_to.changed == false - range_query_from_to.changed == false
- 'range_query_from_to.url.endswith("class/fvnsEncapBlk.json")' - 'range_query_from_to.url.endswith("class/fvnsEncapBlk.json")'
- '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"))" in range_query_from_to.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"))" in range_query_from_to.filter_string'
- 'range_query_from_to.existing.0.fvnsEncapBlk.attributes.from == "vlan-20"' - 'range_query_from_to.previous.0.fvnsEncapBlk.attributes.from == "vlan-20"'
- 'range_query_from_to.existing.0.fvnsEncapBlk.attributes.to == "vlan-40"' - 'range_query_from_to.previous.0.fvnsEncapBlk.attributes.to == "vlan-40"'
- name: query all ranges in a vlan pool - name: query all ranges in a vlan pool
aci_encap_pool_range: aci_encap_pool_range:
@ -301,9 +302,9 @@
- name: query assertions - name: query assertions
assert: assert:
that: that:
- range_query_pool.existing | length == 1 - range_query_pool.previous | length == 1
- 'range_query_pool.existing.0.fvnsVlanInstP.attributes.name == "anstest"' - 'range_query_pool.previous.0.fvnsVlanInstP.attributes.name == "anstest"'
- range_query_pool.existing.0.fvnsVlanInstP.children | length > 1 - range_query_pool.previous.0.fvnsVlanInstP.children | length > 1
- 'range_query_pool.url.endswith("infra/vlanns-[anstest]-static.json")' - 'range_query_pool.url.endswith("infra/vlanns-[anstest]-static.json")'
- name: query all ranges - name: query all ranges
@ -317,8 +318,8 @@
assert: assert:
that: that:
- range_query_all.changed == false - range_query_all.changed == false
- range_query_all.existing | length > 1 - range_query_all.previous | length > 1
- range_query_all.existing.0.fvnsEncapBlk is defined - range_query_all.previous.0.fvnsEncapBlk is defined
- 'range_query_all.url.endswith("class/fvnsEncapBlk.json")' - 'range_query_all.url.endswith("class/fvnsEncapBlk.json")'
- name: delete vlan pool range - deletion works - name: delete vlan pool range - deletion works
@ -332,7 +333,7 @@
that: that:
- delete_range.changed == true - delete_range.changed == true
- delete_range.proposed == {} - delete_range.proposed == {}
- 'delete_range.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'delete_range.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- name: delete vlan pool range - check mode works - name: delete vlan pool range - check mode works
aci_encap_pool_range: &aci_range_absent aci_encap_pool_range: &aci_range_absent
@ -345,7 +346,7 @@
assert: assert:
that: that:
- delete_check_mode.changed == true - delete_check_mode.changed == true
- delete_check_mode.existing != [] - delete_check_mode.previous != []
- name: delete vlan pool range - deletion works - name: delete vlan pool range - deletion works
aci_encap_pool_range: aci_encap_pool_range:
@ -356,7 +357,7 @@
assert: assert:
that: that:
- delete_range_2.changed == true - delete_range_2.changed == true
- delete_range_2.existing == delete_check_mode.existing - delete_range_2.previous == delete_check_mode.previous
- name: delete vlan pool range again - idempotency works - name: delete vlan pool range again - idempotency works
aci_encap_pool_range: aci_encap_pool_range:
@ -367,7 +368,7 @@
assert: assert:
that: that:
- delete_idempotent.changed == false - delete_idempotent.changed == false
- delete_idempotent.existing == [] - delete_idempotent.previous == []
- name: cleanup vlan pool - name: cleanup vlan pool
aci_encap_pool: aci_encap_pool:

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -73,15 +74,15 @@
assert: assert:
that: that:
- epg_present_check_mode.changed == true - epg_present_check_mode.changed == true
- epg_present_check_mode.existing == [] - epg_present_check_mode.previous == []
- epg_present_check_mode.config.fvAEPg.attributes != {} - epg_present_check_mode.sent.fvAEPg.attributes != {}
- 'epg_present_check_mode.config.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == "anstest"' - 'epg_present_check_mode.sent.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == "anstest"'
- epg_present.changed == true - epg_present.changed == true
- epg_present.config == epg_present_check_mode.config - epg_present.sent == epg_present_check_mode.sent
- epg_present_idempotent.changed == false - epg_present_idempotent.changed == false
- epg_present_idempotent.config == {} - epg_present_idempotent.sent == {}
- epg_present_update.changed == true - epg_present_update.changed == true
- 'epg_present_update.config == {"fvAEPg": {"attributes": {"descr": "Ansible Test Update"}}}' - 'epg_present_update.sent == {"fvAEPg": {"attributes": {"descr": "Ansible Test Update"}}}'
- epg_present_missing_param.failed == true - epg_present_missing_param.failed == true
- 'epg_present_missing_param.msg == "state is present but all of the following are missing: ap"' - 'epg_present_missing_param.msg == "state is present but all of the following are missing: ap"'
@ -102,11 +103,11 @@
assert: assert:
that: that:
- epg_query.changed == false - epg_query.changed == false
- epg_query.existing | length == 1 - epg_query.previous | length == 1
- 'epg_query.existing.0.fvAEPg.attributes.name == "anstest"' - 'epg_query.previous.0.fvAEPg.attributes.name == "anstest"'
- '"tn-anstest/ap-anstest/epg-anstest.json" in epg_query.url' - '"tn-anstest/ap-anstest/epg-anstest.json" in epg_query.url'
- epg_query_all.changed == false - epg_query_all.changed == false
- epg_query_all.existing | length > 1 - epg_query_all.previous | length > 1
- '"rsp-subtree-class=fvRsBd" in epg_query_all.filter_string' - '"rsp-subtree-class=fvRsBd" in epg_query_all.filter_string'
- '"class/fvAEPg.json" in epg_query_all.url' - '"class/fvAEPg.json" in epg_query_all.url'
@ -143,11 +144,11 @@
assert: assert:
that: that:
- delete_epg_check_mode.changed == true - delete_epg_check_mode.changed == true
- delete_epg_check_mode.existing != [] - delete_epg_check_mode.previous != []
- delete_epg.changed == true - delete_epg.changed == true
- delete_epg.existing == delete_epg_check_mode.existing - delete_epg.previous == delete_epg_check_mode.previous
- delete_epg_idempotent.changed == false - delete_epg_idempotent.changed == false
- delete_epg_idempotent.existing == [] - delete_epg_idempotent.previous == []
- delete_epg_missing_param.failed == true - delete_epg_missing_param.failed == true
- 'delete_epg_missing_param.msg == "state is absent but all of the following are missing: tenant"' - 'delete_epg_missing_param.msg == "state is absent but all of the following are missing: tenant"'
@ -155,16 +156,16 @@
aci_bd: aci_bd:
<<: *aci_bd_present <<: *aci_bd_present
state: absent state: absent
when: bd_present.existing == [] when: bd_present.previous == []
- name: cleanup ap - name: cleanup ap
aci_ap: aci_ap:
<<: *aci_ap_present <<: *aci_ap_present
state: absent state: absent
when: ap_present.existing == [] when: ap_present.previous == []
- name: cleanup tenant - name: cleanup tenant
aci_tenant: aci_tenant:
<<: *aci_tenant_present <<: *aci_tenant_present
state: absent state: absent
when: tenant_present.existing == [] when: tenant_present.previous == []

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -94,15 +95,15 @@
assert: assert:
that: that:
- provide_present_check_mode.changed == true - provide_present_check_mode.changed == true
- 'provide_present_check_mode.config == {"fvRsProv": {"attributes": {"tnVzBrCPName": "anstest_http"}}}' - 'provide_present_check_mode.sent == {"fvRsProv": {"attributes": {"tnVzBrCPName": "anstest_http"}}}'
- provide_present.changed == true - provide_present.changed == true
- provide_present.config == provide_present_check_mode.config - provide_present.sent == provide_present_check_mode.sent
- provide_present.existing == [] - provide_present.previous == []
- consume_present.changed == true - consume_present.changed == true
- consume_present.existing == [] - consume_present.previous == []
- 'consume_present.config == {"fvRsCons": {"attributes": {"tnVzBrCPName": "anstest_db"}}}' - 'consume_present.sent == {"fvRsCons": {"attributes": {"tnVzBrCPName": "anstest_db"}}}'
- provide_present2.changed == true - provide_present2.changed == true
- provide_present2.existing == [] - provide_present2.previous == []
- missing_param_present.failed == true - missing_param_present.failed == true
- 'missing_param_present.msg == "state is present but all of the following are missing: ap, contract, epg"' - 'missing_param_present.msg == "state is present but all of the following are missing: ap, contract, epg"'
- missing_required_present.failed == true - missing_required_present.failed == true
@ -141,10 +142,10 @@
assert: assert:
that: that:
- query_provide_contract.changed == false - query_provide_contract.changed == false
- query_provide_contract.existing != [] - query_provide_contract.previous != []
- '"class/fvRsProv.json" in query_provide_contract.url' - '"class/fvRsProv.json" in query_provide_contract.url'
- query_consume_contract.changed == false - query_consume_contract.changed == false
- query_consume_contract.existing != [] - query_consume_contract.previous != []
- '"class/fvRsCons.json" in query_consume_contract.url' - '"class/fvRsCons.json" in query_consume_contract.url'
- query_all.changed == false - query_all.changed == false
- '"class/fvRsProv.json" in query_all.url' - '"class/fvRsProv.json" in query_all.url'
@ -198,14 +199,14 @@
assert: assert:
that: that:
- consume_absent_check_mode.changed == true - consume_absent_check_mode.changed == true
- consume_absent_check_mode.existing.0.fvRsCons is defined - consume_absent_check_mode.previous.0.fvRsCons is defined
- consume_absent.changed == true - consume_absent.changed == true
- consume_absent.existing == consume_absent_check_mode.existing - consume_absent.previous == consume_absent_check_mode.previous
- provide_absent.changed == true - provide_absent.changed == true
- provide_absent.existing.0.fvRsProv is defined - provide_absent.previous.0.fvRsProv is defined
- provide_absent2.changed == true - provide_absent2.changed == true
- consume_absent_idempotent.changed == false - consume_absent_idempotent.changed == false
- consume_absent_idempotent.existing == [] - consume_absent_idempotent.previous == []
- missing_param_absent.failed == true - missing_param_absent.failed == true
- 'missing_param_absent.msg == "state is absent but all of the following are missing: contract"' - 'missing_param_absent.msg == "state is absent but all of the following are missing: contract"'
- missing_required_absent.failed == true - missing_required_absent.failed == true

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -110,15 +111,15 @@
that: that:
- phys_check_mode_present.changed == true - phys_check_mode_present.changed == true
- phys_present.changed == true - phys_present.changed == true
- phys_present.existing == [] - phys_present.previous == []
- 'phys_present.config == {"fvRsDomAtt": {"attributes": {}}}' - 'phys_present.sent == {"fvRsDomAtt": {"attributes": {}}}'
- '"[uni/phys-anstest].json" in phys_present.url' - '"[uni/phys-anstest].json" in phys_present.url'
- phys_idempotent.changed == false - phys_idempotent.changed == false
- phys_idempotent.config == {} - phys_idempotent.sent == {}
- phys_update.changed == true - phys_update.changed == true
- 'phys_update.config == {"fvRsDomAtt": {"attributes": {"instrImedcy": "immediate"}}}' - 'phys_update.sent == {"fvRsDomAtt": {"attributes": {"instrImedcy": "immediate"}}}'
- vmm_present.changed == true - vmm_present.changed == true
- 'vmm_present.config == {"fvRsDomAtt": {"attributes": {"resImedcy": "pre-provision"}}}' - 'vmm_present.sent == {"fvRsDomAtt": {"attributes": {"resImedcy": "pre-provision"}}}'
- '"[uni/vmmp-VMware/dom-anstest].json" in vmm_present.url' - '"[uni/vmmp-VMware/dom-anstest].json" in vmm_present.url'
- present_missing_params.failed == true - present_missing_params.failed == true
- 'present_missing_params.msg == "domain_type is vmm but all of the following are missing: vm_provider"' - 'present_missing_params.msg == "domain_type is vmm but all of the following are missing: vm_provider"'
@ -138,7 +139,7 @@
assert: assert:
that: that:
- binding_query.changed == false - binding_query.changed == false
- binding_query.existing | length > 1 - binding_query.previous | length > 1
- '"class/fvRsDomAtt.json" in binding_query.url' - '"class/fvRsDomAtt.json" in binding_query.url'
- name: delete domain epg binding - check mode - name: delete domain epg binding - check mode
@ -175,12 +176,12 @@
assert: assert:
that: that:
- epg_domain_check_mode_absent.changed == true - epg_domain_check_mode_absent.changed == true
- epg_domain_check_mode_absent.existing != [] - epg_domain_check_mode_absent.previous != []
- epg_domain_absent.changed == true - epg_domain_absent.changed == true
- epg_domain_absent.existing == epg_domain_check_mode_absent.existing - epg_domain_absent.previous == epg_domain_check_mode_absent.previous
- epg_vmm_domain_absent.changed == true - epg_vmm_domain_absent.changed == true
- idempotency_absent.changed == false - idempotency_absent.changed == false
- idempotency_absent.existing == [] - idempotency_absent.previous == []
- absent_missing_param.failed == true - absent_missing_param.failed == true
- 'absent_missing_param.msg == "state is absent but all of the following are missing: ap, domain, domain_type, epg"' - 'absent_missing_param.msg == "state is absent but all of the following are missing: ap, domain, domain_type, epg"'

View file

@ -27,6 +27,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -110,23 +111,23 @@
assert: assert:
that: that:
- entry_present_check_mode.changed == true - entry_present_check_mode.changed == true
- entry_present_check_mode.existing == [] - entry_present_check_mode.previous == []
- 'entry_present_check_mode.config == {"vzEntry": {"attributes": {"dFromPort": "http","dToPort": "88","descr": "Ansible Test","etherT": "ip","name": "anstest","prot": "tcp"}}}' - 'entry_present_check_mode.sent == {"vzEntry": {"attributes": {"dFromPort": "http","dToPort": "88","descr": "Ansible Test","etherT": "ip","name": "anstest","prot": "tcp"}}}'
- entry_present.changed == true - entry_present.changed == true
- entry_present.existing == [] - entry_present.previous == []
- entry_present.config == entry_present_check_mode.config - entry_present.sent == entry_present_check_mode.sent
- entry_present_idempotent.changed == false - entry_present_idempotent.changed == false
- entry_present_idempotent.existing != [] - entry_present_idempotent.previous != []
- entry_present_idempotent.config == {} - entry_present_idempotent.sent == {}
- entry_present_update.changed == true - entry_present_update.changed == true
- entry_present_update.existing != [] - entry_present_update.previous != []
- entry_present_update.config != entry_present_update.proposed - entry_present_update.sent != entry_present_update.proposed
- entry_present_2.changed == true - entry_present_2.changed == true
- 'entry_present_2.config.vzEntry.attributes == {"arpOpc": "reply", "etherT": "arp", "name": "anstest2"}' - 'entry_present_2.sent.vzEntry.attributes == {"arpOpc": "reply", "etherT": "arp", "name": "anstest2"}'
- entry_present_3.changed == true - entry_present_3.changed == true
- 'entry_present_3.config.vzEntry.attributes == {"etherT": "ip", "icmpv4T": "echo", "name": "anstest3", "prot": "icmp"}' - 'entry_present_3.sent.vzEntry.attributes == {"etherT": "ip", "icmpv4T": "echo", "name": "anstest3", "prot": "icmp"}'
- entry_present_4.changed == true - entry_present_4.changed == true
- 'entry_present_4.config.vzEntry.attributes == {"dFromPort": "1000", "dToPort": "1000", "etherT": "ip", "name": "anstest4", "prot": "udp"}' - 'entry_present_4.sent.vzEntry.attributes == {"dFromPort": "1000", "dToPort": "1000", "etherT": "ip", "name": "anstest4", "prot": "udp"}'
- present_missing_param.failed == true - present_missing_param.failed == true
- 'present_missing_param.msg == "state is present but all of the following are missing: entry"' - 'present_missing_param.msg == "state is present but all of the following are missing: entry"'
- present_incompatible_params.failed == true - present_incompatible_params.failed == true
@ -187,44 +188,44 @@
assert: assert:
that: that:
- query_tenant_filter_entry.changed == false - query_tenant_filter_entry.changed == false
- query_tenant_filter_entry.existing | length == 1 - query_tenant_filter_entry.previous | length == 1
- 'query_tenant_filter_entry.existing.0.vzEntry.attributes.name == "anstest"' - 'query_tenant_filter_entry.previous.0.vzEntry.attributes.name == "anstest"'
- '"tn-anstest/flt-anstest/e-anstest.json" in query_tenant_filter_entry.url' - '"tn-anstest/flt-anstest/e-anstest.json" in query_tenant_filter_entry.url'
- query_filter_entry.changed == false - query_filter_entry.changed == false
- 'query_filter_entry.existing.0.vzFilter.attributes.name == "anstest"' - 'query_filter_entry.previous.0.vzFilter.attributes.name == "anstest"'
- query_filter_entry.existing.0.vzFilter.children | length == 1 - query_filter_entry.previous.0.vzFilter.children | length == 1
- '"query-target-filter=eq(vzFilter.name, \"anstest\")" in query_filter_entry.filter_string' - '"query-target-filter=eq(vzFilter.name, \"anstest\")" in query_filter_entry.filter_string'
- '"rsp-subtree-filter=eq(vzEntry.name, \"anstest\")" in query_filter_entry.filter_string' - '"rsp-subtree-filter=eq(vzEntry.name, \"anstest\")" in query_filter_entry.filter_string'
- '"class/vzFilter.json" in query_filter_entry.url' - '"class/vzFilter.json" in query_filter_entry.url'
- query_tenant_entry.changed == false - query_tenant_entry.changed == false
- query_tenant_entry.existing | length == 1 - query_tenant_entry.previous | length == 1
- 'query_tenant_entry.existing.0.fvTenant.attributes.name == "anstest"' - 'query_tenant_entry.previous.0.fvTenant.attributes.name == "anstest"'
- '"rsp-subtree-filter=eq(vzEntry.name, \"anstest\")" in query_tenant_entry.filter_string' - '"rsp-subtree-filter=eq(vzEntry.name, \"anstest\")" in query_tenant_entry.filter_string'
- '"rsp-subtree-class=vzEntry" in query_tenant_entry.filter_string' - '"rsp-subtree-class=vzEntry" in query_tenant_entry.filter_string'
- '"tn-anstest.json" in query_tenant_entry.url' - '"tn-anstest.json" in query_tenant_entry.url'
- query_tenant_filter.changed == false - query_tenant_filter.changed == false
- query_tenant_filter.existing | length == 1 - query_tenant_filter.previous | length == 1
- 'query_tenant_filter.existing.0.vzFilter.attributes.name == "anstest"' - 'query_tenant_filter.previous.0.vzFilter.attributes.name == "anstest"'
- query_tenant_filter.existing.0.vzFilter.children | length == 4 - query_tenant_filter.previous.0.vzFilter.children | length == 4
- '"rsp-subtree-class=vzEntry" in query_tenant_filter.filter_string' - '"rsp-subtree-class=vzEntry" in query_tenant_filter.filter_string'
- '"tn-anstest/flt-anstest.json" in query_tenant_filter.url' - '"tn-anstest/flt-anstest.json" in query_tenant_filter.url'
- query_entry.changed == false - query_entry.changed == false
- 'query_entry.existing.0.vzEntry.attributes.name == "anstest"' - 'query_entry.previous.0.vzEntry.attributes.name == "anstest"'
- '"query-target-filter=eq(vzEntry.name, \"anstest\")" in query_entry.filter_string' - '"query-target-filter=eq(vzEntry.name, \"anstest\")" in query_entry.filter_string'
- '"class/vzEntry.json" in query_entry.url' - '"class/vzEntry.json" in query_entry.url'
- query_filter.changed == false - query_filter.changed == false
- 'query_filter.existing.0.vzFilter.attributes.name == "anstest"' - 'query_filter.previous.0.vzFilter.attributes.name == "anstest"'
- '"query-target-filter=eq(vzFilter.name, \"anstest\")" in query_filter.filter_string' - '"query-target-filter=eq(vzFilter.name, \"anstest\")" in query_filter.filter_string'
- '"rsp-subtree-class=vzEntry" in query_filter.filter_string' - '"rsp-subtree-class=vzEntry" in query_filter.filter_string'
- '"class/vzFilter.json" in query_filter.url' - '"class/vzFilter.json" in query_filter.url'
- query_tenant.changed == false - query_tenant.changed == false
- query_tenant.existing | length == 1 - query_tenant.previous | length == 1
- 'query_tenant.existing.0.fvTenant.attributes.name == "anstest"' - 'query_tenant.previous.0.fvTenant.attributes.name == "anstest"'
- '"rsp-subtree-class=vzFilter,vzEntry" in query_tenant.filter_string' - '"rsp-subtree-class=vzFilter,vzEntry" in query_tenant.filter_string'
- '"tn-anstest.json" in query_tenant.url' - '"tn-anstest.json" in query_tenant.url'
- query_all.changed == false - query_all.changed == false
- query_all.existing | length > 1 - query_all.previous | length > 1
- query_all.existing.0.vzEntry is defined - query_all.previous.0.vzEntry is defined
- '"class/vzEntry.json" in query_all.url' - '"class/vzEntry.json" in query_all.url'
- name: delete entry - check mode works - name: delete entry - check mode works
@ -261,12 +262,12 @@
assert: assert:
that: that:
- entry_absent_check_mode.changed == true - entry_absent_check_mode.changed == true
- entry_absent_check_mode.existing != [] - entry_absent_check_mode.previous != []
- entry_absent.changed == true - entry_absent.changed == true
- entry_absent.existing == entry_absent_check_mode.existing - entry_absent.previous == entry_absent_check_mode.previous
- entry_absent.proposed == {} - entry_absent.proposed == {}
- entry_absent_idempotent.changed == false - entry_absent_idempotent.changed == false
- entry_absent_idempotent.existing == [] - entry_absent_idempotent.previous == []
- absent_missing_param.failed == true - absent_missing_param.failed == true
- 'absent_missing_param.msg == "state is absent but all of the following are missing: entry, filter"' - 'absent_missing_param.msg == "state is absent but all of the following are missing: entry, filter"'

View file

@ -38,6 +38,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
leaf_profile: swleafprftest leaf_profile: swleafprftest
state: present state: present
register: leaf_profile_present register: leaf_profile_present
@ -50,6 +51,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: info
leaf_interface_profile: leafintprftest leaf_interface_profile: leafintprftest
state: present state: present
register: leaf_profile_present register: leaf_profile_present
@ -77,10 +79,10 @@
that: that:
- intftoleaf_check_mode_present.changed == true - intftoleaf_check_mode_present.changed == true
- intftoleaf_present.changed == true - intftoleaf_present.changed == true
- intftoleaf_present.existing == [] - intftoleaf_present.previous == []
- 'intftoleaf_present.config == {"infraRsAccPortP": {"attributes": {"tDn": "uni/infra/accportprof-leafintprftest"}}}' - 'intftoleaf_present.sent == {"infraRsAccPortP": {"attributes": {"tDn": "uni/infra/accportprof-leafintprftest"}}}'
- intftoleaf_idempotent.changed == false - intftoleaf_idempotent.changed == false
- intftoleaf_idempotent.config == {} - intftoleaf_idempotent.sent == {}
- name: Query an interface selector profile associated with a switch policy leaf profile - name: Query an interface selector profile associated with a switch policy leaf profile
aci_interface_selector_to_switch_policy_leaf_profile: aci_interface_selector_to_switch_policy_leaf_profile:
@ -93,7 +95,7 @@
assert: assert:
that: that:
- binding_query.changed == false - binding_query.changed == false
- binding_query.existing | length >= 1 - binding_query.previous | length >= 1
- '"api/mo/uni/infra/nprof-swleafprftest/rsaccPortP-[uni/infra/accportprof-leafintprftest].json" in binding_query.url' - '"api/mo/uni/infra/nprof-swleafprftest/rsaccPortP-[uni/infra/accportprof-leafintprftest].json" in binding_query.url'
- name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
@ -125,11 +127,11 @@
assert: assert:
that: that:
- intftoleaf_check_mode_absent.changed == true - intftoleaf_check_mode_absent.changed == true
- intftoleaf_check_mode_absent.existing != [] - intftoleaf_check_mode_absent.previous != []
- intftoleaf_absent.changed == true - intftoleaf_absent.changed == true
- intftoleaf_absent.existing == intftoleaf_check_mode_absent.existing - intftoleaf_absent.previous == intftoleaf_check_mode_absent.previous
- intftoleaf_absent_idempotent.changed == false - intftoleaf_absent_idempotent.changed == false
- intftoleaf_absent_idempotent.existing == [] - intftoleaf_absent_idempotent.previous == []
- intftoleaf_absent_missing_param.failed == true - intftoleaf_absent_missing_param.failed == true
- 'intftoleaf_absent_missing_param.msg == "state is absent but all of the following are missing: interface_selector"' - 'intftoleaf_absent_missing_param.msg == "state is absent but all of the following are missing: interface_selector"'

View file

@ -27,6 +27,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
leaf_profile: sw_name_test leaf_profile: sw_name_test
state: present state: present
register: leaf_profile_present register: leaf_profile_present
@ -65,12 +66,12 @@
that: that:
- sw_leaf_selec_check_mode_present.changed == true - sw_leaf_selec_check_mode_present.changed == true
- sw_leaf_selec_present.changed == true - sw_leaf_selec_present.changed == true
- sw_leaf_selec_present.existing == [] - sw_leaf_selec_present.previous == []
- 'sw_leaf_selec_present.config == {"infraLeafS": {"attributes": {"name": "leaf_selector_name"}, "children": [{"infraNodeBlk": {"attributes": {"from_": "1011", "name": "node_blk_name", "to_": "1011"}}},{"infraRsAccNodePGrp": {"attributes": {"tDn": "uni/infra/funcprof/accnodepgrp-None"}}}]}}' - 'sw_leaf_selec_present.sent == {"infraLeafS": {"attributes": {"name": "leaf_selector_name"}, "children": [{"infraNodeBlk": {"attributes": {"from_": "1011", "name": "node_blk_name", "to_": "1011"}}},{"infraRsAccNodePGrp": {"attributes": {"tDn": "uni/infra/funcprof/accnodepgrp-None"}}}]}}'
- sw_leaf_selec_idempotent.changed == false - sw_leaf_selec_idempotent.changed == false
- sw_leaf_selec_idempotent.config == {} - sw_leaf_selec_idempotent.sent == {}
- sw_leaf_selec_update.changed == true - sw_leaf_selec_update.changed == true
- 'sw_leaf_selec_update.config == {"infraLeafS": {"attributes": {},"children": [{"infraRsAccNodePGrp": {"attributes": {"tDn": "uni/infra/funcprof/accnodepgrp-anstest_policygroupname"}}}]}}' - 'sw_leaf_selec_update.sent == {"infraLeafS": {"attributes": {},"children": [{"infraRsAccNodePGrp": {"attributes": {"tDn": "uni/infra/funcprof/accnodepgrp-anstest_policygroupname"}}}]}}'
- name: Query Specific switch policy leaf profile selector - name: Query Specific switch policy leaf profile selector
aci_switch_leaf_selector: aci_switch_leaf_selector:
@ -83,7 +84,7 @@
assert: assert:
that: that:
- binding_query.changed == false - binding_query.changed == false
- binding_query.existing | length >= 1 - binding_query.previous | length >= 1
- '"api/mo/uni/infra/nprof-sw_name_test/leaves-leaf_selector_name-typ-range.json" in binding_query.url' - '"api/mo/uni/infra/nprof-sw_name_test/leaves-leaf_selector_name-typ-range.json" in binding_query.url'
- name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
@ -116,11 +117,11 @@
assert: assert:
that: that:
- sw_leaf_selec_check_mode_absent.changed == true - sw_leaf_selec_check_mode_absent.changed == true
- sw_leaf_selec_check_mode_absent.existing != [] - sw_leaf_selec_check_mode_absent.previous != []
- sw_leaf_selec_absent.changed == true - sw_leaf_selec_absent.changed == true
- sw_leaf_selec_absent.existing == sw_leaf_selec_check_mode_absent.existing - sw_leaf_selec_absent.previous == sw_leaf_selec_check_mode_absent.previous
- sw_leaf_selec_absent_idempotent.changed == false - sw_leaf_selec_absent_idempotent.changed == false
- sw_leaf_selec_absent_idempotent.existing == [] - sw_leaf_selec_absent_idempotent.previous == []
- sw_leaf_selec_absent_missing_param.failed == true - sw_leaf_selec_absent_missing_param.failed == true
- 'sw_leaf_selec_absent_missing_param.msg == "state is absent but all of the following are missing: leaf"' - 'sw_leaf_selec_absent_missing_param.msg == "state is absent but all of the following are missing: leaf"'

View file

@ -17,6 +17,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: absent state: absent
pool: anstest pool: anstest
allocation_mode: static allocation_mode: static
@ -38,7 +39,7 @@
assert: assert:
that: that:
- create_check_mode.changed == true - create_check_mode.changed == true
- 'create_check_mode.config == {"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "name": "anstest"}}}' - 'create_check_mode.sent == {"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "name": "anstest"}}}'
- name: Create static vlan pool - creation works - name: Create static vlan pool - creation works
aci_vlan_pool: aci_vlan_pool:
@ -49,8 +50,8 @@
assert: assert:
that: that:
- create_static.changed == true - create_static.changed == true
- create_static.existing == [] - create_static.previous == []
- create_static.config == create_check_mode.config - create_static.sent == create_check_mode.sent
- name: Create dynamic vlan pool - creation works - name: Create dynamic vlan pool - creation works
aci_vlan_pool: &aci_pool_present_dynamic aci_vlan_pool: &aci_pool_present_dynamic
@ -63,8 +64,8 @@
assert: assert:
that: that:
- create_dynamic.changed == true - create_dynamic.changed == true
- create_dynamic.existing == [] - create_dynamic.previous == []
- 'create_dynamic.config == {"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "name": "anstest"}}}' - 'create_dynamic.sent == {"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "name": "anstest"}}}'
- name: Create static vlan pool again - idempotency works - name: Create static vlan pool again - idempotency works
aci_vlan_pool: aci_vlan_pool:
@ -75,8 +76,8 @@
assert: assert:
that: that:
- idempotent_static.changed == false - idempotent_static.changed == false
- 'idempotent_static.existing == [{"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-static", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]' - 'idempotent_static.previous == [{"fvnsVlanInstP": {"attributes": {"allocMode": "static", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-static", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]'
- idempotent_static.config == {} - idempotent_static.sent == {}
- name: Create dynamic vlan pool again - idempotency works - name: Create dynamic vlan pool again - idempotency works
aci_vlan_pool: aci_vlan_pool:
@ -87,8 +88,8 @@
assert: assert:
that: that:
- idempotent_dynamic.changed == false - idempotent_dynamic.changed == false
- 'idempotent_dynamic.existing == [{"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-dynamic", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]' - 'idempotent_dynamic.previous == [{"fvnsVlanInstP": {"attributes": {"allocMode": "dynamic", "descr": "Ansible Test", "dn": "uni/infra/vlanns-[anstest]-dynamic", "name": "anstest", "nameAlias": "", "ownerKey": "", "ownerTag": ""}}}]'
- idempotent_dynamic.config == {} - idempotent_dynamic.sent == {}
- name: Update static vlan pool - update works - name: Update static vlan pool - update works
aci_vlan_pool: aci_vlan_pool:
@ -100,7 +101,7 @@
assert: assert:
that: that:
- update_static.changed == true - update_static.changed == true
- 'update_static.config == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}' - 'update_static.sent == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}'
- name: Update dynamic vlan pool - update works - name: Update dynamic vlan pool - update works
aci_vlan_pool: aci_vlan_pool:
@ -112,7 +113,7 @@
assert: assert:
that: that:
- update_dynamic.changed == true - update_dynamic.changed == true
- 'update_dynamic.config == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}' - 'update_dynamic.sent == {"fvnsVlanInstP": {"attributes": {"descr": "Ansible Test Change"}}}'
- name: Missing param - failure message works - name: Missing param - failure message works
aci_vlan_pool: aci_vlan_pool:
@ -153,7 +154,7 @@
that: that:
- get_all_pools.changed == false - get_all_pools.changed == false
- get_all_pools.method == "GET" - get_all_pools.method == "GET"
- get_all_pools.existing | length > 1 - get_all_pools.previous | length > 1
- name: Get created static vlan pool - get mo works - name: Get created static vlan pool - get mo works
aci_vlan_pool: aci_vlan_pool:
@ -166,9 +167,9 @@
that: that:
- get_static_pool.changed == false - get_static_pool.changed == false
- get_static_pool.method == "GET" - get_static_pool.method == "GET"
- get_static_pool.existing | length == 1 - get_static_pool.previous | length == 1
- get_static_pool.existing.0.fvnsVlanInstP.attributes.allocMode == "static" - get_static_pool.previous.0.fvnsVlanInstP.attributes.allocMode == "static"
- get_static_pool.existing.0.fvnsVlanInstP.attributes.name == "anstest" - get_static_pool.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: Get created dynamic vlan pool - get mo works - name: Get created dynamic vlan pool - get mo works
aci_vlan_pool: aci_vlan_pool:
@ -181,9 +182,9 @@
that: that:
- get_dynamic_pool.changed == false - get_dynamic_pool.changed == false
- get_dynamic_pool.method == "GET" - get_dynamic_pool.method == "GET"
- get_dynamic_pool.existing | length == 1 - get_dynamic_pool.previous | length == 1
- get_dynamic_pool.existing.0.fvnsVlanInstP.attributes.allocMode == "dynamic" - get_dynamic_pool.previous.0.fvnsVlanInstP.attributes.allocMode == "dynamic"
- get_dynamic_pool.existing.0.fvnsVlanInstP.attributes.name == "anstest" - get_dynamic_pool.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: Delete static vlan pool - deletion works - name: Delete static vlan pool - deletion works
aci_vlan_pool: aci_vlan_pool:
@ -195,8 +196,8 @@
that: that:
- delete_static.changed == true - delete_static.changed == true
- delete_static.method == "DELETE" - delete_static.method == "DELETE"
- delete_static.existing.0.fvnsVlanInstP.attributes.allocMode == "static" - delete_static.previous.0.fvnsVlanInstP.attributes.allocMode == "static"
- delete_static.existing.0.fvnsVlanInstP.attributes.name == "anstest" - delete_static.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: Delete dynamic vlan pool - check mode works - name: Delete dynamic vlan pool - check mode works
aci_vlan_pool: aci_vlan_pool:
@ -219,8 +220,8 @@
that: that:
- delete_dynamic.changed == true - delete_dynamic.changed == true
- delete_dynamic.method == "DELETE" - delete_dynamic.method == "DELETE"
- delete_dynamic.existing.0.fvnsVlanInstP.attributes.allocMode == "dynamic" - delete_dynamic.previous.0.fvnsVlanInstP.attributes.allocMode == "dynamic"
- delete_dynamic.existing.0.fvnsVlanInstP.attributes.name == "anstest" - delete_dynamic.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- name: Delete static vlan pool again - idempotency works - name: Delete static vlan pool again - idempotency works
aci_vlan_pool: aci_vlan_pool:
@ -231,7 +232,7 @@
assert: assert:
that: that:
- idempotent_delete_static.changed == false - idempotent_delete_static.changed == false
- idempotent_delete_static.existing == [] - idempotent_delete_static.previous == []
- name: Delete dynamic vlan pool again - idempotency works - name: Delete dynamic vlan pool again - idempotency works
aci_vlan_pool: aci_vlan_pool:
@ -242,4 +243,4 @@
assert: assert:
that: that:
- idempotent_delete_dynamic.changed == false - idempotent_delete_dynamic.changed == false
- idempotent_delete_dynamic.existing == [] - idempotent_delete_dynamic.previous == []

View file

@ -30,6 +30,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
pool: anstest pool: anstest
allocation_mode: static allocation_mode: static
@ -53,7 +54,7 @@
assert: assert:
that: that:
- encap_block_present_check_mode.changed == true - encap_block_present_check_mode.changed == true
- 'encap_block_present_check_mode.config == {"fvnsEncapBlk": {"attributes": {"allocMode": "inherit", "descr": "Ansible Test", "from": "vlan-20", "name": "anstest", "to": "vlan-40"}}}' - 'encap_block_present_check_mode.sent == {"fvnsEncapBlk": {"attributes": {"allocMode": "inherit", "descr": "Ansible Test", "from": "vlan-20", "name": "anstest", "to": "vlan-40"}}}'
- name: Create vlan pool encap_block - creation works - name: Create vlan pool encap_block - creation works
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -64,9 +65,9 @@
assert: assert:
that: that:
- encap_block_present.changed == true - encap_block_present.changed == true
- encap_block_present.existing == [] - encap_block_present.previous == []
- encap_block_present.config == encap_block_present_check_mode.config - encap_block_present.sent == encap_block_present_check_mode.sent
- encap_block_present.config == encap_block_present.proposed - encap_block_present.sent == encap_block_present.proposed
- name: Create vlan pool range - idempotency works - name: Create vlan pool range - idempotency works
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -77,7 +78,7 @@
assert: assert:
that: that:
- encap_block_present_idempotent.changed == false - encap_block_present_idempotent.changed == false
- 'encap_block_present_idempotent.existing.0.fvnsEncapBlk.attributes.name == "anstest"' - 'encap_block_present_idempotent.previous.0.fvnsEncapBlk.attributes.name == "anstest"'
- name: Update vlan pool range - update works - name: Update vlan pool range - update works
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -90,8 +91,8 @@
assert: assert:
that: that:
- encap_block_present_update.changed == true - encap_block_present_update.changed == true
- encap_block_present_update.existing != [] - encap_block_present_update.previous != []
- encap_block_present_update.config != encap_block_present.config - encap_block_present_update.sent != encap_block_present.sent
- name: Create vlan pool range - used for query - name: Create vlan pool range - used for query
aci_vlan_pool_encap_block: &aci_encap_block_present_2 aci_vlan_pool_encap_block: &aci_encap_block_present_2
@ -105,7 +106,7 @@
assert: assert:
that: that:
- encap_block_present_2.changed == true - encap_block_present_2.changed == true
- encap_block_present_2.existing == [] - encap_block_present_2.previous == []
- name: Invalid encap_block_start - error message works - name: Invalid encap_block_start - error message works
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -208,8 +209,8 @@
that: that:
- encap_block_query.changed == false - encap_block_query.changed == false
- encap_block_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json") - encap_block_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json")
- encap_block_query.existing | length == 1 - encap_block_query.previous | length == 1
- encap_block_query.existing.0.fvnsEncapBlk.attributes.name == "anstest" - encap_block_query.previous.0.fvnsEncapBlk.attributes.name == "anstest"
- name: Query vlan pool range - from, to, and name are filtered - name: Query vlan pool range - from, to, and name are filtered
aci_vlan_pool_encap_block: &aci_encap_block_query_filter aci_vlan_pool_encap_block: &aci_encap_block_query_filter
@ -223,9 +224,9 @@
- encap_block_query_from_to_name.changed == false - encap_block_query_from_to_name.changed == false
- encap_block_query_from_to_name.url.endswith("class/fvnsEncapBlk.json") - encap_block_query_from_to_name.url.endswith("class/fvnsEncapBlk.json")
- '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in encap_block_query_from_to_name.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in encap_block_query_from_to_name.filter_string'
- encap_block_query_from_to_name.existing.0.fvnsEncapBlk.attributes.name == "anstest" - encap_block_query_from_to_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"
- encap_block_query_from_to_name.existing.0.fvnsEncapBlk.attributes.from == "vlan-20" - encap_block_query_from_to_name.previous.0.fvnsEncapBlk.attributes.from == "vlan-20"
- encap_block_query_from_to_name.existing.0.fvnsEncapBlk.attributes.to == "vlan-40" - encap_block_query_from_to_name.previous.0.fvnsEncapBlk.attributes.to == "vlan-40"
- name: Query vlan pool range - from and name are filtered - name: Query vlan pool range - from and name are filtered
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -239,8 +240,8 @@
- encap_block_query_from_name.changed == false - encap_block_query_from_name.changed == false
- encap_block_query_from_name.url.endswith("class/fvnsEncapBlk.json") - encap_block_query_from_name.url.endswith("class/fvnsEncapBlk.json")
- '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.name, \"anstest\"))" in encap_block_query_from_name.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.name, \"anstest\"))" in encap_block_query_from_name.filter_string'
- encap_block_query_from_name.existing.0.fvnsEncapBlk.attributes.name == "anstest" - encap_block_query_from_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"
- encap_block_query_from_name.existing.0.fvnsEncapBlk.attributes.from == "vlan-20" - encap_block_query_from_name.previous.0.fvnsEncapBlk.attributes.from == "vlan-20"
- name: Query vlan pool range - to and name are filtered - name: Query vlan pool range - to and name are filtered
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -254,8 +255,8 @@
- encap_block_query_to_name.changed == false - encap_block_query_to_name.changed == false
- encap_block_query_to_name.url.endswith("class/fvnsEncapBlk.json") - encap_block_query_to_name.url.endswith("class/fvnsEncapBlk.json")
- '"query-target-filter=and(eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in encap_block_query_to_name.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.to, \"vlan-40\"),eq(fvnsEncapBlk.name, \"anstest\"))" in encap_block_query_to_name.filter_string'
- encap_block_query_to_name.existing.0.fvnsEncapBlk.attributes.name == "anstest" - encap_block_query_to_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"
- encap_block_query_to_name.existing.0.fvnsEncapBlk.attributes.to == "vlan-40" - encap_block_query_to_name.previous.0.fvnsEncapBlk.attributes.to == "vlan-40"
- name: Query vlan pool range - name is filtered - name: Query vlan pool range - name is filtered
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -270,7 +271,7 @@
- encap_block_query_name.changed == false - encap_block_query_name.changed == false
- encap_block_query_name.url.endswith("class/fvnsEncapBlk.json") - encap_block_query_name.url.endswith("class/fvnsEncapBlk.json")
- '"query-target-filter=eq(fvnsEncapBlk.name, \"anstest\")" in encap_block_query_name.filter_string' - '"query-target-filter=eq(fvnsEncapBlk.name, \"anstest\")" in encap_block_query_name.filter_string'
- encap_block_query_name.existing.0.fvnsEncapBlk.attributes.name == "anstest" - encap_block_query_name.previous.0.fvnsEncapBlk.attributes.name == "anstest"
- name: Query vlan pool range - from and to are filtered - name: Query vlan pool range - from and to are filtered
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -284,8 +285,8 @@
- encap_block_query_from_to.changed == false - encap_block_query_from_to.changed == false
- encap_block_query_from_to.url.endswith("class/fvnsEncapBlk.json") - encap_block_query_from_to.url.endswith("class/fvnsEncapBlk.json")
- '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"))" in encap_block_query_from_to.filter_string' - '"query-target-filter=and(eq(fvnsEncapBlk.from, \"vlan-20\"),eq(fvnsEncapBlk.to, \"vlan-40\"))" in encap_block_query_from_to.filter_string'
- encap_block_query_from_to.existing.0.fvnsEncapBlk.attributes.from == "vlan-20" - encap_block_query_from_to.previous.0.fvnsEncapBlk.attributes.from == "vlan-20"
- encap_block_query_from_to.existing.0.fvnsEncapBlk.attributes.to == "vlan-40" - encap_block_query_from_to.previous.0.fvnsEncapBlk.attributes.to == "vlan-40"
- name: Query all ranges in a vlan pool - name: Query all ranges in a vlan pool
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -297,9 +298,9 @@
- name: Query assertions - name: Query assertions
assert: assert:
that: that:
- encap_block_query_pool.existing | length == 1 - encap_block_query_pool.previous | length == 1
- encap_block_query_pool.existing.0.fvnsVlanInstP.attributes.name == "anstest" - encap_block_query_pool.previous.0.fvnsVlanInstP.attributes.name == "anstest"
- encap_block_query_pool.existing.0.fvnsVlanInstP.children | length > 1 - encap_block_query_pool.previous.0.fvnsVlanInstP.children | length > 1
- encap_block_query_pool.url.endswith("infra/vlanns-[anstest]-static.json") - encap_block_query_pool.url.endswith("infra/vlanns-[anstest]-static.json")
- name: Query all ranges - name: Query all ranges
@ -313,8 +314,8 @@
assert: assert:
that: that:
- encap_block_query_all.changed == false - encap_block_query_all.changed == false
- encap_block_query_all.existing | length > 1 - encap_block_query_all.previous | length > 1
- encap_block_query_all.existing.0.fvnsEncapBlk is defined - encap_block_query_all.previous.0.fvnsEncapBlk is defined
- encap_block_query_all.url.endswith("class/fvnsEncapBlk.json") - encap_block_query_all.url.endswith("class/fvnsEncapBlk.json")
- name: Delete vlan pool range - deletion works - name: Delete vlan pool range - deletion works
@ -328,7 +329,7 @@
that: that:
- delete_range.changed == true - delete_range.changed == true
- delete_range.proposed == {} - delete_range.proposed == {}
- delete_range.existing.0.fvnsEncapBlk.attributes.name == "anstest" - delete_range.previous.0.fvnsEncapBlk.attributes.name == "anstest"
- name: Delete vlan pool range - check mode works - name: Delete vlan pool range - check mode works
aci_vlan_pool_encap_block: &aci_encap_block_absent aci_vlan_pool_encap_block: &aci_encap_block_absent
@ -341,7 +342,7 @@
assert: assert:
that: that:
- delete_check_mode.changed == true - delete_check_mode.changed == true
- delete_check_mode.existing != [] - delete_check_mode.previous != []
- name: Delete vlan pool range - deletion works - name: Delete vlan pool range - deletion works
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -352,7 +353,7 @@
assert: assert:
that: that:
- delete_encap_block_2.changed == true - delete_encap_block_2.changed == true
- delete_encap_block_2.existing == delete_check_mode.existing - delete_encap_block_2.previous == delete_check_mode.previous
- name: Delete vlan pool range again - idempotency works - name: Delete vlan pool range again - idempotency works
aci_vlan_pool_encap_block: aci_vlan_pool_encap_block:
@ -363,7 +364,7 @@
assert: assert:
that: that:
- delete_idempotent.changed == false - delete_idempotent.changed == false
- delete_idempotent.existing == [] - delete_idempotent.previous == []
- name: Cleanup vlan pool - name: Cleanup vlan pool
aci_vlan_pool: aci_vlan_pool:

View file

@ -16,6 +16,7 @@
validate_certs: '{{ aci_validate_certs | default(false) }}' validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}' use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: debug
state: present state: present
tenant: anstest tenant: anstest
register: tenant_present register: tenant_present
@ -63,17 +64,17 @@
assert: assert:
that: that:
- vrf_present_check_mode.changed == true - vrf_present_check_mode.changed == true
- 'vrf_present_check_mode.config == {"fvCtx": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}' - 'vrf_present_check_mode.sent == {"fvCtx": {"attributes": {"descr": "Ansible Test", "name": "anstest"}}}'
- vrf_present.changed == true - vrf_present.changed == true
- vrf_present.config == vrf_present_check_mode.config - vrf_present.sent == vrf_present_check_mode.sent
- vrf_present.existing == [] - vrf_present.previous == []
- vrf_present_idempotent.changed == false - vrf_present_idempotent.changed == false
- vrf_present_idempotent.existing != [] - vrf_present_idempotent.previous != []
- vrf_update.changed == true - vrf_update.changed == true
- vrf_update.existing != [] - vrf_update.previous != []
- vrf_update.changed != vrf_update.proposed - vrf_update.changed != vrf_update.proposed
- 'vrf_update.config == {"fvCtx": {"attributes": {"descr": "Ansible Test Update", "pcEnfPref": "unenforced"}}}' - 'vrf_update.sent == {"fvCtx": {"attributes": {"descr": "Ansible Test Update", "pcEnfPref": "unenforced"}}}'
- 'vrf_present_2.config.fvCtx.attributes == {"name": "anstest2", "pcEnfDir": "egress", "descr": "Ansible Test"}' - 'vrf_present_2.sent.fvCtx.attributes == {"name": "anstest2", "pcEnfDir": "egress", "descr": "Ansible Test"}'
- vrf_present_missing_param.failed == true - vrf_present_missing_param.failed == true
- 'vrf_present_missing_param.msg == "state is present but all of the following are missing: tenant"' - 'vrf_present_missing_param.msg == "state is present but all of the following are missing: tenant"'
@ -106,22 +107,22 @@
assert: assert:
that: that:
- query_all.changed == false - query_all.changed == false
- query_all.existing | length > 1 - query_all.previous | length > 1
- query_all.existing.0.fvCtx is defined - query_all.previous.0.fvCtx is defined
- '"class/fvCtx.json" in query_all.url' - '"class/fvCtx.json" in query_all.url'
- query_tenant.changed == false - query_tenant.changed == false
- query_tenant.existing | length == 1 - query_tenant.previous | length == 1
- query_tenant.existing.0.fvTenant.children | length == 2 - query_tenant.previous.0.fvTenant.children | length == 2
- 'query_tenant.existing.0.fvTenant.attributes.name == "anstest"' - 'query_tenant.previous.0.fvTenant.attributes.name == "anstest"'
- '"rsp-subtree-class=fvCtx" in query_tenant.filter_string' - '"rsp-subtree-class=fvCtx" in query_tenant.filter_string'
- '"tn-anstest.json" in query_tenant.url' - '"tn-anstest.json" in query_tenant.url'
- query_vrf_vrf.changed == false - query_vrf_vrf.changed == false
- query_vrf_vrf.existing != [] - query_vrf_vrf.previous != []
- 'query_vrf_vrf.existing.0.fvCtx.attributes.name == "anstest"' - 'query_vrf_vrf.previous.0.fvCtx.attributes.name == "anstest"'
- '"query-target-filter=eq(fvCtx.name, \"anstest\")" in query_vrf_vrf.filter_string' - '"query-target-filter=eq(fvCtx.name, \"anstest\")" in query_vrf_vrf.filter_string'
- '"class/fvCtx.json" in query_vrf_vrf.url' - '"class/fvCtx.json" in query_vrf_vrf.url'
- query_vrf.changed == false - query_vrf.changed == false
- query_vrf.existing | length == 1 - query_vrf.previous | length == 1
- '"tn-anstest/ctx-anstest.json" in query_vrf.url' - '"tn-anstest/ctx-anstest.json" in query_vrf.url'
- name: delete vrf - check mode works - name: delete vrf - check mode works
@ -157,12 +158,12 @@
assert: assert:
that: that:
- vrf_absent_check_mode.changed == true - vrf_absent_check_mode.changed == true
- vrf_absent_check_mode.existing != [] - vrf_absent_check_mode.previous != []
- vrf_absent_check_mode.proposed == {} - vrf_absent_check_mode.proposed == {}
- vrf_absent.changed == true - vrf_absent.changed == true
- vrf_absent.existing == vrf_absent_check_mode.existing - vrf_absent.previous == vrf_absent_check_mode.previous
- vrf_absent_idempotent.changed == false - vrf_absent_idempotent.changed == false
- vrf_absent_idempotent.existing == [] - vrf_absent_idempotent.previous == []
- vrf_absent_missing_param.failed == true - vrf_absent_missing_param.failed == true
- 'vrf_absent_missing_param.msg == "state is absent but all of the following are missing: vrf"' - 'vrf_absent_missing_param.msg == "state is absent but all of the following are missing: vrf"'

View file

@ -21,12 +21,31 @@
import sys import sys
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.module_utils.network.aci.aci import aci_response_json, aci_response_xml from ansible.module_utils.network.aci.aci import ACIModule
from ansible.module_utils.six import PY2, PY3 from ansible.module_utils.six import PY2, PY3
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
from nose.plugins.skip import SkipTest from nose.plugins.skip import SkipTest
class AltModule():
params = dict(
hostname='dummy',
port=123,
protocol='https',
state='present',
)
class AltACIModule(ACIModule):
def __init__(self):
self.result = dict(changed=False)
self.module = AltModule
self.params = self.module.params
aci = AltACIModule()
try: try:
from lxml import etree from lxml import etree
if sys.version_info >= (2, 7): if sys.version_info >= (2, 7):
@ -40,24 +59,28 @@ class AciRest(unittest.TestCase):
def test_invalid_aci_login(self): def test_invalid_aci_login(self):
self.maxDiff = None self.maxDiff = None
expected_result = { error = dict(
'error_code': '401', code='401',
'error_text': 'Username or password is incorrect - FAILED local authentication', text='Username or password is incorrect - FAILED local authentication',
'imdata': [{ )
imdata = [{
'error': { 'error': {
'attributes': { 'attributes': {
'code': '401', 'code': '401',
'text': 'Username or password is incorrect - FAILED local authentication', 'text': 'Username or password is incorrect - FAILED local authentication',
}, },
}, },
}], }]
'totalCount': '1',
} totalCount = 1
json_response = '{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"Username or password is incorrect - FAILED local authentication"}}}]}' # NOQA json_response = '{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"Username or password is incorrect - FAILED local authentication"}}}]}' # NOQA
json_result = dict() json_result = dict()
aci_response_json(json_result, json_response) aci.response_json(json_response)
self.assertEqual(expected_result, json_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.imdata, imdata)
self.assertEqual(aci.totalCount, totalCount)
# Python 2.7+ is needed for xmljson # Python 2.7+ is needed for xmljson
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
@ -68,16 +91,15 @@ class AciRest(unittest.TestCase):
</imdata> </imdata>
''' '''
xml_result = dict() xml_result = dict()
aci_response_xml(xml_result, xml_response) aci.response_xml(xml_response)
self.assertEqual(json_result, xml_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.imdata, imdata)
self.assertEqual(aci.totalCount, totalCount)
def test_valid_aci_login(self): def test_valid_aci_login(self):
self.maxDiff = None self.maxDiff = None
expected_result = { imdata = [{
'error_code': 0,
'error_text': 'Success',
'imdata': [{
'aaaLogin': { 'aaaLogin': {
'attributes': { 'attributes': {
'token': 'ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem', # NOQA 'token': 'ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem', # NOQA
@ -148,14 +170,15 @@ class AciRest(unittest.TestCase):
}, },
}], }],
}, },
}], }]
'totalCount': '1',
} totalCount = 1
json_response = '{"totalCount":"1","imdata":[{"aaaLogin":{"attributes":{"token":"ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem","siteFingerprint":"NdxD72K/uXaUK0wn","refreshTimeoutSeconds":"600","maximumLifetimeSeconds":"86400","guiIdleTimeoutSeconds":"1200","restTimeoutSeconds":"90","creationTime":"1500134817","firstLoginTime":"1500134817","userName":"admin","remoteUser":"false","unixUserId":"15374","sessionId":"o7hObsqNTfCmDGcZI5c4ng==","lastName":"","firstName":"","version":"2.0(2f)","buildTime":"Sat Aug 20 23:07:07 PDT 2016","node":"topology/pod-1/node-1"},"children":[{"aaaUserDomain":{"attributes":{"name":"all","rolesR":"admin","rolesW":"admin"},"children":[{"aaaReadRoles":{"attributes":{}}},{"aaaWriteRoles":{"attributes":{},"children":[{"role":{"attributes":{"name":"admin"}}}]}}]}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-common","readPrivileges":"admin","writePrivileges":"admin"}}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-infra","readPrivileges":"admin","writePrivileges":"admin"}}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-mgmt","readPrivileges":"admin","writePrivileges":"admin"}}}]}}]}' # NOQA json_response = '{"totalCount":"1","imdata":[{"aaaLogin":{"attributes":{"token":"ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem","siteFingerprint":"NdxD72K/uXaUK0wn","refreshTimeoutSeconds":"600","maximumLifetimeSeconds":"86400","guiIdleTimeoutSeconds":"1200","restTimeoutSeconds":"90","creationTime":"1500134817","firstLoginTime":"1500134817","userName":"admin","remoteUser":"false","unixUserId":"15374","sessionId":"o7hObsqNTfCmDGcZI5c4ng==","lastName":"","firstName":"","version":"2.0(2f)","buildTime":"Sat Aug 20 23:07:07 PDT 2016","node":"topology/pod-1/node-1"},"children":[{"aaaUserDomain":{"attributes":{"name":"all","rolesR":"admin","rolesW":"admin"},"children":[{"aaaReadRoles":{"attributes":{}}},{"aaaWriteRoles":{"attributes":{},"children":[{"role":{"attributes":{"name":"admin"}}}]}}]}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-common","readPrivileges":"admin","writePrivileges":"admin"}}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-infra","readPrivileges":"admin","writePrivileges":"admin"}}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-mgmt","readPrivileges":"admin","writePrivileges":"admin"}}}]}}]}' # NOQA
json_result = dict() json_result = dict()
aci_response_json(json_result, json_response) aci.response_json(json_response)
self.assertEqual(expected_result, json_result) self.assertEqual(aci.imdata, imdata)
self.assertEqual(aci.totalCount, totalCount)
# Python 2.7+ is needed for xmljson # Python 2.7+ is needed for xmljson
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
@ -163,30 +186,35 @@ class AciRest(unittest.TestCase):
xml_response = '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1">\n<aaaLogin token="ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem" siteFingerprint="NdxD72K/uXaUK0wn" refreshTimeoutSeconds="600" maximumLifetimeSeconds="86400" guiIdleTimeoutSeconds="1200" restTimeoutSeconds="90" creationTime="1500134817" firstLoginTime="1500134817" userName="admin" remoteUser="false" unixUserId="15374" sessionId="o7hObsqNTfCmDGcZI5c4ng==" lastName="" firstName="" version="2.0(2f)" buildTime="Sat Aug 20 23:07:07 PDT 2016" node="topology/pod-1/node-1">\n<aaaUserDomain name="all" rolesR="admin" rolesW="admin">\n<aaaReadRoles/>\n<aaaWriteRoles>\n<role name="admin"/>\n</aaaWriteRoles>\n</aaaUserDomain>\n<DnDomainMapEntry dn="uni/tn-common" readPrivileges="admin" writePrivileges="admin"/>\n<DnDomainMapEntry dn="uni/tn-infra" readPrivileges="admin" writePrivileges="admin"/>\n<DnDomainMapEntry dn="uni/tn-mgmt" readPrivileges="admin" writePrivileges="admin"/>\n</aaaLogin></imdata>\n''' # NOQA xml_response = '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1">\n<aaaLogin token="ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem" siteFingerprint="NdxD72K/uXaUK0wn" refreshTimeoutSeconds="600" maximumLifetimeSeconds="86400" guiIdleTimeoutSeconds="1200" restTimeoutSeconds="90" creationTime="1500134817" firstLoginTime="1500134817" userName="admin" remoteUser="false" unixUserId="15374" sessionId="o7hObsqNTfCmDGcZI5c4ng==" lastName="" firstName="" version="2.0(2f)" buildTime="Sat Aug 20 23:07:07 PDT 2016" node="topology/pod-1/node-1">\n<aaaUserDomain name="all" rolesR="admin" rolesW="admin">\n<aaaReadRoles/>\n<aaaWriteRoles>\n<role name="admin"/>\n</aaaWriteRoles>\n</aaaUserDomain>\n<DnDomainMapEntry dn="uni/tn-common" readPrivileges="admin" writePrivileges="admin"/>\n<DnDomainMapEntry dn="uni/tn-infra" readPrivileges="admin" writePrivileges="admin"/>\n<DnDomainMapEntry dn="uni/tn-mgmt" readPrivileges="admin" writePrivileges="admin"/>\n</aaaLogin></imdata>\n''' # NOQA
xml_result = dict() xml_result = dict()
aci_response_xml(xml_result, xml_response) aci.response_xml(xml_response)
self.assertEqual(json_result, xml_result) self.assertEqual(aci.imdata, imdata)
self.assertEqual(aci.totalCount, totalCount)
def test_invalid_input(self): def test_invalid_input(self):
self.maxDiff = None self.maxDiff = None
expected_result = { error = dict(
'error_code': '401', code='401',
'error_text': 'Username or password is incorrect - FAILED local authentication', text='Username or password is incorrect - FAILED local authentication',
'imdata': [{ )
imdata = [{
'error': { 'error': {
'attributes': { 'attributes': {
'code': '401', 'code': '401',
'text': 'Username or password is incorrect - FAILED local authentication', 'text': 'Username or password is incorrect - FAILED local authentication',
}, },
}, },
}], }]
'totalCount': '1',
} totalCount = 1
json_response = '{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"Username or password is incorrect - FAILED local authentication"}}}]}' # NOQA json_response = '{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"Username or password is incorrect - FAILED local authentication"}}}]}' # NOQA
json_result = dict() json_result = dict()
aci_response_json(json_result, json_response) aci.response_json(json_response)
self.assertEqual(expected_result, json_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.imdata, imdata)
self.assertEqual(aci.totalCount, totalCount)
# Python 2.7+ is needed for xmljson # Python 2.7+ is needed for xmljson
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
@ -197,8 +225,10 @@ class AciRest(unittest.TestCase):
</imdata> </imdata>
''' '''
xml_result = dict() xml_result = dict()
aci_response_xml(xml_result, xml_response) aci.response_xml(xml_response)
self.assertEqual(json_result, xml_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.imdata, imdata)
self.assertEqual(aci.totalCount, totalCount)
def test_empty_response(self): def test_empty_response(self):
self.maxDiffi = None self.maxDiffi = None
@ -208,16 +238,17 @@ class AciRest(unittest.TestCase):
else: else:
error_text = "Unable to parse output as JSON, see 'raw' output. Expecting value: line 1 column 1 (char 0)" error_text = "Unable to parse output as JSON, see 'raw' output. Expecting value: line 1 column 1 (char 0)"
expected_json_result = { error = dict(
'error_code': -1, code=-1,
'error_text': error_text, text=error_text,
'raw': '', )
} raw = ''
json_response = '' json_response = ''
json_result = dict() json_result = dict()
aci_response_json(json_result, json_response) aci.response_json(json_response)
self.assertEqual(expected_json_result, json_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.result['raw'], raw)
# Python 2.7+ is needed for xmljson # Python 2.7+ is needed for xmljson
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
@ -234,16 +265,18 @@ class AciRest(unittest.TestCase):
else: else:
error_text = "Unable to parse output as XML, see 'raw' output. Document is empty, line 1, column 1 (<string>, line 1)" error_text = "Unable to parse output as XML, see 'raw' output. Document is empty, line 1, column 1 (<string>, line 1)"
expected_xml_result = { error = dict(
'error_code': -1, code=-1,
'error_text': error_text, text=error_text,
'raw': '', )
}
raw = ''
xml_response = '' xml_response = ''
xml_result = dict() xml_result = dict()
aci_response_xml(xml_result, xml_response) aci.response_xml(xml_response)
self.assertEqual(expected_xml_result, xml_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.result['raw'], raw)
def test_invalid_response(self): def test_invalid_response(self):
self.maxDiff = None self.maxDiff = None
@ -255,16 +288,18 @@ class AciRest(unittest.TestCase):
else: else:
error_text = "Unable to parse output as JSON, see 'raw' output. Expecting value: line 1 column 9 (char 8)" error_text = "Unable to parse output as JSON, see 'raw' output. Expecting value: line 1 column 9 (char 8)"
expected_json_result = { error = dict(
'error_code': -1, code=-1,
'error_text': error_text, text=error_text,
'raw': '{ "aaa":', )
}
raw = '{ "aaa":'
json_response = '{ "aaa":' json_response = '{ "aaa":'
json_result = dict() json_result = dict()
aci_response_json(json_result, json_response) aci.response_json(json_response)
self.assertEqual(expected_json_result, json_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.result['raw'], raw)
# Python 2.7+ is needed for xmljson # Python 2.7+ is needed for xmljson
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
@ -279,13 +314,15 @@ class AciRest(unittest.TestCase):
else: else:
error_text = "Unable to parse output as XML, see 'raw' output. Couldn't find end of Start Tag aaa line 1, line 1, column 6 (<string>, line 1)" # NOQA error_text = "Unable to parse output as XML, see 'raw' output. Couldn't find end of Start Tag aaa line 1, line 1, column 6 (<string>, line 1)" # NOQA
expected_xml_result = { error = dict(
'error_code': -1, code=-1,
'error_text': error_text, text=error_text,
'raw': '<aaa ', )
}
raw = '<aaa '
xml_response = '<aaa ' xml_response = '<aaa '
xml_result = dict() xml_result = dict()
aci_response_xml(xml_result, xml_response) aci.response_xml(xml_response)
self.assertEqual(expected_xml_result, xml_result) self.assertEqual(aci.error, error)
self.assertEqual(aci.result['raw'], raw)