6from __future__
import absolute_import, division, print_function
9ANSIBLE_METADATA = {
'metadata_version':
'1.1',
10 'status': [
'preview'],
11 'supported_by':
'certified'}
15module: aci_epg_to_contract
16short_description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv)
18- Bind EPGs to Contracts on Cisco ACI fabrics.
20- The C(tenant), C(app_profile), C(EPG), and C(Contract) used must exist before using this module in your playbook.
21 The M(aci_tenant), M(aci_ap), M(aci_epg), and M(aci_contract) modules can be used
for this.
26 - Name of an existing application network profile, that will contain the EPGs.
28 aliases: [ app_profile, app_profile_name ]
31 - The name of the contract.
33 aliases: [ contract_name ]
36 - Determines
if the EPG should Provide
or Consume the Contract.
39 choices: [ consumer, provider ]
42 - The name of the end point group.
48 - The APIC defaults to C(unspecified) when unset during creation.
50 choices: [ level1, level2, level3, unspecified ]
53 - The matching algorithm
for Provided Contracts.
54 - The APIC defaults to C(at_least_one) when unset during creation.
56 choices: [ all, at_least_one, at_most_one, none ]
59 - Use C(present)
or C(absent)
for adding
or removing.
60 - Use C(query)
for listing an object
or multiple objects.
62 choices: [ absent, present, query ]
66 - Name of an existing tenant.
68 aliases: [ tenant_name ]
69extends_documentation_fragment: aci
74- name: APIC Management Information Model reference
75 description: More information about the internal APIC classes B(fv:RsCons)
and B(fv:RsProv).
76 link: https://developer.cisco.com/docs/apic-mim-ref/
78- Jacob McGill (
@jmcgill298)
82- name: Add a new contract to EPG binding
86 password: SomeSecretPassword
90 contract: anstest_http
91 contract_type: provider
93 delegate_to: localhost
95- name: Remove an existing contract to EPG binding
99 password: SomeSecretPassword
103 contract: anstest_http
104 contract_type: provider
106 delegate_to: localhost
108- name: Query a specific contract to EPG binding
112 password: SomeSecretPassword
116 contract: anstest_http
117 contract_type: provider
119 delegate_to: localhost
120 register: query_result
122- name: Query all provider contract to EPG bindings
126 password: SomeSecretPassword
127 contract_type: provider
129 delegate_to: localhost
130 register: query_result
135 description: The existing configuration from the APIC after the module has finished
143 "descr":
"Production environment",
144 "dn":
"uni/tn-production",
145 "name":
"production",
154 description: The error information
as returned
from the APIC
160 "text":
"unknown managed object class foo"
163 description: The raw output returned by the APIC REST API (xml
or json)
164 returned: parse error
166 sample:
'<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
168 description: The actual/minimal configuration pushed to the APIC
175 "descr":
"Production environment"
180 description: The original configuration
from the APIC before the module has started
188 "descr":
"Production",
189 "dn":
"uni/tn-production",
190 "name":
"production",
199 description: The assembled configuration
from the user-provided parameters
206 "descr":
"Production environment",
212 description: The filter string used
for the request
213 returned: failure
or debug
215 sample: ?rsp-prop-include=config-only
217 description: The HTTP method used
for the request to the APIC
218 returned: failure
or debug
222 description: The HTTP response
from the APIC
223 returned: failure
or debug
225 sample: OK (30 bytes)
227 description: The HTTP status
from the APIC
228 returned: failure
or debug
232 description: The HTTP url used
for the request to the APIC
233 returned: failure
or debug
235 sample: https://10.11.12.13/api/mo/uni/tn-production.json
238from ansible.module_utils.basic import AnsibleModule
239from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
241ACI_CLASS_MAPPING = dict(
252PROVIDER_MATCH_MAPPING = dict(
254 at_least_one=
'AtleastOne',
255 at_most_one=
'tmostOne',
262 argument_spec.update(
263 contract_type=dict(type=
'str', required=
True, choices=[
'consumer',
'provider']),
264 ap=dict(type=
'str', aliases=[
'app_profile',
'app_profile_name']),
265 epg=dict(type=
'str', aliases=[
'epg_name']),
266 contract=dict(type=
'str', aliases=[
'contract_name']),
267 priority=dict(type=
'str', choices=[
'level1',
'level2',
'level3',
'unspecified']),
268 provider_match=dict(type=
'str', choices=[
'all',
'at_least_one',
'at_most_one',
'none']),
269 state=dict(type=
'str', default=
'present', choices=[
'absent',
'present',
'query']),
270 tenant=dict(type=
'str', aliases=[
'tenant_name']),
274 argument_spec=argument_spec,
275 supports_check_mode=
True,
277 [
'state',
'absent', [
'ap',
'contract',
'epg',
'tenant']],
278 [
'state',
'present', [
'ap',
'contract',
'epg',
'tenant']],
282 ap = module.params[
'ap']
283 contract = module.params[
'contract']
284 contract_type = module.params[
'contract_type']
285 epg = module.params[
'epg']
286 priority = module.params[
'priority']
287 provider_match = module.params[
'provider_match']
288 if provider_match
is not None:
289 provider_match = PROVIDER_MATCH_MAPPING[provider_match]
290 state = module.params[
'state']
291 tenant = module.params[
'tenant']
293 aci_class = ACI_CLASS_MAPPING[contract_type][
"class"]
294 aci_rn = ACI_CLASS_MAPPING[contract_type][
"rn"]
296 if contract_type ==
"consumer" and provider_match
is not None:
297 module.fail_json(msg=
"the 'provider_match' is only configurable for Provided Contracts")
302 aci_class=
'fvTenant',
303 aci_rn=
'tn-{0}'.
format(tenant),
304 module_object=tenant,
305 target_filter={
'name': tenant},
309 aci_rn=
'ap-{0}'.
format(ap),
311 target_filter={
'name': ap},
315 aci_rn=
'epg-{0}'.
format(epg),
317 target_filter={
'name': epg},
321 aci_rn=
'{0}{1}'.
format(aci_rn, contract),
322 module_object=contract,
323 target_filter={
'tnVzBrCPName': contract},
329 if state ==
'present':
333 matchT=provider_match,
335 tnVzBrCPName=contract,
339 aci.get_diff(aci_class=aci_class)
343 elif state ==
'absent':
349if __name__ ==
"__main__":