Skip to content

Commit

Permalink
TM Provider Gateway (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
Didainius authored Dec 20, 2024
1 parent 150245e commit 05b2e43
Show file tree
Hide file tree
Showing 11 changed files with 571 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .changes/v3.0.0/725-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
* Added `TmProviderGateway` and `types.TmProviderGateway` structures and methods
`VCDClient.CreateTmProviderGateway`, `VCDClient.GetAllTmProviderGateways`,
`VCDClient.GetTmProviderGatewayByName`, `VCDClient.GetTmProviderGatewayById`,
`VCDClient.GetTmProviderGatewayByNameAndRegionId`, `TmProviderGateway.Update`,
`TmProviderGateway.Delete` to manage Provider Gateways [GH-725]
* Added `TmTier0Gateway` and `types.TmTier0Gateway` structures and methods
`VCDClient.GetAllTmTier0GatewaysWithContext`, `VCDClient.GetTmTier0GatewayWithContextByName` to
read Tier 0 Gateways that are available for TM consumption [GH-725]
* Added `TmIpSpaceAssociation` and `types.TmIpSpaceAssociation` structures and methods
`VCDClient.CreateTmIpSpaceAssociation`, `VCDClient.GetAllTmIpSpaceAssociations`,
`VCDClient.GetTmIpSpaceAssociationById`,
`VCDClient.GetAllTmIpSpaceAssociationsByProviderGatewayId`,
`VCDClient.GetAllTmIpSpaceAssociationsByIpSpaceId`, `TmIpSpaceAssociation.Delete` to manage IP
Space associations with Provider Gateways [GH-725]
1 change: 1 addition & 0 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ type TestConfig struct {
NsxtManagerUsername string `yaml:"nsxtManagerUsername"`
NsxtManagerPassword string `yaml:"nsxtManagerPassword"`
NsxtManagerUrl string `yaml:"nsxtManagerUrl"`
NsxtTier0Gateway string `yaml:"nsxtTier0Gateway"`
} `yaml:"tm,omitempty"`
VCD struct {
Org string `yaml:"org"`
Expand Down
5 changes: 5 additions & 0 deletions govcd/openapi_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ var endpointMinApiVersions = map[string]string{
types.OpenApiPathVcf + types.OpenApiEndpointZones: "40.0",
types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs: "40.0",
types.OpenApiPathVcf + types.OpenApiEndpointTmIpSpaces: "40.0",
types.OpenApiPathVcf + types.OpenApiEndpointTmProviderGateways: "40.0",
types.OpenApiPathVcf + types.OpenApiEndpointTmIpSpaceAssociations: "40.0",
}

// endpointElevatedApiVersions endpoint elevated API versions
Expand Down Expand Up @@ -258,6 +260,9 @@ var endpointElevatedApiVersions = map[string][]string{
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointOrgs: {
"40.0", // TM Orgs
},
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointImportableTier0Routers: {
"40.0", // TM Tier 0 Gateways
},
}

// checkOpenApiEndpointCompatibility checks if VCD version (to which the client is connected) is sufficient to work with
Expand Down
1 change: 1 addition & 0 deletions govcd/sample_govcd_test_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,4 @@ tm:
nsxtManagerUsername: username for NSX-T Manager
nsxtManagerPassword: password for NSX-T Manager
nsxtManagerUrl: https://HOST
nsxtTier0Gateway: tier0gateway
31 changes: 31 additions & 0 deletions govcd/tm_common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package govcd

import (
"fmt"
"net/url"
"time"

Expand Down Expand Up @@ -235,3 +236,33 @@ func createOrg(vcd *TestVCD, check *C, canManageOrgs bool) (*TmOrg, func()) {
check.Assert(err, IsNil)
}
}

func createTmIpSpace(vcd *TestVCD, region *Region, check *C, nameSuffix, octet3 string) (*TmIpSpace, func()) {
ipSpaceType := &types.TmIpSpace{
Name: check.TestName() + "-" + nameSuffix,
RegionRef: types.OpenApiReference{ID: region.Region.ID},
Description: check.TestName(),
DefaultQuota: types.TmIpSpaceDefaultQuota{
MaxCidrCount: 3,
MaxIPCount: -1,
MaxSubnetSize: 24,
},
ExternalScopeCidr: fmt.Sprintf("12.12.%s.0/30", octet3),
InternalScopeCidrBlocks: []types.TmIpSpaceInternalScopeCidrBlocks{
{
Cidr: fmt.Sprintf("10.0.%s.0/24", octet3),
},
},
}

ipSpace, err := vcd.client.CreateTmIpSpace(ipSpaceType)
check.Assert(err, IsNil)
check.Assert(ipSpace, NotNil)
AddToCleanupListOpenApi(ipSpace.TmIpSpace.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmIpSpaces+ipSpace.TmIpSpace.ID)

return ipSpace, func() {
printVerbose("# Deleting IP Space %s\n", ipSpace.TmIpSpace.Name)
err = ipSpace.Delete()
check.Assert(err, IsNil)
}
}
98 changes: 98 additions & 0 deletions govcd/tm_ip_space_associations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package govcd

import (
"fmt"
"net/url"

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

const labelTmIpSpaceAssociation = "TM IP Space Association"

// TmIpSpaceAssociation manages associations between Provider Gateways and IP Spaces. Each
// association results in a separate entity. There is no update option. The first association is
// created automatically when a Provider Gateway (`TmProviderGateway`) is created.
type TmIpSpaceAssociation struct {
TmIpSpaceAssociation *types.TmIpSpaceAssociation
vcdClient *VCDClient
}

// wrap is a hidden helper that facilitates the usage of a generic CRUD function
//
//lint:ignore U1000 this method is used in generic functions, but annoys staticcheck
func (g TmIpSpaceAssociation) wrap(inner *types.TmIpSpaceAssociation) *TmIpSpaceAssociation {
g.TmIpSpaceAssociation = inner
return &g
}

// Creates TM IP Space Association with Provider Gateway
func (vcdClient *VCDClient) CreateTmIpSpaceAssociation(config *types.TmIpSpaceAssociation) (*TmIpSpaceAssociation, error) {
c := crudConfig{
entityLabel: labelTmIpSpaceAssociation,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmIpSpaceAssociations,
requiresTm: true,
}
outerType := TmIpSpaceAssociation{vcdClient: vcdClient}
return createOuterEntity(&vcdClient.Client, outerType, c, config)
}

// GetAllTmIpSpaceAssociations retrieves all TM IP Space and Provider Gateway associations
func (vcdClient *VCDClient) GetAllTmIpSpaceAssociations(queryParameters url.Values) ([]*TmIpSpaceAssociation, error) {
c := crudConfig{
entityLabel: labelTmIpSpaceAssociation,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmIpSpaceAssociations,
queryParameters: queryParameters,
requiresTm: true,
}

outerType := TmIpSpaceAssociation{vcdClient: vcdClient}
return getAllOuterEntities(&vcdClient.Client, outerType, c)
}

// GetTmIpSpaceAssociationById retrieves a single IP Spaces and Provider Gateway association by ID
func (vcdClient *VCDClient) GetTmIpSpaceAssociationById(id string) (*TmIpSpaceAssociation, error) {
c := crudConfig{
entityLabel: labelTmIpSpaceAssociation,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmIpSpaceAssociations,
endpointParams: []string{id},
requiresTm: true,
}

outerType := TmIpSpaceAssociation{vcdClient: vcdClient}
return getOuterEntity(&vcdClient.Client, outerType, c)
}

// GetAllTmIpSpaceAssociationsByProviderGatewayId retrieves all IP Space associations to a
// particulat Provider Gateway
func (vcdClient *VCDClient) GetAllTmIpSpaceAssociationsByProviderGatewayId(providerGatewayId string) ([]*TmIpSpaceAssociation, error) {
if providerGatewayId == "" {
return nil, fmt.Errorf("%s lookup requires %s ID", labelTmIpSpaceAssociation, labelTmProviderGateway)
}

queryParams := url.Values{}
queryParams = queryParameterFilterAnd("providerGatewayRef.id=="+providerGatewayId, queryParams)

return vcdClient.GetAllTmIpSpaceAssociations(queryParams)
}

// GetAllTmIpSpaceAssociationsByIpSpaceId retrieves all associations for a given IP Space ID
func (vcdClient *VCDClient) GetAllTmIpSpaceAssociationsByIpSpaceId(ipSpaceId string) ([]*TmIpSpaceAssociation, error) {
if ipSpaceId == "" {
return nil, fmt.Errorf("%s lookup requires %s ID", labelTmIpSpaceAssociation, labelTmProviderGateway)
}

queryParams := url.Values{}
queryParams = queryParameterFilterAnd("ipSpaceRef.id=="+ipSpaceId, queryParams)
return vcdClient.GetAllTmIpSpaceAssociations(queryParams)
}

// Delete the association
func (o *TmIpSpaceAssociation) Delete() error {
c := crudConfig{
entityLabel: labelTmIpSpaceAssociation,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmIpSpaceAssociations,
endpointParams: []string{o.TmIpSpaceAssociation.ID},
requiresTm: true,
}
return deleteEntityById(&o.vcdClient.Client, c)
}
133 changes: 133 additions & 0 deletions govcd/tm_provider_gateway.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package govcd

import (
"fmt"
"net/url"

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

const labelTmProviderGateway = "TM Provider Gateway"

// TmProviderGateway manages Provider Gateway creation and configuration.
//
// NOTE. While creation of Provider Gateway requires at least one IP Space (`TmIpSpace`) reference,
// they are not being returned by API after creation. One must use `TmIpSpaceAssociation` for
// managing IP Space associations with Provider gateways after their initial creation is done.
type TmProviderGateway struct {
TmProviderGateway *types.TmProviderGateway
vcdClient *VCDClient
}

// wrap is a hidden helper that facilitates the usage of a generic CRUD function
//
//lint:ignore U1000 this method is used in generic functions, but annoys staticcheck
func (g TmProviderGateway) wrap(inner *types.TmProviderGateway) *TmProviderGateway {
g.TmProviderGateway = inner
return &g
}

// Creates TM Provider Gateway with provided configuration
func (vcdClient *VCDClient) CreateTmProviderGateway(config *types.TmProviderGateway) (*TmProviderGateway, error) {
c := crudConfig{
entityLabel: labelTmProviderGateway,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmProviderGateways,
requiresTm: true,
}
outerType := TmProviderGateway{vcdClient: vcdClient}
return createOuterEntity(&vcdClient.Client, outerType, c, config)
}

// GetAllTmProviderGateways retrieves all Provider Gateways with optional filter
func (vcdClient *VCDClient) GetAllTmProviderGateways(queryParameters url.Values) ([]*TmProviderGateway, error) {
c := crudConfig{
entityLabel: labelTmProviderGateway,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmProviderGateways,
queryParameters: queryParameters,
requiresTm: true,
}

outerType := TmProviderGateway{vcdClient: vcdClient}
return getAllOuterEntities(&vcdClient.Client, outerType, c)
}

// GetTmProviderGatewayByName retrieves Provider Gateway by Name
func (vcdClient *VCDClient) GetTmProviderGatewayByName(name string) (*TmProviderGateway, error) {
if name == "" {
return nil, fmt.Errorf("%s lookup requires name", labelTmProviderGateway)
}

queryParams := url.Values{}
queryParams.Add("filter", "name=="+name)

filteredEntities, err := vcdClient.GetAllTmProviderGateways(queryParams)
if err != nil {
return nil, err
}

singleEntity, err := oneOrError("name", name, filteredEntities)
if err != nil {
return nil, err
}

return vcdClient.GetTmProviderGatewayById(singleEntity.TmProviderGateway.ID)
}

// GetTmProviderGatewayById retrieves a given Provider Gateway by ID
func (vcdClient *VCDClient) GetTmProviderGatewayById(id string) (*TmProviderGateway, error) {
c := crudConfig{
entityLabel: labelTmProviderGateway,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmProviderGateways,
endpointParams: []string{id},
requiresTm: true,
}

outerType := TmProviderGateway{vcdClient: vcdClient}
return getOuterEntity(&vcdClient.Client, outerType, c)
}

// GetTmProviderGatewayByNameAndRegionId retrieves Provider Gateway by name in a given Region
func (vcdClient *VCDClient) GetTmProviderGatewayByNameAndRegionId(name, regionId string) (*TmProviderGateway, error) {
if name == "" || regionId == "" {
return nil, fmt.Errorf("%s lookup requires name and Org ID", labelTmProviderGateway)
}

queryParams := url.Values{}
queryParams.Add("filter", "name=="+name)
queryParams = queryParameterFilterAnd("regionRef.id=="+regionId, queryParams)

filteredEntities, err := vcdClient.GetAllTmProviderGateways(queryParams)
if err != nil {
return nil, err
}

singleEntity, err := oneOrError("name", name, filteredEntities)
if err != nil {
return nil, err
}

return vcdClient.GetTmProviderGatewayById(singleEntity.TmProviderGateway.ID)
}

// Update existing Provider Gateway
func (o *TmProviderGateway) Update(TmProviderGatewayConfig *types.TmProviderGateway) (*TmProviderGateway, error) {
c := crudConfig{
entityLabel: labelTmProviderGateway,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmProviderGateways,
endpointParams: []string{o.TmProviderGateway.ID},
requiresTm: true,
}
outerType := TmProviderGateway{vcdClient: o.vcdClient}
return updateOuterEntity(&o.vcdClient.Client, outerType, c, TmProviderGatewayConfig)
}

// Delete Provider Gateway
func (o *TmProviderGateway) Delete() error {
c := crudConfig{
entityLabel: labelTmProviderGateway,
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmProviderGateways,
endpointParams: []string{o.TmProviderGateway.ID},
requiresTm: true,
}
return deleteEntityById(&o.vcdClient.Client, c)
}
Loading

0 comments on commit 05b2e43

Please sign in to comment.