Skip to content

Commit 9be0d42

Browse files
anvitha-jainlhercot
authored andcommitted
[ignore] Added aci_l3out_static_routes.py file back.
1 parent a2fbd36 commit 9be0d42

File tree

2 files changed

+370
-5
lines changed

2 files changed

+370
-5
lines changed

docs/developing_aci_module_guidelines.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,15 +452,14 @@ This method uses the root class (e.g., fvTenant) and optional subclass dictionar
452452
* When the `state` is not `query`:The URL includes the full DN (base URL (to access the APIC) with the distinguished name of the object (to access the object)) of the object, and the response is typically limited to configuration data (config-only).
453453
* When `state` is `query`, the URL and filter string used depend on which parameters are passed to the object. This method handles the complexity so that it is easier to add new modules and ensures that all modules are consistent in the type of data returned.
454454

455-
> [!IMPORTANT]
456-
> The design goal for querying the objects, is to use the provided ID parameters to return the most specific data possible:
457-
> * If no ID parameters are given, return all objects of the class.
458-
> * If only some ID parameters are provided, return all objects that match those IDs.
459-
460455
* **Query specific object**: the URL is constructed to target a specific object within the module's class using its distinguished name. The filter string is typically not applied, allowing retrieval of the full object data. This approach simplifies module development by handling the URL construction dynamically and ensures consistent data retrieval for individual objects.
461456

462457
* **Query all objects**: the URL is built to query all objects of the specified class. If a target filter is provided, it is applied as a query parameter to restrict the returned data to matching objects. This method manages the complexity of querying collections, making it easier to add new modules and maintain uniformity in the data returned across modules.
463458

459+
> [!IMPORTANT]
460+
> The design goal for querying the objects, is to use the provided ID parameters to return the most specific data possible:
461+
> * If no ID parameters are given, return all objects of the class.
462+
> * If only some ID parameters are provided, return all objects that match those IDs.
464463

