Skip to content

Commit 8dee2fc

Browse files
CACIT-82 added datasource (#151)
* CACIT-82 added datasource * fvCEP datasource updated
1 parent 48c9cf7 commit 8dee2fc

File tree

5 files changed

+313
-0
lines changed

5 files changed

+313
-0
lines changed

aci/data_source_aci_fvcep.go

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
package aci
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/ciscoecosystem/aci-go-client/client"
8+
"github.com/ciscoecosystem/aci-go-client/container"
9+
"github.com/ciscoecosystem/aci-go-client/models"
10+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
11+
)
12+
13+
func dataSourceAciClientEndPoint() *schema.Resource {
14+
return &schema.Resource{
15+
16+
Read: dataSourceAciClientEndPointRead,
17+
18+
SchemaVersion: 1,
19+
20+
Schema: AppendBaseAttrSchema(map[string]*schema.Schema{
21+
"name": &schema.Schema{
22+
Type: schema.TypeString,
23+
Optional: true,
24+
Computed: true,
25+
},
26+
27+
"mac": &schema.Schema{
28+
Type: schema.TypeString,
29+
Optional: true,
30+
Computed: true,
31+
},
32+
33+
"ip": &schema.Schema{
34+
Type: schema.TypeString,
35+
Optional: true,
36+
Computed: true,
37+
},
38+
39+
"vlan": &schema.Schema{
40+
Type: schema.TypeString,
41+
Optional: true,
42+
Computed: true,
43+
},
44+
45+
"fvcep_objects": &schema.Schema{
46+
Type: schema.TypeList,
47+
Optional: true,
48+
Computed: true,
49+
Elem: &schema.Resource{
50+
Schema: map[string]*schema.Schema{
51+
"name": &schema.Schema{
52+
Type: schema.TypeString,
53+
Optional: true,
54+
Computed: true,
55+
},
56+
57+
"mac": &schema.Schema{
58+
Type: schema.TypeString,
59+
Optional: true,
60+
Computed: true,
61+
},
62+
63+
"ip": &schema.Schema{
64+
Type: schema.TypeString,
65+
Optional: true,
66+
Computed: true,
67+
},
68+
69+
"vlan": &schema.Schema{
70+
Type: schema.TypeString,
71+
Optional: true,
72+
Computed: true,
73+
},
74+
75+
"tenant_name": &schema.Schema{
76+
Type: schema.TypeString,
77+
Optional: true,
78+
Computed: true,
79+
},
80+
81+
"vrf_name": &schema.Schema{
82+
Type: schema.TypeString,
83+
Optional: true,
84+
Computed: true,
85+
},
86+
87+
"application_profile_name": &schema.Schema{
88+
Type: schema.TypeString,
89+
Optional: true,
90+
Computed: true,
91+
},
92+
93+
"epg_name": &schema.Schema{
94+
Type: schema.TypeString,
95+
Optional: true,
96+
Computed: true,
97+
},
98+
99+
"l2out_name": &schema.Schema{
100+
Type: schema.TypeString,
101+
Optional: true,
102+
Computed: true,
103+
},
104+
105+
"instance_profile_name": &schema.Schema{
106+
Type: schema.TypeString,
107+
Optional: true,
108+
Computed: true,
109+
},
110+
},
111+
},
112+
},
113+
}),
114+
}
115+
}
116+
117+
func extractInfo(con *container.Container) (obj map[string]interface{}, dn string) {
118+
infoMap := make(map[string]interface{})
119+
dnString := models.G(con, "dn")
120+
infoMap["name"] = models.G(con, "name")
121+
infoMap["mac"] = models.G(con, "mac")
122+
infoMap["ip"] = models.G(con, "ip")
123+
infoMap["vlan"] = models.G(con, "encap")
124+
125+
dnInfoList := strings.Split(dnString, "/")
126+
tenantInfo := strings.Split(dnInfoList[1], "-")
127+
if tenantInfo[0] == "tn" {
128+
infoMap["tenant_name"] = tenantInfo[1]
129+
130+
level2Info := strings.Split(dnInfoList[2], "-")
131+
if level2Info[0] == "ctx" {
132+
infoMap["vrf_name"] = level2Info[1]
133+
134+
} else if level2Info[0] == "ap" {
135+
infoMap["application_profile_name"] = level2Info[1]
136+
137+
level3Info := strings.Split(dnInfoList[3], "-")
138+
if level3Info[0] == "epg" {
139+
infoMap["epg_name"] = level3Info[1]
140+
} else {
141+
return nil, ""
142+
}
143+
144+
} else if level2Info[0] == "l2out" {
145+
infoMap["l2out_name"] = level2Info[1]
146+
147+
level3Info := strings.Split(dnInfoList[3], "-")
148+
if level3Info[0] == "instP" {
149+
infoMap["instance_profile_name"] = level3Info[1]
150+
} else {
151+
return nil, ""
152+
}
153+
154+
} else {
155+
return nil, ""
156+
}
157+
158+
} else {
159+
return nil, ""
160+
}
161+
162+
return infoMap, dnString
163+
}
164+
165+
func getRemoteClientEndPoint(client *client.Client, query string) (objMap []interface{}, objdns []string, err error) {
166+
baseURL := "/api/node/class"
167+
168+
var duURL string
169+
if query == "" {
170+
duURL = fmt.Sprintf("%s/fvCEp.json", baseURL)
171+
} else {
172+
duURL = fmt.Sprintf("%s/fvCEp.json?query-target-filter=and(%s)", baseURL, query)
173+
}
174+
175+
fvCEpCont, err := client.GetViaURL(duURL)
176+
if err != nil {
177+
return nil, nil, err
178+
}
179+
180+
objects := make([]interface{}, 0, 1)
181+
dns := make([]string, 0, 1)
182+
183+
count, err := fvCEpCont.ArrayCount("imdata")
184+
if err != nil {
185+
return nil, nil, err
186+
}
187+
188+
for i := 0; i < count; i++ {
189+
clientEndPointCont, err := fvCEpCont.ArrayElement(i, "imdata")
190+
if err != nil {
191+
return nil, nil, err
192+
}
193+
194+
objMap, dn := extractInfo(clientEndPointCont.S("fvCEp", "attributes"))
195+
if dn != "" {
196+
objects = append(objects, objMap)
197+
dns = append(dns, dn)
198+
}
199+
}
200+
201+
return objects, dns, nil
202+
}
203+
204+
func dataSourceAciClientEndPointRead(d *schema.ResourceData, m interface{}) error {
205+
aciClient := m.(*client.Client)
206+
207+
var queryString string
208+
if mac, ok := d.GetOk("mac"); ok {
209+
if queryString != "" {
210+
queryString = fmt.Sprintf("%s,eq(fvCEp.mac, \"%s\")", queryString, mac.(string))
211+
} else {
212+
queryString = fmt.Sprintf("eq(fvCEp.mac, \"%s\")", mac.(string))
213+
}
214+
}
215+
216+
if ip, ok := d.GetOk("ip"); ok {
217+
if queryString != "" {
218+
queryString = fmt.Sprintf("%s,eq(fvCEp.ip, \"%s\")", queryString, ip.(string))
219+
} else {
220+
queryString = fmt.Sprintf("eq(fvCEp.ip, \"%s\")", ip.(string))
221+
}
222+
}
223+
224+
if name, ok := d.GetOk("name"); ok {
225+
if queryString != "" {
226+
queryString = fmt.Sprintf("%s,eq(fvCEp.name, \"%s\")", queryString, name.(string))
227+
} else {
228+
queryString = fmt.Sprintf("eq(fvCEp.name, \"%s\")", name.(string))
229+
}
230+
}
231+
232+
if vlan, ok := d.GetOk("vlan"); ok {
233+
if queryString != "" {
234+
queryString = fmt.Sprintf("%s,eq(fvCEp.encap, \"vlan-%s\")", queryString, vlan.(string))
235+
} else {
236+
queryString = fmt.Sprintf("eq(fvCEp.encap, \"vlan-%s\")", vlan.(string))
237+
}
238+
}
239+
240+
objects, dns, err := getRemoteClientEndPoint(aciClient, queryString)
241+
if err != nil {
242+
return err
243+
}
244+
245+
d.Set("fvcep_objects", objects)
246+
d.SetId(strings.Join(dns, " "))
247+
return nil
248+
}

