Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for NSX-T Edge Gateway Static Routes #586

Merged
merged 7 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Didainius marked this conversation as resolved.
Show resolved Hide resolved
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
Didainius marked this conversation as resolved.
Show resolved Hide resolved
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