Skip to content

Commit 7106558

Browse files
gmicollhercot
authored andcommitted
[minor_changes] Add aci_match_community_factor and all test cases for route control profile and Match rules related modules.
1 parent 95dc8e7 commit 7106558

File tree

21 files changed

+1435
-32
lines changed

21 files changed

+1435
-32
lines changed

plugins/modules/aci_context_policy.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@
6969
- cisco.aci.owner
7070
7171
notes:
72-
- The C(tenant) used must exist before using this module in your playbook.
73-
The M(cisco.aci.aci_tenant) module can be used for this.
72+
- The C(tenant) and the C(route_control_profile) used must exist before using this module in your playbook.
73+
The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_route_control_profile) modules can be used for this.
7474
seealso:
7575
- module: cisco.aci.aci_tenant
7676
- name: APIC Management Information Model reference
@@ -201,6 +201,8 @@ def main():
201201
l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects
202202
route_control_profile=dict(type="str", aliases=["rtctrl_profile_name"]), # Not required for querying all objects
203203
context_policy=dict(type="str", aliases=["name", "context_name"]), # Not required for querying all objects
204+
subject_profile=dict(type="str", aliases=["subject_name"]),
205+
action_rule=dict(type="str", aliases=["action_rule_name"]),
204206
action = dict(type="str", choices=["deny", "permit"]),
205207
order=dict(type="int"),
206208
description=dict(type="str", aliases=["descr"]),
@@ -225,10 +227,14 @@ def main():
225227
tenant = module.params.get("tenant")
226228
l3out = module.params.get("l3out")
227229
route_control_profile = module.params.get("route_control_profile")
230+
subject_profile = module.params.get("subject_profile")
231+
action_rule = module.params.get("action_rule")
228232
name_alias = module.params.get("name_alias")
229233

230234
aci = ACIModule(module)
231235

236+
child_classes = ["rtctrlRsCtxPToSubjP", "rtctrlScope"]
237+
232238
tenant_url_config = dict(
233239
aci_class="fvTenant",
234240
aci_rn="tn-{0}".format(tenant),
@@ -261,26 +267,40 @@ def main():
261267
),
262268
subclass_2=route_control_profile_url_config,
263269
subclass_3=context_policy_url_config,
270+
child_classes=child_classes,
264271
)
265272
else:
266273
aci.construct_url(
267274
root_class=tenant_url_config,
268275
subclass_1=route_control_profile_url_config,
269276
subclass_2=context_policy_url_config,
277+
child_classes=child_classes,
270278
)
271279

272280
aci.get_existing()
273281

274282
if state == "present":
283+
child_configs = []
284+
if subject_profile is not None:
285+
child_configs.append({"rtctrlRsCtxPToSubjP": {"attributes": {"tnRtctrlSubjPName": subject_profile}}})
286+
if action_rule is not None:
287+
child_configs.append(
288+
{"rtctrlScope": {"attributes": {"descr": ""},
289+
"children": [{"rtctrlRsScopeToAttrP": {"attributes": {"tnRtctrlAttrPName": action_rule}}}],
290+
}
291+
}
292+
)
293+
275294
aci.payload(
276295
aci_class="rtctrlCtxP",
277296
class_config=dict(
278-
name=route_control_profile,
297+
name=context_policy,
279298
descr=description,
280299
action=action,
281300
order=order,
282301
nameAlias=name_alias,
283302
),
303+
child_configs=child_configs,
284304
)
285305

286306
aci.get_diff(aci_class="rtctrlCtxP")