aci/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ func Provider() terraform.ResourceProvider {
255255
"aci_fabric_path_ep": dataSourceAciFabricPathEndpoint(),
256256
"aci_fabric_if_pol": dataSourceAciLinkLevelPolicy(),
257257
"aci_aaa_domain": dataSourceAciSecurityDomain(),
258+
"aci_client_end_point": dataSourceAciClientEndPoint(),
258259
},
259260

260261
ConfigureFunc: configureClient,

examples/client_end_point/main.tf

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
provider "aci" {
2+
username = ""
3+
password = ""
4+
url = ""
5+
insecure = true
6+
}
7+
8+
data "aci_client_end_point" "check" {
9+
name = "25:56:68:78:98:74"
10+
mac = "25:56:68:78:98:74"
11+
ip = "0.0.0.0"
12+
vlan = "5"
13+
}

website/aci.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
<li<%= sidebar_current("docs-aci-data-source-cdp_interface_policy") %>>
5858
<a href="/docs/providers/aci/d/cdp_interface_policy.html">aci_cdp_interface_policy</a>
5959
</li>
60+
<li<%= sidebar_current("docs-aci-data-source-client_end_point") %>>
61+
<a href="/docs/providers/aci/d/client_end_point.html">aci_client_end_point</a>
62+
</li>
6063
<li<%= sidebar_current("docs-aci-data-source-cloud_applicationcontainer") %>>
6164
<a href="/docs/providers/aci/d/cloud_applicationcontainer.html">aci_cloud_applicationcontainer</a>
6265
</li>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
layout: "aci"
3+
page_title: "ACI: aci_client_end_point"
4+
sidebar_current: "docs-aci-data-source-client_end_point"
5+
description: |-
6+
Data source for ACI Client End Point
7+
---
8+
9+
# aci_client_end_point #
10+
Data source for ACI Client End Point
11+
12+
## Example Usage ##
13+
14+
```hcl
15+
16+
data "aci_client_end_point" "check" {
17+
application_epg_dn = "${aci_application_epg.epg.id}"
18+
mac = "25:56:68:78:98:74"
19+
ip = "1.2.3.4"
20+
vlan = "5"
21+
}
22+
23+
```
24+
25+
26+
## Argument Reference ##
27+
* `application_epg_dn` - (Required) Distinguished name of parent ApplicationEPG object.
28+
* `name` - (Optional) name of Object client end point.
29+
* `mac` - (Optional) Mac address of the object client end point.
30+
* `ip` - (Optional) ip address of the object client end point.
31+
* `vlan` - (Optional) vlan for the object client end point.
32+
33+
34+
35+
## Attribute Reference
36+
37+
* `id` - Attribute id set as all Dns for matching the Client End Point.
38+
* `fvcep_objects` - list of all client end point objects which matched to the given filter attributes.
39+
* `fvcep_objects.name` - Name of object client end point.
40+
* `fvcep_objects.mac` - Mac address of object client end point.
41+
* `fvcep_objects.ip` - IP address of object client end point.
42+
* `fvcep_objects.vlan` - vlan of client end point object.
43+
* `fvcep_objects.tenant_name` - parent Tenant name for matched client end point.
44+
* `fvcep_objects.vrf_name` - parent vrf name for matched client end point.
45+
* `fvcep_objects.application_profile_name` - parent application profile name for matched client end point.
46+
* `fvcep_objects.epg_name` - parent epg name for matched client end point.
47+
* `fvcep_objects.l2out_name` - parent l2out name for matched client end point.
48+
* `fvcep_objects.instance_profile_name` - parent instance profile name for matched client end point.

0 commit comments

Comments
 (0)