Skip to content

Commit

Permalink
[bugfix] Fix issue with Client End Points when Endpoint is associated…
Browse files Browse the repository at this point in the history
… with an ESG
  • Loading branch information
lhercot committed Apr 4, 2023
1 parent f7bacf4 commit 82823d1
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 40 deletions.
92 changes: 74 additions & 18 deletions aci/data_source_aci_fvcep.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ func dataSourceAciClientEndPoint() *schema.Resource {
Computed: true,
},

"esg_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"l2out_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Expand All @@ -122,6 +128,14 @@ func dataSourceAciClientEndPoint() *schema.Resource {
Type: schema.TypeString,
},
},

"base_epg": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
Expand All @@ -135,6 +149,10 @@ func extractInfo(con *container.Container) (obj map[string]interface{}, dn strin
infoMap["name"] = models.G(con, "name")
infoMap["mac"] = models.G(con, "mac")
infoMap["ip"] = models.G(con, "ip")
if infoMap["ip"] == "{}" {
infoMap["ip"] = ""
}

infoMap["vlan"] = models.G(con, "encap")

dnInfoList := strings.Split(dnString, "/")
Expand All @@ -152,6 +170,26 @@ func extractInfo(con *container.Container) (obj map[string]interface{}, dn strin
level3Info := regexp.MustCompile("-").Split(dnInfoList[3], 2)
if level3Info[0] == "epg" {
infoMap["epg_name"] = level3Info[1]
} else if level3Info[0] == "esg" {
infoMap["esg_name"] = level3Info[1]
baseEpgDnInfoList := strings.Split(models.G(con, "baseEpgDn"), "/")
baseEpgTenantInfo := regexp.MustCompile("-").Split(baseEpgDnInfoList[1], 2)
if baseEpgTenantInfo[0] == "tn" {
baseEpgTenantName := baseEpgTenantInfo[1]
baseEpgLevel2Info := regexp.MustCompile("-").Split(baseEpgDnInfoList[2], 2)
if baseEpgLevel2Info[0] == "ap" {
baseEpgApplicationProfileName := baseEpgLevel2Info[1]
baseEpgLevel3Info := regexp.MustCompile("-").Split(baseEpgDnInfoList[3], 2)
if baseEpgLevel3Info[0] == "epg" {
baseEpgEpgName := baseEpgLevel3Info[1]
infoMap["base_epg"] = map[string]interface{}{
"tenant_name": baseEpgTenantName,
"application_profile_name": baseEpgApplicationProfileName,
"epg_name": baseEpgEpgName,
}
}
}
}
} else {
return nil, ""
}
Expand Down Expand Up @@ -205,7 +243,7 @@ func getRemoteClientEndPoint(client *client.Client, query string, allowEmptyResu
if query == "" {
duURL = fmt.Sprintf("%s/fvCEp.json", baseURL)
} else {
duURL = fmt.Sprintf("%s/fvCEp.json?query-target-filter=or(%s)&rsp-subtree=children&rsp-subtree-class=fvIp", baseURL, query)
duURL = fmt.Sprintf("%s/fvCEp.json?query-target-filter=and(%s)&rsp-subtree=children&rsp-subtree-class=fvIp", baseURL, query)
}

fvCEpCont, err := client.GetViaURL(duURL)
Expand All @@ -230,21 +268,24 @@ func getRemoteClientEndPoint(client *client.Client, query string, allowEmptyResu
objMap, dn := extractInfo(clientEndPointCont.S("fvCEp", "attributes"))

// Reading fvIp object properties
fvIpObjects, err := clientEndPointCont.S("fvCEp").Children()
if err != nil {
return nil, nil, err
}
ips := make([]string, 0, 1)

fvIpObjects, err := clientEndPointCont.S("fvCEp", "children").Children()
if err == nil {
for j := 0; j < len(fvIpObjects); j++ {
ips = append(ips, models.G(fvIpObjects[j].S("fvIp", "attributes"), "addr"))
ips := make([]string, 0, 1)

if err == nil {
for j := 0; j < len(fvIpObjects); j++ {
ips = append(ips, models.G(fvIpObjects[j].S("fvIp", "attributes"), "addr"))
}
}
}

objMap["ips"] = ips
if len(ips) > 0 {
objMap["ip"] = ips[0]
objMap["ips"] = ips
if len(ips) > 0 {
objMap["ip"] = ips[0]
}
} else {
if errors.Is(err, container.ErrNotObjOrArray) == false {
return nil, nil, err
}
}

if dn != "" {
Expand All @@ -267,6 +308,8 @@ func getRemoteClientEndPoint(client *client.Client, query string, allowEmptyResu
func dataSourceAciClientEndPointRead(d *schema.ResourceData, m interface{}) error {
aciClient := m.(*client.Client)

allowEmptyResult := d.Get("allow_empty_result").(bool)

var queryString string
if mac, ok := d.GetOk("mac"); ok {
if queryString != "" {
Expand All @@ -292,6 +335,13 @@ func dataSourceAciClientEndPointRead(d *schema.ResourceData, m interface{}) erro
} else {
queryString = tempQueryString
}
} else {
d.SetId("")
if allowEmptyResult {
return nil
} else {
return errors.New("Error retrieving Object: Object may not exists")
}
}
d.Set("ip", ip)
}
Expand All @@ -312,15 +362,21 @@ func dataSourceAciClientEndPointRead(d *schema.ResourceData, m interface{}) erro
}
}

allowEmptyResult := d.Get("allow_empty_result")

objects, dns, err := getRemoteClientEndPoint(aciClient, queryString, allowEmptyResult.(bool))
objects, dns, err := getRemoteClientEndPoint(aciClient, queryString, allowEmptyResult)
if err != nil {
return err
}

d.Set("fvcep_objects", objects)
d.SetId(strings.Join(dns, " "))
if objects != nil {
d.Set("fvcep_objects", objects)
}

if dns != nil {
d.SetId(strings.Join(dns, " "))
} else {
d.SetId("")
}

return nil
}

Expand Down
45 changes: 23 additions & 22 deletions aci/resource_aci_fvesg.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,28 +140,29 @@ func resourceAciEndpointSecurityGroup() *schema.Resource {
Optional: true,
Description: "Create relation to vzBrCP",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{"match_t": {
Optional: true,
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"All",
"AtleastOne",
"AtmostOne",
"None",
}, false),
}, "prio": {
Optional: true,
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"level1",
"level2",
"level3",
"level4",
"level5",
"level6",
"unspecified",
}, false),
},
Schema: map[string]*schema.Schema{
"match_t": {
Optional: true,
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"All",
"AtleastOne",
"AtmostOne",
"None",
}, false),
}, "prio": {
Optional: true,
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"level1",
"level2",
"level3",
"level4",
"level5",
"level6",
"unspecified",
}, false),
},
"target_dn": {
Required: true,
Type: schema.TypeString,
Expand Down
23 changes: 23 additions & 0 deletions examples/aci_client_end_point/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
terraform {
required_providers {
aci = {
source = "ciscodevnet/aci"
}
}
}

provider "aci" {
username = ""
password = ""
url = ""
insecure = true
}

data "aci_client_end_point" "this" {
ip = "10.1.1.33"
allow_empty_result = true
}

output "mac_endpoints" {
value = data.aci_client_end_point.this.fvcep_objects
}
4 changes: 4 additions & 0 deletions website/docs/d/client_end_point.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ data "aci_client_end_point" "check" {
- `fvcep_objects.vrf_name` - Parent VRF name of the Client End Point object.
- `fvcep_objects.application_profile_name` - Parent Application Profile name of the Client End Point object.
- `fvcep_objects.epg_name` - Parent EPG name of the Client End Point object.
- `fvcep_objects.esg_name` - Parent ESG name of the Client End Point object.
- `fvcep_objects.l2out_name` - Parent L2Out name of the Client End Point object.
- `fvcep_objects.instance_profile_name` - Parent Instance Profile name of the Client End Point object.
- `fvcep_objects.endpoint_path` - List of endpoint paths associated with the Client End Point object.
- `fvcep_objects.base_epg.tenant_name` - Name of the Tenant of the base EPG of the Client End Point object when the Client End Point is associated with an ESG.
- `fvcep_objects.base_epg.application_profile_name` - Name of the Application Profile of the base EPG of the Client End Point object when the Client End Point is associated with an ESG.
- `fvcep_objects.base_epg.epg_name` - Name of the base EPG of the Client End Point object when the Client End Point is associated with an ESG.

0 comments on commit 82823d1

Please sign in to comment.