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

TM Provider Gateway #725

Merged
merged 27 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 25 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
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 @@ -168,6 +168,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 @@ -257,6 +259,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
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
Loading