Skip to content

Commit b08ab12

Browse files
authored
IP Spaces CRUD (#578)
1 parent 004ed07 commit b08ab12

File tree

7 files changed

+677
-4
lines changed

7 files changed

+677
-4
lines changed

.changes/v2.21.0/578-features.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
* Added IP Space CRUD support via `IpSpace` and `types.IpSpace` and `VCDClient.CreateIpSpace`,
2+
`VCDClient.GetAllIpSpaceSummaries`, `VCDClient.GetIpSpaceById`, `VCDClient.GetIpSpaceByName`,
3+
`VCDClient.GetIpSpaceByNameAndOrgId`, `IpSpace.Update`, `IpSpace.Delete` [GH-578]

govcd/ip_space.go

+227
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* Copyright 2023 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 IpSpace struct {
26+
IpSpace *types.IpSpace
27+
vcdClient *VCDClient
28+
}
29+
30+
// CreateIpSpace creates IP Space with desired configuration
31+
func (vcdClient *VCDClient) CreateIpSpace(ipSpaceConfig *types.IpSpace) (*IpSpace, error) {
32+
client := vcdClient.Client
33+
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces
34+
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
35+
if err != nil {
36+
return nil, err
37+
}
38+
39+
urlRef, err := client.OpenApiBuildEndpoint(endpoint)
40+
if err != nil {
41+
return nil, err
42+
}
43+
44+
result := &IpSpace{
45+
IpSpace: &types.IpSpace{},
46+
vcdClient: vcdClient,
47+
}
48+
49+
err = client.OpenApiPostItem(apiVersion, urlRef, nil, ipSpaceConfig, result.IpSpace, nil)
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
return result, nil
55+
}
56+
57+
// GetAllIpSpaceSummaries retrieve summaries of all IP Spaces with an optional filter
58+
// Note. There is no API endpoint to get multiple IP Spaces with their full definitions. Only
59+
// "summaries" endpoint exists, but it does not include all fields. To retrieve complete structure
60+
// one can use `GetIpSpaceById` or `GetIpSpaceByName`
61+
func (vcdClient *VCDClient) GetAllIpSpaceSummaries(queryParameters url.Values) ([]*IpSpace, error) {
62+
client := vcdClient.Client
63+
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaceSummaries
64+
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
65+
if err != nil {
66+
return nil, err
67+
}
68+
69+
urlRef, err := client.OpenApiBuildEndpoint(endpoint)
70+
if err != nil {
71+
return nil, err
72+
}
73+
74+
typeResponses := []*types.IpSpace{{}}
75+
err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParameters, &typeResponses, nil)
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
// Wrap all typeResponses into IpSpace types with client
81+
results := make([]*IpSpace, len(typeResponses))
82+
for sliceIndex := range typeResponses {
83+
results[sliceIndex] = &IpSpace{
84+
IpSpace: typeResponses[sliceIndex],
85+
vcdClient: vcdClient,
86+
}
87+
}
88+
89+
return results, nil
90+
}
91+
92+
// GetIpSpaceById retrieves IP Space with a given ID
93+
func (vcdClient *VCDClient) GetIpSpaceById(id string) (*IpSpace, error) {
94+
if id == "" {
95+
return nil, fmt.Errorf("IP Space lookup requires ID")
96+
}
97+
98+
client := vcdClient.Client
99+
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces
100+
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
101+
if err != nil {
102+
return nil, err
103+
}
104+
105+
urlRef, err := client.OpenApiBuildEndpoint(endpoint, id)
106+
if err != nil {
107+
return nil, err
108+
}
109+
110+
response := &IpSpace{
111+
vcdClient: vcdClient,
112+
IpSpace: &types.IpSpace{},
113+
}
114+
115+
err = client.OpenApiGetItem(apiVersion, urlRef, nil, response.IpSpace, nil)
116+
if err != nil {
117+
return nil, err
118+
}
119+
120+
return response, nil
121+
}
122+
123+
// GetIpSpaceByName retrieves IP Space with a given name
124+
// Note. It will return an error if multiple IP Spaces exist with the same name
125+
func (vcdClient *VCDClient) GetIpSpaceByName(name string) (*IpSpace, error) {
126+
if name == "" {
127+
return nil, fmt.Errorf("IP Space lookup requires name")
128+
}
129+
130+
queryParameters := url.Values{}
131+
queryParameters.Add("filter", "name=="+name)
132+
133+
filteredIpSpaces, err := vcdClient.GetAllIpSpaceSummaries(queryParameters)
134+
if err != nil {
135+
return nil, fmt.Errorf("error getting IP Spaces: %s", err)
136+
}
137+
138+
singleIpSpace, err := oneOrError("name", name, filteredIpSpaces)
139+
if err != nil {
140+
return nil, err
141+
}
142+
143+
return vcdClient.GetIpSpaceById(singleIpSpace.IpSpace.ID)
144+
}
145+
146+
// GetIpSpaceByNameAndOrgId retrieves IP Space with a given name in a particular Org
147+
// Note. Only PRIVATE IP spaces belong to Orgs
148+
func (vcdClient *VCDClient) GetIpSpaceByNameAndOrgId(name, orgId string) (*IpSpace, error) {
149+
if name == "" || orgId == "" {
150+
return nil, fmt.Errorf("IP Space lookup requires name and Org ID")
151+
}
152+
153+
queryParameters := url.Values{}
154+
queryParameters.Add("filter", "name=="+name)
155+
queryParameters = queryParameterFilterAnd("orgRef.id=="+orgId, queryParameters)
156+
157+
filteredIpSpaces, err := vcdClient.GetAllIpSpaceSummaries(queryParameters)
158+
if err != nil {
159+
return nil, fmt.Errorf("error getting IP Spaces: %s", err)
160+
}
161+
162+
singleIpSpace, err := oneOrError("name", name, filteredIpSpaces)
163+
if err != nil {
164+
return nil, fmt.Errorf("error ")
165+
}
166+
167+
return vcdClient.GetIpSpaceById(singleIpSpace.IpSpace.ID)
168+
}
169+
170+
// Update updates IP Space with new config
171+
func (ipSpace *IpSpace) Update(ipSpaceConfig *types.IpSpace) (*IpSpace, error) {
172+
client := ipSpace.vcdClient.Client
173+
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces
174+
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
175+
if err != nil {
176+
return nil, err
177+
}
178+
179+
ipSpaceConfig.ID = ipSpace.IpSpace.ID
180+
urlRef, err := client.OpenApiBuildEndpoint(endpoint, ipSpaceConfig.ID)
181+
if err != nil {
182+
return nil, err
183+
}
184+
185+
returnIpSpace := &IpSpace{
186+
IpSpace: &types.IpSpace{},
187+
vcdClient: ipSpace.vcdClient,
188+
}
189+
190+
err = client.OpenApiPutItem(apiVersion, urlRef, nil, ipSpaceConfig, returnIpSpace.IpSpace, nil)
191+
if err != nil {
192+
return nil, fmt.Errorf("error updating IP Space: %s", err)
193+
}
194+
195+
return returnIpSpace, nil
196+
197+
}
198+
199+
// Delete deletes IP Space
200+
func (ipSpace *IpSpace) Delete() error {
201+
if ipSpace == nil || ipSpace.IpSpace == nil || ipSpace.IpSpace.ID == "" {
202+
return fmt.Errorf("IP Space must have ID")
203+
}
204+
205+
client := ipSpace.vcdClient.Client
206+
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces
207+
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
208+
if err != nil {
209+
return err
210+
}
211+
212+
urlRef, err := client.OpenApiBuildEndpoint(endpoint, ipSpace.IpSpace.ID)
213+
if err != nil {
214+
return err
215+
}
216+
217+
err = client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil)
218+
if err != nil {
219+
return err
220+
}
221+
222+
if err != nil {
223+
return fmt.Errorf("error deleting IP space: %s", err)
224+
}
225+
226+
return nil
227+
}

0 commit comments

Comments
 (0)