Skip to content

Commit 6176f3e

Browse files
authored
Add support for Provider VDCs read functions and upgrade OpenAPI Compute Policies version to v2.0.0 (#502)
* Add read functions for Provider VDCs and extended flavor of Provider VDCs * Upgrade some Compute Policy retrieval functions from OpenAPI 1.0.0 to 2.0.0 Signed-off-by: abarreiro <abarreiro@vmware.com>
1 parent cc66003 commit 6176f3e

13 files changed

+497
-8
lines changed

.changes/v2.17.0/502-features.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
* Added new methods `VCDClient.GetProviderVdcByHref`, `VCDClient.GetProviderVdcById`, `VCDClient.GetProviderVdcByName` and `ProviderVdc.Refresh` to retrieve Provider VDCs [GH-502]
2+
* Added new methods `VCDClient.GetProviderVdcExtendedByHref`, `VCDClient.GetProviderVdcExtendedById`, `VCDClient.GetProviderVdcExtendedByName` and `ProviderVdcExtended.Refresh` to retrieve the extended flavor of Provider VDCs [GH-502]
3+
* Added new methods `ProviderVdcExtended.ToProviderVdc`, to convert from an extended Provider VDC to a regular one [GH-502]
4+
* Added new methods `ProviderVdc.GetMetadata`, `ProviderVdc.AddMetadataEntry`, `ProviderVdc.AddMetadataEntryAsync`, `ProviderVdc.MergeMetadataAsync`, `ProviderVdc.MergeMetadata`, `ProviderVdc.DeleteMetadataEntry` and `ProviderVdc.DeleteMetadataEntryAsync` to manage Provider VDCs metadata [GH-502]

.changes/v2.17.0/502-improvements.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* Updated VDC Compute Policies retrieval methods `AdminVdc.GetAllAssignedVdcComputePolicies` and `Org.GetAllVdcComputePolicies`
2+
from OpenAPI v1.0.0 to v2.0.0, this version supports more filtering options like `isVgpuPolicy`[GH-502]

govcd/api.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,20 @@ func (client *Client) RemoveProvidedCustomHeaders(values map[string]string) {
776776

777777
// Retrieves the administrator URL of a given HREF
778778
func getAdminURL(href string) string {
779-
return strings.ReplaceAll(href, "/api/", "/api/admin/")
779+
adminApi := "/api/admin/"
780+
if strings.Contains(href, adminApi) {
781+
return href
782+
}
783+
return strings.ReplaceAll(href, "/api/", adminApi)
784+
}
785+
786+
// Retrieves the admin extension URL of a given HREF
787+
func getAdminExtensionURL(href string) string {
788+
adminExtensionApi := "/api/admin/extension/"
789+
if strings.Contains(href, adminExtensionApi) {
790+
return href
791+
}
792+
return strings.ReplaceAll(getAdminURL(href), "/api/admin/", adminExtensionApi)
780793
}
781794

782795
// TestConnection calls API to test a connection against a VCD, including SSL handshake and hostname verification.

govcd/api_vcd_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build api || openapi || functional || catalog || vapp || gateway || network || org || query || extnetwork || task || vm || vdc || system || disk || lb || lbAppRule || lbAppProfile || lbServerPool || lbServiceMonitor || lbVirtualServer || user || search || nsxv || nsxt || auth || affinity || role || alb || certificate || vdcGroup || metadata || ALL
2-
// +build api openapi functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user search nsxv nsxt auth affinity role alb certificate vdcGroup metadata ALL
1+
//go:build api || openapi || functional || catalog || vapp || gateway || network || org || query || extnetwork || task || vm || vdc || system || disk || lb || lbAppRule || lbAppProfile || lbServerPool || lbServiceMonitor || lbVirtualServer || user || search || nsxv || nsxt || auth || affinity || role || alb || certificate || vdcGroup || metadata || providervdc || ALL
2+
// +build api openapi functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user search nsxv nsxt auth affinity role alb certificate vdcGroup metadata providervdc ALL
33

44
/*
55
* Copyright 2022 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.

govcd/common_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build api || auth || functional || catalog || vapp || gateway || network || org || query || extnetwork || task || vm || vdc || system || disk || lb || lbAppRule || lbAppProfile || lbServerPool || lbServiceMonitor || lbVirtualServer || user || role || nsxv || nsxt || openapi || affinity || search || alb || certificate || vdcGroup || metadata || ALL
2-
// +build api auth functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user role nsxv nsxt openapi affinity search alb certificate vdcGroup metadata ALL
1+
//go:build api || auth || functional || catalog || vapp || gateway || network || org || query || extnetwork || task || vm || vdc || system || disk || lb || lbAppRule || lbAppProfile || lbServerPool || lbServiceMonitor || lbVirtualServer || user || role || nsxv || nsxt || openapi || affinity || search || alb || certificate || vdcGroup || metadata || providervdc || ALL
2+
// +build api auth functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user role nsxv nsxt openapi affinity search alb certificate vdcGroup metadata providervdc ALL
33

44
/*
55
* Copyright 2021 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.

govcd/metadata.go

+80
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,86 @@ func (vdc *Vdc) DeleteMetadataEntryAsync(key string) (Task, error) {
223223
return deleteMetadata(vdc.client, key, getAdminURL(vdc.Vdc.HREF))
224224
}
225225

226+
// GetMetadata returns Provider VDC metadata.
227+
// Note: Requires system administrator privileges.
228+
func (providerVdc *ProviderVdc) GetMetadata() (*types.Metadata, error) {
229+
return getMetadata(providerVdc.client, providerVdc.ProviderVdc.HREF)
230+
}
231+
232+
// AddMetadataEntry adds Provider VDC metadata typedValue and key/value pair provided as input
233+
// and waits for the task to finish.
234+
// Note: Requires system administrator privileges.
235+
func (providerVdc *ProviderVdc) AddMetadataEntry(typedValue, key, value string) error {
236+
task, err := providerVdc.AddMetadataEntryAsync(typedValue, key, value)
237+
if err != nil {
238+
return err
239+
}
240+
241+
err = task.WaitTaskCompletion()
242+
if err != nil {
243+
return err
244+
}
245+
246+
err = providerVdc.Refresh()
247+
if err != nil {
248+
return err
249+
}
250+
251+
return nil
252+
}
253+
254+
// AddMetadataEntryAsync adds Provider VDC metadata typedValue and key/value pair provided as input and returns the task.
255+
// Note: Requires system administrator privileges.
256+
func (providerVdc *ProviderVdc) AddMetadataEntryAsync(typedValue, key, value string) (Task, error) {
257+
return addMetadata(providerVdc.client, typedValue, key, value, providerVdc.ProviderVdc.HREF)
258+
}
259+
260+
// MergeMetadataAsync merges Provider VDC metadata provided as a key-value map of type `typedValue` with the already present in VCD,
261+
// then waits for the task to complete.
262+
// Note: Requires system administrator privileges.
263+
func (providerVdc *ProviderVdc) MergeMetadataAsync(typedValue string, metadata map[string]interface{}) (Task, error) {
264+
return mergeAllMetadata(providerVdc.client, typedValue, metadata, providerVdc.ProviderVdc.HREF)
265+
}
266+
267+
// MergeMetadata merges Provider VDC metadata provided as a key-value map of type `typedValue` with the already present in VCD,
268+
// then waits for the task to complete.
269+
// Note: Requires system administrator privileges.
270+
func (providerVdc *ProviderVdc) MergeMetadata(typedValue string, metadata map[string]interface{}) error {
271+
task, err := providerVdc.MergeMetadataAsync(typedValue, metadata)
272+
if err != nil {
273+
return err
274+
}
275+
return task.WaitTaskCompletion()
276+
}
277+
278+
// DeleteMetadataEntry deletes Provider VDC metadata by key provided as input and waits for
279+
// the task to finish.
280+
// Note: Requires system administrator privileges.
281+
func (providerVdc *ProviderVdc) DeleteMetadataEntry(key string) error {
282+
task, err := providerVdc.DeleteMetadataEntryAsync(key)
283+
if err != nil {
284+
return err
285+
}
286+
287+
err = task.WaitTaskCompletion()
288+
if err != nil {
289+
return err
290+
}
291+
292+
err = providerVdc.Refresh()
293+
if err != nil {
294+
return err
295+
}
296+
297+
return nil
298+
}
299+
300+
// DeleteMetadataEntryAsync deletes Provider VDC metadata depending on key provided as input and returns the task.
301+
// Note: Requires system administrator privileges.
302+
func (providerVdc *ProviderVdc) DeleteMetadataEntryAsync(key string) (Task, error) {
303+
return deleteMetadata(providerVdc.client, key, providerVdc.ProviderVdc.HREF)
304+
}
305+
226306
// GetMetadata returns VApp metadata.
227307
func (vapp *VApp) GetMetadata() (*types.Metadata, error) {
228308
return getMetadata(vapp.client, vapp.VApp.HREF)

govcd/metadata_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,17 @@ func (vcd *TestVCD) Test_MetadataOnCatalogItemCRUD(check *C) {
474474
testMetadataCRUDActions(catalogItem, check, nil)
475475
}
476476

477+
func (vcd *TestVCD) Test_MetadataOnProviderVdcCRUD(check *C) {
478+
fmt.Printf("Running: %s\n", check.TestName())
479+
providerVdc, err := vcd.client.GetProviderVdcByName(vcd.config.VCD.NsxtProviderVdc.Name)
480+
if err != nil {
481+
check.Skip(fmt.Sprintf("%s: Provider VDC %s not found. Test can't proceed", check.TestName(), vcd.config.VCD.NsxtProviderVdc.Name))
482+
return
483+
}
484+
485+
testMetadataCRUDActions(providerVdc, check, nil)
486+
}
487+
477488
func (vcd *TestVCD) Test_MetadataOnOpenApiOrgVdcNetworkCRUD(check *C) {
478489
fmt.Printf("Running: %s\n", check.TestName())
479490
net, err := vcd.vdc.GetOpenApiOrgVdcNetworkByName(vcd.config.VCD.Network.Net1)

govcd/openapi_endpoints.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ var endpointMinApiVersions = map[string]string{
7474
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor: "35.0", // VCD 10.2+
7575
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpConfigPrefixLists: "35.0", // VCD 10.2+
7676
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpConfig: "35.0", // VCD 10.2+
77+
78+
types.OpenApiPathVersion2_0_0 + types.OpenApiEndpointVdcAssignedComputePolicies: "35.0",
79+
types.OpenApiPathVersion2_0_0 + types.OpenApiEndpointVdcComputePolicies: "35.0",
7780
}
7881

7982
// elevateNsxtNatRuleApiVersion helps to elevate API version to consume newer NSX-T NAT Rule features
@@ -126,7 +129,7 @@ var endpointElevatedApiVersions = map[string][]string{
126129
func (client *Client) checkOpenApiEndpointCompatibility(endpoint string) (string, error) {
127130
minimumApiVersion, ok := endpointMinApiVersions[endpoint]
128131
if !ok {
129-
return "", fmt.Errorf("minimum API version for endopoint '%s' is not defined", endpoint)
132+
return "", fmt.Errorf("minimum API version for endpoint '%s' is not defined", endpoint)
130133
}
131134

132135
if client.APIVCDMaxVersionIs("< " + minimumApiVersion) {

govcd/provider_vdc.go

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package govcd
2+
3+
import (
4+
"fmt"
5+
"github.com/vmware/go-vcloud-director/v2/types/v56"
6+
"net/http"
7+
"net/url"
8+
)
9+
10+
// ProviderVdc is the basic Provider VDC structure, contains the minimum set of attributes.
11+
type ProviderVdc struct {
12+
ProviderVdc *types.ProviderVdc
13+
client *Client
14+
}
15+
16+
// ProviderVdcExtended is the extended Provider VDC structure, contains same attributes as ProviderVdc plus some more.
17+
type ProviderVdcExtended struct {
18+
VMWProviderVdc *types.VMWProviderVdc
19+
client *Client
20+
}
21+
22+
func newProviderVdc(cli *Client) *ProviderVdc {
23+
return &ProviderVdc{
24+
ProviderVdc: new(types.ProviderVdc),
25+
client: cli,
26+
}
27+
}
28+
29+
func newProviderVdcExtended(cli *Client) *ProviderVdcExtended {
30+
return &ProviderVdcExtended{
31+
VMWProviderVdc: new(types.VMWProviderVdc),
32+
client: cli,
33+
}
34+
}
35+
36+
// GetProviderVdcByHref finds a Provider VDC by its HREF.
37+
// On success, returns a pointer to the ProviderVdc structure and a nil error
38+
// On failure, returns a nil pointer and an error
39+
func (vcdClient *VCDClient) GetProviderVdcByHref(providerVdcHref string) (*ProviderVdc, error) {
40+
providerVdc := newProviderVdc(&vcdClient.Client)
41+
42+
_, err := vcdClient.Client.ExecuteRequest(providerVdcHref, http.MethodGet,
43+
"", "error retrieving Provider VDC: %s", nil, providerVdc.ProviderVdc)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
return providerVdc, nil
49+
}
50+
51+
// GetProviderVdcExtendedByHref finds a Provider VDC with extended attributes by its HREF.
52+
// On success, returns a pointer to the ProviderVdcExtended structure and a nil error
53+
// On failure, returns a nil pointer and an error
54+
func (vcdClient *VCDClient) GetProviderVdcExtendedByHref(providerVdcHref string) (*ProviderVdcExtended, error) {
55+
providerVdc := newProviderVdcExtended(&vcdClient.Client)
56+
57+
_, err := vcdClient.Client.ExecuteRequest(getAdminExtensionURL(providerVdcHref), http.MethodGet,
58+
"", "error retrieving extended Provider VDC: %s", nil, providerVdc.VMWProviderVdc)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
return providerVdc, nil
64+
}
65+
66+
// GetProviderVdcById finds a Provider VDC by URN.
67+
// On success, returns a pointer to the ProviderVdc structure and a nil error
68+
// On failure, returns a nil pointer and an error
69+
func (vcdClient *VCDClient) GetProviderVdcById(providerVdcId string) (*ProviderVdc, error) {
70+
providerVdcHref := vcdClient.Client.VCDHREF
71+
providerVdcHref.Path += "/admin/providervdc/" + extractUuid(providerVdcId)
72+
73+
return vcdClient.GetProviderVdcByHref(providerVdcHref.String())
74+
}
75+
76+
// GetProviderVdcExtendedById finds a Provider VDC with extended attributes by URN.
77+
// On success, returns a pointer to the ProviderVdcExtended structure and a nil error
78+
// On failure, returns a nil pointer and an error
79+
func (vcdClient *VCDClient) GetProviderVdcExtendedById(providerVdcId string) (*ProviderVdcExtended, error) {
80+
providerVdcHref := vcdClient.Client.VCDHREF
81+
providerVdcHref.Path += "/admin/extension/providervdc/" + extractUuid(providerVdcId)
82+
83+
return vcdClient.GetProviderVdcExtendedByHref(providerVdcHref.String())
84+
}
85+
86+
// GetProviderVdcByName finds a Provider VDC by name.
87+
// On success, returns a pointer to the ProviderVdc structure and a nil error
88+
// On failure, returns a nil pointer and an error
89+
func (vcdClient *VCDClient) GetProviderVdcByName(providerVdcName string) (*ProviderVdc, error) {
90+
providerVdc, err := getProviderVdcByName(vcdClient, providerVdcName, false)
91+
return providerVdc.(*ProviderVdc), err
92+
}
93+
94+
// GetProviderVdcExtendedByName finds a Provider VDC with extended attributes by name.
95+
// On success, returns a pointer to the ProviderVdcExtended structure and a nil error
96+
// On failure, returns a nil pointer and an error
97+
func (vcdClient *VCDClient) GetProviderVdcExtendedByName(providerVdcName string) (*ProviderVdcExtended, error) {
98+
providerVdcExtended, err := getProviderVdcByName(vcdClient, providerVdcName, true)
99+
return providerVdcExtended.(*ProviderVdcExtended), err
100+
}
101+
102+
// Refresh updates the contents of the Provider VDC associated to the receiver object.
103+
func (providerVdc *ProviderVdc) Refresh() error {
104+
if providerVdc.ProviderVdc.HREF == "" {
105+
return fmt.Errorf("cannot refresh, receiver Provider VDC is empty")
106+
}
107+
108+
unmarshalledVdc := &types.ProviderVdc{}
109+
110+
_, err := providerVdc.client.ExecuteRequest(providerVdc.ProviderVdc.HREF, http.MethodGet,
111+
"", "error refreshing Provider VDC: %s", nil, unmarshalledVdc)
112+
if err != nil {
113+
return err
114+
}
115+
116+
providerVdc.ProviderVdc = unmarshalledVdc
117+
118+
return nil
119+
}
120+
121+
// Refresh updates the contents of the extended Provider VDC associated to the receiver object.
122+
func (providerVdcExtended *ProviderVdcExtended) Refresh() error {
123+
if providerVdcExtended.VMWProviderVdc.HREF == "" {
124+
return fmt.Errorf("cannot refresh, receiver extended Provider VDC is empty")
125+
}
126+
127+
unmarshalledVdc := &types.VMWProviderVdc{}
128+
129+
_, err := providerVdcExtended.client.ExecuteRequest(providerVdcExtended.VMWProviderVdc.HREF, http.MethodGet,
130+
"", "error refreshing extended Provider VDC: %s", nil, unmarshalledVdc)
131+
if err != nil {
132+
return err
133+
}
134+
135+
providerVdcExtended.VMWProviderVdc = unmarshalledVdc
136+
137+
return nil
138+
}
139+
140+
// ToProviderVdc converts the receiver ProviderVdcExtended into the subset ProviderVdc
141+
func (providerVdcExtended *ProviderVdcExtended) ToProviderVdc() (*ProviderVdc, error) {
142+
providerVdcHref := providerVdcExtended.client.VCDHREF
143+
providerVdcHref.Path += "/admin/providervdc/" + extractUuid(providerVdcExtended.VMWProviderVdc.ID)
144+
145+
providerVdc := newProviderVdc(providerVdcExtended.client)
146+
147+
_, err := providerVdcExtended.client.ExecuteRequest(providerVdcHref.String(), http.MethodGet,
148+
"", "error retrieving Provider VDC: %s", nil, providerVdc.ProviderVdc)
149+
if err != nil {
150+
return nil, err
151+
}
152+
153+
return providerVdc, nil
154+
}
155+
156+
// getProviderVdcByName finds a Provider VDC with extension (extended=true) or without extension (extended=false) by name
157+
// On success, returns a pointer to the ProviderVdc (extended=false) or ProviderVdcExtended (extended=true) structure and a nil error
158+
// On failure, returns a nil pointer and an error
159+
func getProviderVdcByName(vcdClient *VCDClient, providerVdcName string, extended bool) (interface{}, error) {
160+
foundProviderVdcs, err := vcdClient.QueryWithNotEncodedParams(nil, map[string]string{
161+
"type": "providerVdc",
162+
"filter": fmt.Sprintf("name==%s", url.QueryEscape(providerVdcName)),
163+
"filterEncoded": "true",
164+
})
165+
if err != nil {
166+
return nil, err
167+
}
168+
if len(foundProviderVdcs.Results.VMWProviderVdcRecord) == 0 {
169+
return nil, ErrorEntityNotFound
170+
}
171+
if len(foundProviderVdcs.Results.VMWProviderVdcRecord) > 1 {
172+
return nil, fmt.Errorf("more than one Provider VDC found with name '%s'", providerVdcName)
173+
}
174+
if extended {
175+
return vcdClient.GetProviderVdcExtendedByHref(foundProviderVdcs.Results.VMWProviderVdcRecord[0].HREF)
176+
}
177+
return vcdClient.GetProviderVdcByHref(foundProviderVdcs.Results.VMWProviderVdcRecord[0].HREF)
178+
}

0 commit comments

Comments
 (0)