plugins/modules/aci _match_as_path_regex_term.py renamed to plugins/modules/aci_match_as_path_regex_term.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
- cisco.aci.owner
5959
6060
notes:
61-
- The C(tenant) used must exist before using this module in your playbook.
62-
The M(cisco.aci.aci_tenant) module can be used for this.
61+
- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook.
62+
The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this.
6363
seealso:
6464
- module: cisco.aci.aci_tenant
6565
- name: APIC Management Information Model reference
@@ -187,7 +187,6 @@ def main():
187187
argument_spec.update(aci_owner_spec())
188188
argument_spec.update(
189189
tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects
190-
l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects
191190
subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects
192191
match_as_path_regex_term=dict(type="str", aliases=["name", "match_rule_name"]),
193192
regex=dict(type="str"),
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
5+
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
6+
7+
from __future__ import absolute_import, division, print_function
8+
9+
__metaclass__ = type
10+
11+
ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "certified"}
12+
13+
DOCUMENTATION = r"""
14+
---
15+
module: aci_subject_profile
16+
short_description: Manage Match Community Factor (rtctrl:MatchCommFactor)
17+
description:
18+
- Manage Match Community Factors for Match Rules Based on Community on Cisco ACI fabrics.
19+
options:
20+
tenant:
21+
description:
22+
- The name of an existing tenant.
23+
type: str
24+
aliases: [ tenant_name ]
25+
subject_profile:
26+
description:
27+
- Name of an exising subject profile.
28+
type: str
29+
aliases: [ subject_name ]
30+
match_community_term:
31+
description:
32+
- Name of an existing match community term.
33+
type: str
34+
aliases: [ match_rule_name ]
35+
community:
36+
description:
37+
- The match community value.
38+
type: str
39+
scope:
40+
description:
41+
- The item scope.
42+
- if the scope is transitive, this community may be passed between ASs.
43+
- if the scope is Non transitive, this community should be carried only within the local AS.
44+
type: str
45+
choices: [ transitive, non-transitive ]
46+
description:
47+
description:
48+
- The description for the Match Community Term.
49+
type: str
50+
aliases: [ descr ]
51+
state:
52+
description:
53+
- Use C(present) or C(absent) for adding or removing.
54+
- Use C(query) for listing an object or multiple objects.
55+
type: str
56+
choices: [ absent, present, query ]
57+
default: present
58+
name_alias:
59+
description:
60+
- The alias for the current object. This relates to the nameAlias field in ACI.
61+
type: str
62+
extends_documentation_fragment:
63+
- cisco.aci.aci
64+
- cisco.aci.annotation
65+
- cisco.aci.owner
66+
67+
notes:
68+
- The C(tenant), the C(subject_profile) and the C(match_community_term) used must exist before using this module in your playbook.
69+
The M(cisco.aci.aci_tenant), the M(cisco.aci.subject_profile) and M(cisco.aci.match_community_term) modules can be used for this.
70+
seealso:
71+
- module: cisco.aci.aci_tenant
72+
- name: APIC Management Information Model reference
73+
description: More information about the internal APIC class B(rtctrl:MatchCommFactor).
74+
link: https://developer.cisco.com/docs/apic-mim-ref/
75+
author:
76+
- Gaspard Micol (@gmicol)
77+
"""
78+
79+
EXAMPLES = r"""
80+
"""
81+
82+
RETURN = r"""
83+
current:
84+
description: The existing configuration from the APIC after the module has finished
85+
returned: success
86+
type: list
87+
sample:
88+
[
89+
{
90+
"fvTenant": {
91+
"attributes": {
92+
"descr": "Production environment",
93+
"dn": "uni/tn-production",
94+
"name": "production",
95+
"nameAlias": "",
96+
"ownerKey": "",
97+
"ownerauto_continue": ""
98+
}
99+
}
100+
}
101+
]
102+
error:
103+
description: The error information as returned from the APIC
104+
returned: failure
105+
type: dict
106+
sample:
107+
{
108+
"code": "122",
109+
"text": "unknown managed object class foo"
110+
}
111+
raw:
112+
description: The raw output returned by the APIC REST API (xml or json)
113+
returned: parse error
114+
type: str
115+
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
116+
sent:
117+
description: The actual/minimal configuration pushed to the APIC
118+
returned: info
119+
type: list
120+
sample:
121+
{
122+
"fvTenant": {
123+
"attributes": {
124+
"descr": "Production environment"
125+
}
126+
}
127+
}
128+
previous:
129+
description: The original configuration from the APIC before the module has started
130+
returned: info
131+
type: list
132+
sample:
133+
[
134+
{
135+
"fvTenant": {
136+
"attributes": {
137+
"descr": "Production",
138+
"dn": "uni/tn-production",
139+
"name": "production",
140+
"nameAlias": "",
141+
"ownerKey": "",
142+
"ownerauto_continue": ""
143+
}
144+
}
145+
}
146+
]
147+
proposed:
148+
description: The assembled configuration from the user-provided parameters
149+
returned: info
150+
type: dict
151+
sample:
152+
{
153+
"fvTenant": {
154+
"attributes": {
155+
"descr": "Production environment",
156+
"name": "production"
157+
}
158+
}
159+
}
160+
filter_string:
161+
description: The filter string used for the request
162+
returned: failure or debug
163+
type: str
164+
sample: ?rsp-prop-include=config-only
165+
method:
166+
description: The HTTP method used for the request to the APIC
167+
returned: failure or debug
168+
type: str
169+
sample: POST
170+
response:
171+
description: The HTTP response from the APIC
172+
returned: failure or debug
173+
type: str
174+
sample: OK (30 bytes)
175+
status:
176+
description: The HTTP status from the APIC
177+
returned: failure or debug
178+
type: int
179+
sample: 200
180+
url:
181+
description: The HTTP url used for the request to the APIC
182+
returned: failure or debug
183+
type: str
184+
sample: https://10.11.12.13/api/mo/uni/tn-production.json
185+
"""
186+
187+
from ansible.module_utils.basic import AnsibleModule
188+
from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec
189+
190+
191+
def main():
192+
argument_spec = aci_argument_spec()
193+
argument_spec.update(aci_annotation_spec())
194+
argument_spec.update(aci_owner_spec())
195+
argument_spec.update(
196+
tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects
197+
subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects
198+
match_community_term=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects
199+
community=dict(type="str"),
200+
scope=dict(type="str", choices=["transitive", "non-transitive"]),
201+
description=dict(type="str", aliases=["descr"]),
202+
name_alias=dict(type="str"),
203+
state=dict(type="str", default="present", choices=["present", "absent", "query"]),
204+
)
205+
206+
module = AnsibleModule(
207+
argument_spec=argument_spec,
208+
supports_check_mode=True,
209+
required_if=[
210+
["state", "absent", ["community", "tenant", "subject_profile", "match_community_term"]],
211+
["state", "present", ["community", "tenant", "subject_profile", "match_community_term"]],
212+
],
213+
)
214+
215+
community = module.params.get("community")
216+
scope = module.params.get("scope")
217+
description = module.params.get("description")
218+
state = module.params.get("state")
219+
tenant = module.params.get("tenant")
220+
subject_profile = module.params.get("subject_profile")
221+
match_community_term = module.params.get("match_community_term")
222+
name_alias = module.params.get("name_alias")
223+
224+
aci = ACIModule(module)
225+
226+
aci.construct_url(
227+
root_class=dict(
228+
aci_class="fvTenant",
229+
aci_rn="tn-{0}".format(tenant),
230+
module_object=tenant,
231+
target_filter={"name": tenant},
232+
),
233+
subclass_1=dict(
234+
aci_class="rtctrlSubjP",
235+
aci_rn="subj-{0}".format(subject_profile),
236+
module_object=subject_profile,
237+
target_filter={"name": subject_profile},
238+
),
239+
subclass_2=dict(
240+
aci_class="rtctrlMatchCommTerm",
241+
aci_rn="commtrm-{0}".format(match_community_term),
242+
module_object=match_community_term,
243+
target_filter={"name": match_community_term},
244+
),
245+
subclass_3=dict(
246+
aci_class="rtctrlMatchCommFactor",
247+
aci_rn="commfct-{0}".format(community),
248+
module_object=community,
249+
target_filter={"community": community},
250+
),
251+
)
252+
253+
aci.get_existing()
254+
255+
if state == "present":
256+
aci.payload(
257+
aci_class="rtctrlMatchCommFactor",
258+
class_config=dict(
259+
community=community,
260+
scope=scope,
261+
descr=description,
262+
nameAlias=name_alias,
263+
),
264+
)
265+
266+
aci.get_diff(aci_class="rtctrlMatchCommFactor")
267+
268+
aci.post_config()
269+
270+
elif state == "absent":
271+
aci.delete_config()
272+
273+
aci.exit_json()
274+
275+
276+
if __name__ == "__main__":
277+
main()

0 commit comments

Comments
 (0)