465464
> [!TIP]
466465
> For more information on the ACI REST APIs and how to construct URLs [ACI REST API Guide](https://www.cisco.com/c/en/us/td/docs/dcn/aci/apic/all/apic-rest-api-configuration-guide/cisco-apic-rest-api-configuration-guide-42x-and-later/m_using_the_rest_api.html).
Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright: (c) 2020, Anvitha Jain(@anvitha-jain) <[email protected]>
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_l3out_static_routes
16+
short_description: Manage Static routes object (ip:RouteP)
17+
description:
18+
- Manage External Subnet objects.
19+
options:
20+
description:
21+
description:
22+
- The description for the static routes.
23+
type: str
24+
aliases: [ descr ]
25+
tenant:
26+
description:
27+
- Name of an existing tenant.
28+
type: str
29+
aliases: [ tenant_name ]
30+
l3out:
31+
description:
32+
- Name of an existing L3Out.
33+
type: str
34+
aliases: [ l3out_name ]
35+
logical_node:
36+
description:
37+
- Name of an existing logical node profile.
38+
type: str
39+
aliases: [ node_profile, node_profile_name ]
40+
pod_id:
41+
description:
42+
- Existing podId.
43+
type: int
44+
node_id:
45+
description:
46+
- Existing nodeId.
47+
type: int
48+
prefix:
49+
description:
50+
- Configure IP and next hop IP for the routed outside network.
51+
type: str
52+
aliases: [ route ]
53+
track_policy:
54+
description:
55+
- Relation definition for static route to TrackList.
56+
type: str
57+
preference:
58+
description:
59+
- Administrative preference value for the route.
60+
type: int
61+
bfd:
62+
description:
63+
- Determines if bfd is required for route control.
64+
- The APIC defaults to C(unspecified) when unset during creation.
65+
type: str
66+
choices: [ bfd, unspecified ]
67+
state:
68+
description:
69+
- Use C(present) or C(absent) for adding or removing.
70+
- Use C(query) for listing an object or multiple objects.
71+
type: str
72+
choices: [ absent, present, query ]
73+
default: present
74+
name_alias:
75+
description:
76+
- The alias for the current object. This relates to the nameAlias field in ACI.
77+
type: str
78+
extends_documentation_fragment:
79+
- cisco.aci.aci
80+
- cisco.aci.annotation
81+
82+
notes:
83+
- The C(tenant), C(l3out), C(logical_node), C(fabric_node) and C(prefix) used must exist before using this module in your playbook.
84+
The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_l3out) modules can be used for this.
85+
seealso:
86+
- module: cisco.aci.aci_tenant
87+
- module: cisco.aci.aci_l3out
88+
- name: APIC Management Information Model reference
89+
description: More information about the internal APIC class B(l3ext:ipRouteP).
90+
link: https://developer.cisco.com/docs/apic-mim-ref/
91+
author:
92+
- Anvitha Jain(@anvitha-jain)
93+
"""
94+
95+
EXAMPLES = r"""
96+
- name: Create static routes
97+
cisco.aci.aci_l3out_static_routes:
98+
host: apic
99+
username: admin
100+
password: SomeSecretPassword
101+
tenant: tenantName
102+
l3out: l3out
103+
logical_node: nodeName
104+
node_id: 101
105+
pod_id: 1
106+
prefix: 10.10.0.0/16
107+
delegate_to: localhost
108+
109+
- name: Delete static routes
110+
cisco.aci.aci_l3out_static_routes:
111+
host: apic
112+
username: admin
113+
password: SomeSecretPassword
114+
tenant: tenantName
115+
l3out: l3out
116+
logical_node: nodeName
117+
node_id: 101
118+
pod_id: 1
119+
prefix: 10.10.0.0/16
120+
delegate_to: localhost
121+
122+
- name: Query for a specific MO under l3out
123+
cisco.aci.aci_l3out_static_routes:
124+
host: apic
125+
username: admin
126+
password: SomeSecretPassword
127+
tenant: tenantName
128+
l3out: l3out
129+
logical_node: nodeName
130+
node_id: 101
131+
pod_id: 1
132+
prefix: 10.10.0.0/16
133+
delegate_to: localhost
134+
135+
- name: Query for all static routes
136+
cisco.aci.aci_l3out_static_routes:
137+
host: apic
138+
username: admin
139+
password: SomeSecretPassword
140+
tenant: production
141+
state: query
142+
delegate_to: localhost
143+
register: query_result
144+
"""
145+
146+
RETURN = r"""
147+
current:
148+
description: The existing configuration from the APIC after the module has finished
149+
returned: success
150+
type: list
151+
sample:
152+
[
153+
{
154+
"fvTenant": {
155+
"attributes": {
156+
"descr": "Production environment",
157+
"dn": "uni/tn-production",
158+
"name": "production",
159+
"nameAlias": "",
160+
"ownerKey": "",
161+
"ownerTag": ""
162+
}
163+
}
164+
}
165+
]
166+
error:
167+
description: The error information as returned from the APIC
168+
returned: failure
169+
type: dict
170+
sample:
171+
{
172+
"code": "122",
173+
"text": "unknown managed object class foo"
174+
}
175+
raw:
176+
description: The raw output returned by the APIC REST API (xml or json)
177+
returned: parse error
178+
type: str
179+
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
180+
sent:
181+
description: The actual/minimal configuration pushed to the APIC
182+
returned: info
183+
type: list
184+
sample:
185+
{
186+
"fvTenant": {
187+
"attributes": {
188+
"descr": "Production environment"
189+
}
190+
}
191+
}
192+
previous:
193+
description: The original configuration from the APIC before the module has started
194+
returned: info
195+
type: list
196+
sample:
197+
[
198+
{
199+
"fvTenant": {
200+
"attributes": {
201+
"descr": "Production",
202+
"dn": "uni/tn-production",
203+
"name": "production",
204+
"nameAlias": "",
205+
"ownerKey": "",
206+
"ownerTag": ""
207+
}
208+
}
209+
}
210+
]
211+
proposed:
212+
description: The assembled configuration from the user-provided parameters
213+
returned: info
214+
type: dict
215+
sample:
216+
{
217+
"fvTenant": {
218+
"attributes": {
219+
"descr": "Production environment",
220+
"name": "production"
221+
}
222+
}
223+
}
224+
filter_string:
225+
description: The filter string used for the request
226+
returned: failure or debug
227+
type: str
228+
sample: ?rsp-prop-include=config-only
229+
method:
230+
description: The HTTP method used for the request to the APIC
231+
returned: failure or debug
232+
type: str
233+
sample: POST
234+
response:
235+
description: The HTTP response from the APIC
236+
returned: failure or debug
237+
type: str
238+
sample: OK (30 bytes)
239+
status:
240+
description: The HTTP status from the APIC
241+
returned: failure or debug
242+
type: int
243+
sample: 200
244+
url:
245+
description: The HTTP url used for the request to the APIC
246+
returned: failure or debug
247+
type: str
248+
sample: https://10.11.12.13/api/mo/uni/tn-production.json
249+
"""
250+
251+
from ansible.module_utils.basic import AnsibleModule
252+
from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec
253+
254+
255+
def main():
256+
argument_spec = aci_argument_spec()
257+
argument_spec.update(aci_annotation_spec())
258+
argument_spec.update(
259+
tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects
260+
l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects
261+
logical_node=dict(type="str", aliases=["node_profile", "node_profile_name"]), # Not required for querying all objects
262+
pod_id=dict(type="int"),
263+
node_id=dict(type="int"),
264+
prefix=dict(type="str", aliases=["route"]),
265+
track_policy=dict(type="str"),
266+
preference=dict(type="int"),
267+
bfd=dict(type="str", choices=["bfd", "unspecified"]),
268+
description=dict(type="str", aliases=["descr"]),
269+
state=dict(type="str", default="present", choices=["absent", "present", "query"]),
270+
name_alias=dict(type="str"),
271+
)
272+
273+
module = AnsibleModule(
274+
argument_spec=argument_spec,
275+
supports_check_mode=True,
276+
required_if=[
277+
["state", "present", ["prefix", "node_id", "pod_id", "logical_node", "l3out", "tenant"]],
278+
["state", "absent", ["prefix", "node_id", "pod_id", "logical_node", "l3out", "tenant"]],
279+
],
280+
)
281+
282+
aci = ACIModule(module)
283+
284+
tenant = module.params.get("tenant")
285+
l3out = module.params.get("l3out")
286+
logical_node = module.params.get("logical_node")
287+
node_id = module.params.get("node_id")
288+
pod_id = module.params.get("pod_id")
289+
prefix = module.params.get("prefix")
290+
track_policy = module.params.get("track_policy")
291+
preference = module.params.get("preference")
292+
bfd = module.params.get("bfd")
293+
description = module.params.get("description")
294+
state = module.params.get("state")
295+
name_alias = module.params.get("name_alias")
296+
297+
fabric_node = "topology/pod-{0}/node-{1}".format(pod_id, node_id)
298+
child_classes = ["ipNexthopP"]
299+
if track_policy is not None:
300+
child_classes.append("ipRsRouteTrack")
301+
302+
aci.construct_url(
303+
root_class=dict(
304+
aci_class="fvTenant",
305+
aci_rn="tn-{0}".format(tenant),
306+
module_object=tenant,
307+
target_filter={"name": tenant},
308+
),
309+
subclass_1=dict(
310+
aci_class="l3extOut",
311+
aci_rn="out-{0}".format(l3out),
312+
module_object=l3out,
313+
target_filter={"name": l3out},
314+
),
315+
subclass_2=dict(
316+
aci_class="l3extLNodeP",
317+
aci_rn="lnodep-{0}".format(logical_node),
318+
module_object=logical_node,
319+
target_filter={"name": logical_node},
320+
),
321+
subclass_3=dict(
322+
aci_class="l3extRsNodeL3OutAtt",
323+
aci_rn="rsnodeL3OutAtt-[{0}]".format(fabric_node),
324+
module_object=fabric_node,
325+
target_filter={"name": fabric_node},
326+
),
327+
subclass_4=dict(
328+
aci_class="ipRouteP",
329+
aci_rn="rt-[{0}]".format(prefix),
330+
module_object=prefix,
331+
target_filter={"name": prefix},
332+
),
333+
child_classes=child_classes,
334+
)
335+
336+
aci.get_existing()
337+
338+
if state == "present":
339+
child_configs = []
340+
class_config = dict(
341+
descr=description,
342+
ip=prefix,
343+
pref=preference,
344+
nameAlias=name_alias,
345+
)
346+
if bfd is not None:
347+
class_config["rtCtrl"] = bfd
348+
349+
if track_policy is not None:
350+
tDn = "uni/tn-{0}/tracklist-{1}".format(tenant, track_policy)
351+
child_configs.append({"ipRsRouteTrack": {"attributes": {"tDn": tDn}}})
352+
353+
aci.payload(aci_class="ipRouteP", class_config=class_config, child_configs=child_configs)
354+
355+
aci.get_diff(aci_class="ipRouteP")
356+
357+
aci.post_config()
358+
359+
elif state == "absent":
360+
aci.delete_config()
361+
362+
aci.exit_json()
363+
364+
365+
if __name__ == "__main__":
366+
main()

0 commit comments

Comments
 (0)