Skip to content

Commit dc93038

Browse files
committed
Consumption of Generic functions
1 parent 4d5a06a commit dc93038

10 files changed

+450
-537
lines changed

govcd/adminorg_ldap_test.go

-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package govcd
88

99
import (
1010
"fmt"
11-
"time"
1211

1312
"github.com/vmware/go-vcloud-director/v2/types/v56"
1413
. "gopkg.in/check.v1"
@@ -62,10 +61,6 @@ func (vcd *TestVCD) Test_LDAP(check *C) {
6261
check.Assert(err, IsNil)
6362
}()
6463

65-
sleepTime := 10 * time.Second
66-
fmt.Printf("# Sleeping %s to prevent 'LDAP context not initialized' errors\n", sleepTime.String())
67-
time.Sleep(sleepTime)
68-
6964
// Run tests requiring LDAP from here.
7065
vcd.test_GroupCRUD(check)
7166
vcd.test_GroupFinderGetGenericEntity(check)

govcd/ip_space_generic.go

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
3+
*/
4+
5+
package govcd
6+
7+
import (
8+
"fmt"
9+
"net/url"
10+
11+
"github.com/vmware/go-vcloud-director/v2/types/v56"
12+
)
13+
14+
// IpSpace provides structured approach to allocating public and private IP addresses by preventing
15+
// the use of overlapping IP addresses across organizations and organization VDCs.
16+
//
17+
// An IP space consists of a set of defined non-overlapping IP ranges and small CIDR blocks that are
18+
// reserved and used during the consumption aspect of the IP space life cycle. An IP space can be
19+
// either IPv4 or IPv6, but not both.
20+
//
21+
// Every IP space has an internal scope and an external scope. The internal scope of an IP space is
22+
// a list of CIDR notations that defines the exact span of IP addresses in which all ranges and
23+
// blocks must be contained in. The external scope defines the total span of IP addresses to which
24+
// the IP space has access, for example the internet or a WAN.
25+
type GenericIpSpace2 struct {
26+
IpSpace *types.IpSpace
27+
vcdClient *VCDClient
28+
}
29+
30+
// wrap is a hidden helper that helps to facilitate usage of generic CRUD function
31+
//
32+
//lint:ignore U1000 this method is used in generic functions, but annoys staticcheck
33+
func (g GenericIpSpace2) wrap(inner *types.IpSpace) *GenericIpSpace2 {
34+
g.IpSpace = inner
35+
return &g
36+
}
37+
38+
// CreateIpSpace creates IP Space with desired configuration
39+
func (vcdClient *VCDClient) GenCreateIpSpace(ipSpaceConfig *types.IpSpace) (*GenericIpSpace2, error) {
40+
c := crudConfig{
41+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
42+
entityName: "IP Space",
43+
}
44+
outerType := GenericIpSpace2{vcdClient: vcdClient}
45+
return createOuterEntity(&vcdClient.Client, outerType, c, ipSpaceConfig)
46+
}
47+
48+
// GetAllIpSpaceSummaries retrieve summaries of all IP Spaces with an optional filter
49+
// Note. There is no API endpoint to get multiple IP Spaces with their full definitions. Only
50+
// "summaries" endpoint exists, but it does not include all fields. To retrieve complete structure
51+
// one can use `GetIpSpaceById` or `GetIpSpaceByName`
52+
func (vcdClient *VCDClient) GenGetAllIpSpaceSummaries(queryParameters url.Values) ([]*GenericIpSpace2, error) {
53+
c := crudConfig{
54+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaceSummaries,
55+
entityName: "IP Space",
56+
queryParameters: queryParameters,
57+
}
58+
59+
outerType := GenericIpSpace2{vcdClient: vcdClient}
60+
return getAllOuterEntities[GenericIpSpace2, types.IpSpace](&vcdClient.Client, outerType, c)
61+
}
62+
63+
// GetIpSpaceById retrieves IP Space with a given ID
64+
func (vcdClient *VCDClient) GenGetIpSpaceById(id string) (*GenericIpSpace2, error) {
65+
66+
c := crudConfig{
67+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
68+
endpointParams: []string{id},
69+
entityName: "IP Space",
70+
}
71+
72+
outerType := GenericIpSpace2{vcdClient: vcdClient}
73+
return getOuterEntity[GenericIpSpace2, types.IpSpace](&vcdClient.Client, outerType, c)
74+
}
75+
76+
// GetIpSpaceByName retrieves IP Space with a given name
77+
// Note. It will return an error if multiple IP Spaces exist with the same name
78+
func (vcdClient *VCDClient) GenGetIpSpaceByName(name string) (*GenericIpSpace2, error) {
79+
if name == "" {
80+
return nil, fmt.Errorf("IP Space lookup requires name")
81+
}
82+
83+
queryParams := url.Values{}
84+
queryParams.Add("filter", "name=="+name)
85+
86+
filteredEntities, err := vcdClient.GenGetAllIpSpaceSummaries(queryParams)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
singleIpSpace, err := oneOrError("name", name, filteredEntities)
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
return vcdClient.GenGetIpSpaceById(singleIpSpace.IpSpace.ID)
97+
}
98+
99+
// GetIpSpaceByNameAndOrgId retrieves IP Space with a given name in a particular Org
100+
// Note. Only PRIVATE IP spaces belong to Orgs
101+
func (vcdClient *VCDClient) GenGetIpSpaceByNameAndOrgId(name, orgId string) (*GenericIpSpace2, error) {
102+
if name == "" || orgId == "" {
103+
return nil, fmt.Errorf("IP Space lookup requires name and Org ID")
104+
}
105+
106+
queryParams := url.Values{}
107+
queryParams.Add("filter", "name=="+name)
108+
queryParams = queryParameterFilterAnd("orgRef.id=="+orgId, queryParams)
109+
110+
filteredEntities, err := vcdClient.GenGetAllIpSpaceSummaries(queryParams)
111+
if err != nil {
112+
return nil, err
113+
}
114+
115+
singleIpSpace, err := oneOrError("name", name, filteredEntities)
116+
if err != nil {
117+
return nil, err
118+
}
119+
120+
return vcdClient.GenGetIpSpaceById(singleIpSpace.IpSpace.ID)
121+
}
122+
123+
// Update updates IP Space with new config
124+
func (ipSpace *GenericIpSpace2) Update(ipSpaceConfig *types.IpSpace) (*GenericIpSpace2, error) {
125+
c := crudConfig{
126+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
127+
endpointParams: []string{ipSpaceConfig.ID},
128+
entityName: "IP Space",
129+
}
130+
outerType := GenericIpSpace2{vcdClient: ipSpace.vcdClient}
131+
return updateOuterEntity(&ipSpace.vcdClient.Client, outerType, c, ipSpaceConfig)
132+
}
133+
134+
// Delete deletes IP Space
135+
func (ipSpace *GenericIpSpace2) Delete() error {
136+
c := crudConfig{
137+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
138+
endpointParams: []string{ipSpace.IpSpace.ID},
139+
entityName: "IP Space",
140+
}
141+
return deleteEntityById(&ipSpace.vcdClient.Client, c)
142+
}

govcd/ip_space_generic_test.go

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//go:build network || nsxt || functional || openapi || ALL
2+
3+
package govcd
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/vmware/go-vcloud-director/v2/types/v56"
9+
. "gopkg.in/check.v1"
10+
)
11+
12+
func (vcd *TestVCD) Test_GenericIpSpacePublic(check *C) {
13+
if vcd.skipAdminTests {
14+
check.Skip(fmt.Sprintf(TestRequiresSysAdminPrivileges, check.TestName()))
15+
}
16+
skipNoNsxtConfiguration(vcd, check)
17+
skipOpenApiEndpointTest(vcd, check, types.OpenApiPathVersion1_0_0+types.OpenApiEndpointIpSpaces)
18+
19+
ipSpaceConfig := &types.IpSpace{
20+
Name: check.TestName(),
21+
IPSpaceInternalScope: []string{"22.0.0.0/24"},
22+
IPSpaceExternalScope: "200.0.0.1/24",
23+
Type: types.IpSpacePublic,
24+
RouteAdvertisementEnabled: false,
25+
IPSpacePrefixes: []types.IPSpacePrefixes{
26+
{
27+
DefaultQuotaForPrefixLength: -1,
28+
IPPrefixSequence: []types.IPPrefixSequence{
29+
{
30+
StartingPrefixIPAddress: "22.0.0.200",
31+
PrefixLength: 31,
32+
TotalPrefixCount: 3,
33+
},
34+
},
35+
},
36+
{
37+
DefaultQuotaForPrefixLength: 2,
38+
IPPrefixSequence: []types.IPPrefixSequence{
39+
{
40+
StartingPrefixIPAddress: "22.0.0.100",
41+
PrefixLength: 30,
42+
TotalPrefixCount: 3,
43+
},
44+
},
45+
},
46+
},
47+
IPSpaceRanges: types.IPSpaceRanges{
48+
DefaultFloatingIPQuota: 3,
49+
IPRanges: []types.IpSpaceRangeValues{
50+
{
51+
StartIPAddress: "22.0.0.10",
52+
EndIPAddress: "22.0.0.30",
53+
},
54+
{
55+
StartIPAddress: "22.0.0.32",
56+
EndIPAddress: "22.0.0.34",
57+
},
58+
},
59+
},
60+
}
61+
62+
createdIpSpace, err := vcd.client.GenCreateIpSpace(ipSpaceConfig)
63+
check.Assert(err, IsNil)
64+
check.Assert(createdIpSpace, NotNil)
65+
66+
openApiEndpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces + createdIpSpace.IpSpace.ID
67+
AddToCleanupListOpenApi(createdIpSpace.IpSpace.Name, check.TestName(), openApiEndpoint)
68+
69+
// Get by ID
70+
byId, err := vcd.client.GenGetIpSpaceById(createdIpSpace.IpSpace.ID)
71+
check.Assert(err, IsNil)
72+
check.Assert(byId.IpSpace, DeepEquals, createdIpSpace.IpSpace)
73+
74+
// Get by Name
75+
byName, err := vcd.client.GenGetIpSpaceByName(createdIpSpace.IpSpace.Name)
76+
check.Assert(err, IsNil)
77+
check.Assert(byName.IpSpace, DeepEquals, createdIpSpace.IpSpace)
78+
79+
// Get all and make sure it is found
80+
allIpSpaces, err := vcd.client.GenGetAllIpSpaceSummaries(nil)
81+
check.Assert(err, IsNil)
82+
check.Assert(len(allIpSpaces) > 0, Equals, true)
83+
var found bool
84+
for i := range allIpSpaces {
85+
if allIpSpaces[i].IpSpace.ID == byId.IpSpace.ID {
86+
found = true
87+
break
88+
}
89+
}
90+
check.Assert(found, Equals, true)
91+
92+
// If an Org is assigned - attempt to lookup by name and Org ID
93+
if byId.IpSpace.OrgRef != nil && byId.IpSpace.OrgRef.ID != "" {
94+
byNameAndOrgId, err := vcd.client.GenGetIpSpaceByNameAndOrgId(byId.IpSpace.Name, byId.IpSpace.OrgRef.ID)
95+
check.Assert(err, IsNil)
96+
check.Assert(byNameAndOrgId, NotNil)
97+
check.Assert(byNameAndOrgId.IpSpace, DeepEquals, createdIpSpace.IpSpace)
98+
99+
}
100+
101+
// Check an update
102+
103+
ipSpaceConfig.ID = createdIpSpace.IpSpace.ID
104+
ipSpaceConfig.RouteAdvertisementEnabled = true
105+
ipSpaceConfig.IPSpaceInternalScope = append(ipSpaceConfig.IPSpaceInternalScope, "32.0.0.0/24")
106+
107+
updatedIpSpace, err := createdIpSpace.Update(ipSpaceConfig)
108+
check.Assert(err, IsNil)
109+
check.Assert(updatedIpSpace, NotNil)
110+
check.Assert(len(ipSpaceConfig.IPSpaceInternalScope), Equals, len(updatedIpSpace.IpSpace.IPSpaceInternalScope))
111+
112+
if vcd.client.Client.APIVCDMaxVersionIs(">= 38.0") {
113+
fmt.Println("# Testing NAT and Firewall rule autocreation flags for VCD 10.5.0+")
114+
ipSpaceConfig.Name = check.TestName() + "-GatewayServiceConfig"
115+
ipSpaceConfig.DefaultGatewayServiceConfig = &types.IpSpaceDefaultGatewayServiceConfig{
116+
EnableDefaultFirewallRuleCreation: true,
117+
EnableDefaultNoSnatRuleCreation: true,
118+
EnableDefaultSnatRuleCreation: true,
119+
}
120+
121+
updatedIpSpace, err = updatedIpSpace.Update(ipSpaceConfig)
122+
check.Assert(err, IsNil)
123+
check.Assert(updatedIpSpace.IpSpace.DefaultGatewayServiceConfig, DeepEquals, ipSpaceConfig.DefaultGatewayServiceConfig)
124+
}
125+
126+
err = createdIpSpace.Delete()
127+
check.Assert(err, IsNil)
128+
129+
// Check that the entity is not found
130+
notFoundById, err := vcd.client.GenGetIpSpaceById(byId.IpSpace.ID)
131+
check.Assert(ContainsNotFound(err), Equals, true)
132+
check.Assert(notFoundById, IsNil)
133+
}

0 commit comments

Comments
 (0)