Skip to content

Commit b3b69da

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

10 files changed

+442
-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

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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+
func (g GenericIpSpace2) wrap(inner *types.IpSpace) *GenericIpSpace2 {
32+
g.IpSpace = inner
33+
return &g
34+
}
35+
36+
// CreateIpSpace creates IP Space with desired configuration
37+
func (vcdClient *VCDClient) GenCreateIpSpace(ipSpaceConfig *types.IpSpace) (*GenericIpSpace2, error) {
38+
c := crudConfig{
39+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
40+
entityName: "IP Space",
41+
}
42+
outerType := GenericIpSpace2{vcdClient: vcdClient}
43+
return createOuterEntity(&vcdClient.Client, outerType, c, ipSpaceConfig)
44+
}
45+
46+
// GetAllIpSpaceSummaries retrieve summaries of all IP Spaces with an optional filter
47+
// Note. There is no API endpoint to get multiple IP Spaces with their full definitions. Only
48+
// "summaries" endpoint exists, but it does not include all fields. To retrieve complete structure
49+
// one can use `GetIpSpaceById` or `GetIpSpaceByName`
50+
func (vcdClient *VCDClient) GenGetAllIpSpaceSummaries(queryParameters url.Values) ([]*GenericIpSpace2, error) {
51+
c := crudConfig{
52+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaceSummaries,
53+
entityName: "IP Space",
54+
queryParameters: queryParameters,
55+
}
56+
57+
outerType := GenericIpSpace2{vcdClient: vcdClient}
58+
return getAllOuterEntities[GenericIpSpace2, types.IpSpace](&vcdClient.Client, outerType, c)
59+
}
60+
61+
// GetIpSpaceById retrieves IP Space with a given ID
62+
func (vcdClient *VCDClient) GenGetIpSpaceById(id string) (*GenericIpSpace2, error) {
63+
64+
c := crudConfig{
65+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
66+
endpointParams: []string{id},
67+
entityName: "IP Space",
68+
}
69+
70+
outerType := GenericIpSpace2{vcdClient: vcdClient}
71+
return getOuterEntity[GenericIpSpace2, types.IpSpace](&vcdClient.Client, outerType, c)
72+
}
73+
74+
// GetIpSpaceByName retrieves IP Space with a given name
75+
// Note. It will return an error if multiple IP Spaces exist with the same name
76+
func (vcdClient *VCDClient) GenGetIpSpaceByName(name string) (*GenericIpSpace2, error) {
77+
if name == "" {
78+
return nil, fmt.Errorf("IP Space lookup requires name")
79+
}
80+
81+
queryParams := url.Values{}
82+
queryParams.Add("filter", "name=="+name)
83+
84+
filteredEntities, err := vcdClient.GenGetAllIpSpaceSummaries(queryParams)
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
singleIpSpace, err := oneOrError("name", name, filteredEntities)
90+
if err != nil {
91+
return nil, err
92+
}
93+
94+
return vcdClient.GenGetIpSpaceById(singleIpSpace.IpSpace.ID)
95+
}
96+
97+
// GetIpSpaceByNameAndOrgId retrieves IP Space with a given name in a particular Org
98+
// Note. Only PRIVATE IP spaces belong to Orgs
99+
func (vcdClient *VCDClient) GenGetIpSpaceByNameAndOrgId(name, orgId string) (*GenericIpSpace2, error) {
100+
if name == "" || orgId == "" {
101+
return nil, fmt.Errorf("IP Space lookup requires name and Org ID")
102+
}
103+
104+
queryParams := url.Values{}
105+
queryParams.Add("filter", "name=="+name)
106+
queryParams = queryParameterFilterAnd("orgRef.id=="+orgId, queryParams)
107+
108+
filteredEntities, err := vcdClient.GenGetAllIpSpaceSummaries(queryParams)
109+
if err != nil {
110+
return nil, err
111+
}
112+
113+
singleIpSpace, err := oneOrError("name", name, filteredEntities)
114+
if err != nil {
115+
return nil, err
116+
}
117+
118+
return vcdClient.GenGetIpSpaceById(singleIpSpace.IpSpace.ID)
119+
}
120+
121+
// Update updates IP Space with new config
122+
func (ipSpace *GenericIpSpace2) Update(ipSpaceConfig *types.IpSpace) (*GenericIpSpace2, error) {
123+
c := crudConfig{
124+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
125+
endpointParams: []string{ipSpaceConfig.ID},
126+
entityName: "IP Space",
127+
}
128+
outerType := GenericIpSpace2{vcdClient: ipSpace.vcdClient}
129+
return updateOuterEntity(&ipSpace.vcdClient.Client, outerType, c, ipSpaceConfig)
130+
}
131+
132+
// Delete deletes IP Space
133+
func (ipSpace *GenericIpSpace2) Delete() error {
134+
c := crudConfig{
135+
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces,
136+
endpointParams: []string{ipSpace.IpSpace.ID},
137+
entityName: "IP Space",
138+
}
139+
return deleteEntityById(&ipSpace.vcdClient.Client, c)
140+
}

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)