Skip to content

Commit

Permalink
Add support for NSX-T Edge Gateway Static Routes (#586)
Browse files Browse the repository at this point in the history
  • Loading branch information
Didainius authored Jul 14, 2023
1 parent 572755d commit c7f2584
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .changes/v2.21.0/586-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
* Added support for NSX-T Edge Gateway Static Route configuration via types
`NsxtEdgeGatewayStaticRoute`, `types.NsxtEdgeGatewayStaticRoute` and methods
`NsxtEdgeGateway.CreateStaticRoute`, `NsxtEdgeGateway.GetAllStaticRoutes`,
`NsxtEdgeGateway.GetStaticRouteByNetworkCidr`, `NsxtEdgeGateway.GetStaticRouteByName`,
`NsxtEdgeGateway.GetStaticRouteById`, `NsxtEdgeGatewayStaticRoute.Update`,
`NsxtEdgeGatewayStaticRoute.Delete` [GH-586]
26 changes: 13 additions & 13 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,19 +179,19 @@ type TestConfig struct {
VimServer string `yaml:"vimServer,omitempty"`
LdapServer string `yaml:"ldapServer,omitempty"`
Nsxt struct {
Manager string `yaml:"manager"`
Tier0router string `yaml:"tier0router"`
Tier0routerVrf string `yaml:"tier0routerVrf"`
NsxtDvpg string `yaml:"nsxtDvpg"`
GatewayQosProfile string `yaml:"gatewayQosProfile"`
Vdc string `yaml:"vdc"`
ExternalNetwork string `yaml:"externalNetwork"`
EdgeGateway string `yaml:"edgeGateway"`
NsxtImportSegment string `yaml:"nsxtImportSegment"`
VdcGroup string `yaml:"vdcGroup"`
VdcGroupEdgeGateway string `yaml:"vdcGroupEdgeGateway"`
NsxtEdgeCluster string `yaml:"nsxtEdgeCluster"`

Manager string `yaml:"manager"`
Tier0router string `yaml:"tier0router"`
Tier0routerVrf string `yaml:"tier0routerVrf"`
NsxtDvpg string `yaml:"nsxtDvpg"`
GatewayQosProfile string `yaml:"gatewayQosProfile"`
Vdc string `yaml:"vdc"`
ExternalNetwork string `yaml:"externalNetwork"`
EdgeGateway string `yaml:"edgeGateway"`
NsxtImportSegment string `yaml:"nsxtImportSegment"`
VdcGroup string `yaml:"vdcGroup"`
VdcGroupEdgeGateway string `yaml:"vdcGroupEdgeGateway"`
NsxtEdgeCluster string `yaml:"nsxtEdgeCluster"`
RoutedNetwork string `yaml:"routedNetwork"`
NsxtAlbControllerUrl string `yaml:"nsxtAlbControllerUrl"`
NsxtAlbControllerUser string `yaml:"nsxtAlbControllerUser"`
NsxtAlbControllerPassword string `yaml:"nsxtAlbControllerPassword"`
Expand Down
270 changes: 270 additions & 0 deletions govcd/nsxt_edgegateway_static_route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
/*
* Copyright 2022 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"fmt"
"net/url"

"github.com/vmware/go-vcloud-director/v2/types/v56"
)

// NsxtEdgeGatewayStaticRoute represents NSX-T Edge Gateway Static Route
type NsxtEdgeGatewayStaticRoute struct {
NsxtEdgeGatewayStaticRoute *types.NsxtEdgeGatewayStaticRoute
client *Client
// edgeGatewayId is stored for usage in NsxtEdgeGatewayStaticRoute receiver functions
edgeGatewayId string
}

// CreateStaticRoute based on type definition
func (egw *NsxtEdgeGateway) CreateStaticRoute(staticRouteConfig *types.NsxtEdgeGatewayStaticRoute) (*NsxtEdgeGatewayStaticRoute, error) {
client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayStaticRoutes
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
if err != nil {
return nil, err
}

returnObject := &NsxtEdgeGatewayStaticRoute{
client: egw.client,
edgeGatewayId: egw.EdgeGateway.ID,
NsxtEdgeGatewayStaticRoute: &types.NsxtEdgeGatewayStaticRoute{},
}

// Non standard behavior of entity - `Details` field in task contains ID of newly created object while the Owner is Edge Gateway
task, err := client.OpenApiPostItemAsync(apiVersion, urlRef, nil, staticRouteConfig)
if err != nil {
return nil, fmt.Errorf("error creating NSX-T Edge Gateway Static Route: %s", err)
}

err = task.WaitTaskCompletion()
if err != nil {
return nil, fmt.Errorf("error creating NSX-T Edge Gateway Static Route: %s", err)
}

// API does not return an ID for created object - we know that it is expected to be in
// task.Task.Details therefore attempt to find it, but if it is empty - look for an entity by a
// set of requested parameters
staticRouteId := task.Task.Details
if staticRouteId != "" {
getUrlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID), staticRouteId)
if err != nil {
return nil, err
}
err = client.OpenApiGetItem(apiVersion, getUrlRef, nil, returnObject.NsxtEdgeGatewayStaticRoute, nil)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway Static Route after creation: %s", err)
}
} else {
// ID was not present in response, therefore Static Route needs to be found manually. Using
// 'Name', 'Description' and 'NetworkCidr' for finding the entity. Duplicate entries can
// exist, but but it should be a good enough combination for finding unique entry until VCD API is fixed
allStaticRoutes, err := egw.GetAllStaticRoutes(nil)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway Static Route after creation: %s", err)
}

var foundStaticRoute bool
for _, singleStaticRoute := range allStaticRoutes {
if singleStaticRoute.NsxtEdgeGatewayStaticRoute.Name == staticRouteConfig.Name &&
singleStaticRoute.NsxtEdgeGatewayStaticRoute.NetworkCidr == staticRouteConfig.NetworkCidr &&
singleStaticRoute.NsxtEdgeGatewayStaticRoute.Description == staticRouteConfig.Description {
foundStaticRoute = true
returnObject = singleStaticRoute
break
}
}

if !foundStaticRoute {
return nil, fmt.Errorf("error finding Static Route after creation by Name '%s', NetworkCidr '%s', Description '%s'",
staticRouteConfig.Name, staticRouteConfig.NetworkCidr, staticRouteConfig.Description)
}

}

return returnObject, nil
}

// GetAllStaticRoutes retrieves all Static Routes for a particular NSX-T Edge Gateway
func (egw *NsxtEdgeGateway) GetAllStaticRoutes(queryParameters url.Values) ([]*NsxtEdgeGatewayStaticRoute, error) {
client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayStaticRoutes
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
if err != nil {
return nil, err
}

typeResponses := []*types.NsxtEdgeGatewayStaticRoute{{}}
err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParameters, &typeResponses, nil)
if err != nil {
return nil, err
}

wrappedResponses := make([]*NsxtEdgeGatewayStaticRoute, len(typeResponses))
for sliceIndex := range typeResponses {
wrappedResponses[sliceIndex] = &NsxtEdgeGatewayStaticRoute{
NsxtEdgeGatewayStaticRoute: typeResponses[sliceIndex],
client: client,
edgeGatewayId: egw.EdgeGateway.ID,
}
}

return wrappedResponses, nil
}

// GetStaticRouteByNetworkCidr retrieves Static Route by network CIDR
//
// Note. It will return an error if more than one items is found
func (egw *NsxtEdgeGateway) GetStaticRouteByNetworkCidr(networkCidr string) (*NsxtEdgeGatewayStaticRoute, error) {
if networkCidr == "" {
return nil, fmt.Errorf("cidr cannot be empty")
}

allStaticRoutes, err := egw.GetAllStaticRoutes(nil)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway Static Route: %s", err)
}

filteredByNetworkCidr := make([]*NsxtEdgeGatewayStaticRoute, 0)
for _, sr := range allStaticRoutes {
if sr.NsxtEdgeGatewayStaticRoute.NetworkCidr == networkCidr {
filteredByNetworkCidr = append(filteredByNetworkCidr, sr)
}
}

singleResult, err := oneOrError("networkCidr", networkCidr, filteredByNetworkCidr)
if err != nil {
return nil, err
}

return singleResult, nil
}

// GetStaticRouteByName retrieves Static Route by name
//
// Note. It will return an error if more than one items is found
func (egw *NsxtEdgeGateway) GetStaticRouteByName(name string) (*NsxtEdgeGatewayStaticRoute, error) {
if name == "" {
return nil, fmt.Errorf("cidr cannot be empty")
}

allStaticRoutes, err := egw.GetAllStaticRoutes(nil)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway Static Route: %s", err)
}

filteredByNetworkName := make([]*NsxtEdgeGatewayStaticRoute, 0)
// First - filter by name
for _, sr := range allStaticRoutes {
if sr.NsxtEdgeGatewayStaticRoute.Name == name {
filteredByNetworkName = append(filteredByNetworkName, sr)
}
}

singleResult, err := oneOrError("name", name, filteredByNetworkName)
if err != nil {
return nil, err
}

return singleResult, nil
}

// GetStaticRouteById retrieves Static Route by given ID
func (egw *NsxtEdgeGateway) GetStaticRouteById(id string) (*NsxtEdgeGatewayStaticRoute, error) {
if id == "" {
return nil, fmt.Errorf("ID is required")
}

client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayStaticRoutes
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID), id)
if err != nil {
return nil, err
}

returnObject := &NsxtEdgeGatewayStaticRoute{
client: egw.client,
edgeGatewayId: egw.EdgeGateway.ID,
NsxtEdgeGatewayStaticRoute: &types.NsxtEdgeGatewayStaticRoute{},
}

err = client.OpenApiGetItem(apiVersion, urlRef, nil, returnObject.NsxtEdgeGatewayStaticRoute, nil)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway Static Route: %s", err)
}

return returnObject, nil
}

// Update Static Route
func (staticRoute *NsxtEdgeGatewayStaticRoute) Update(StaticRouteConfig *types.NsxtEdgeGatewayStaticRoute) (*NsxtEdgeGatewayStaticRoute, error) {
client := staticRoute.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayStaticRoutes
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, staticRoute.edgeGatewayId), StaticRouteConfig.ID)
if err != nil {
return nil, err
}

returnObject := &NsxtEdgeGatewayStaticRoute{
client: staticRoute.client,
edgeGatewayId: staticRoute.edgeGatewayId,
NsxtEdgeGatewayStaticRoute: &types.NsxtEdgeGatewayStaticRoute{},
}

err = client.OpenApiPutItem(apiVersion, urlRef, nil, StaticRouteConfig, returnObject.NsxtEdgeGatewayStaticRoute, nil)
if err != nil {
return nil, fmt.Errorf("error setting NSX-T Edge Gateway Static Route: %s", err)
}

return returnObject, nil
}

// Delete Static Route
func (staticRoute *NsxtEdgeGatewayStaticRoute) Delete() error {
client := staticRoute.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayStaticRoutes
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return err
}

// Insert Edge Gateway ID into endpoint path
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, staticRoute.edgeGatewayId), staticRoute.NsxtEdgeGatewayStaticRoute.ID)
if err != nil {
return err
}

err = client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil)
if err != nil {
return fmt.Errorf("error deleting NSX-T Edge Gateway Static Route: %s", err)
}

return nil
}
Loading

0 comments on commit c7f2584

Please sign in to comment.