From 7197a23c66b5f3c928e5308a01e0e28060d5792e Mon Sep 17 00:00:00 2001 From: abarreiro Date: Thu, 6 Feb 2025 14:42:49 +0100 Subject: [PATCH 01/25] Add more VM class methods Signed-off-by: abarreiro --- govcd/tm_vdc.go | 29 ++++++++++++++--- govcd/tm_vm_class.go | 75 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 govcd/tm_vm_class.go diff --git a/govcd/tm_vdc.go b/govcd/tm_vdc.go index 0aa24af6c..9d06ce3ee 100644 --- a/govcd/tm_vdc.go +++ b/govcd/tm_vdc.go @@ -130,18 +130,39 @@ func (o *TmVdc) Delete() error { return deleteEntityById(&o.vcdClient.Client, c) } -// AssignVmClasses assigns VM Classes to the receiver VDC -func (o *TmVdc) AssignVmClasses(vmClasses *types.RegionVirtualMachineClasses) error { +// AssignVmClassesToRegionQuota assigns VM Classes to the receiver VDC +func (o *VCDClient) AssignVmClassesToRegionQuota(regionQuotaId string, vmClasses *types.RegionVirtualMachineClasses) error { c := crudConfig{ entityLabel: labelTmOrgVdc, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, - endpointParams: []string{o.TmVdc.ID}, + endpointParams: []string{regionQuotaId}, requiresTm: true, } // It's a PUT call with OpenAPI references, so we reuse generic functions for simplicity - _, err := updateInnerEntity[types.RegionVirtualMachineClasses](&o.vcdClient.Client, c, vmClasses) + _, err := updateInnerEntity[types.RegionVirtualMachineClasses](&o.Client, c, vmClasses) if err != nil { return err } return nil } + +// AssignVmClasses assigns VM Classes to the receiver VDC +func (o *TmVdc) AssignVmClasses(vmClasses *types.RegionVirtualMachineClasses) error { + return o.vcdClient.AssignVmClassesToRegionQuota(o.TmVdc.ID, vmClasses) +} + +// GetVmClassesFromRegionQuota returns all VM Classes of the given Region Quota +func (o *VCDClient) GetVmClassesFromRegionQuota(regionQuotaId string) (*types.RegionVirtualMachineClasses, error) { + c := crudConfig{ + entityLabel: labelTmOrgVdc, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, + endpointParams: []string{regionQuotaId}, + requiresTm: true, + } + // It's a GET call with OpenAPI references, so we reuse generic functions for simplicity + result, err := getInnerEntity[types.RegionVirtualMachineClasses](&o.Client, c) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/govcd/tm_vm_class.go b/govcd/tm_vm_class.go new file mode 100644 index 000000000..e18f07508 --- /dev/null +++ b/govcd/tm_vm_class.go @@ -0,0 +1,75 @@ +package govcd + +/* + * Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. + */ + +import ( + "fmt" + "net/url" + + "github.com/vmware/go-vcloud-director/v3/types/v56" +) + +const labelRegionVirtualMachineClass = "VM Class" + +// RegionVirtualMachineClass defines a VM Class in VCFA +type RegionVirtualMachineClass struct { + RegionVirtualMachineClass *types.RegionVirtualMachineClass + 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 RegionVirtualMachineClass) wrap(inner *types.RegionVirtualMachineClass) *RegionVirtualMachineClass { + g.RegionVirtualMachineClass = inner + return &g +} + +// GetAllRegionVirtualMachineClasses retrieves all Tenant Manager VM Classes +func (vcdClient *VCDClient) GetAllRegionVirtualMachineClasses(queryParameters url.Values) ([]*RegionVirtualMachineClass, error) { + c := crudConfig{ + entityLabel: labelRegionVirtualMachineClass, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVmClasses, + queryParameters: queryParameters, + requiresTm: true, + } + + outerType := RegionVirtualMachineClass{vcdClient: vcdClient} + return getAllOuterEntities(&vcdClient.Client, outerType, c) +} + +// GetRegionVirtualMachineClassByNameAndRegionId retrieves a VM Class by a given name and Region ID +func (vcdClient *VCDClient) GetRegionVirtualMachineClassByNameAndRegionId(name, regionId string) (*RegionVirtualMachineClass, error) { + if name == "" { + return nil, fmt.Errorf("%s lookup requires name", labelTmOrgVdc) + } + + queryParams := url.Values{} + queryParams.Add("filter", fmt.Sprintf("name==%s;region.id==%s", name, regionId)) + filteredEntities, err := vcdClient.GetAllRegionVirtualMachineClasses(queryParams) + if err != nil { + return nil, err + } + + singleResult, err := oneOrError("name + region.id", fmt.Sprintf("%s + %s", name, regionId), filteredEntities) + if err != nil { + return nil, err + } + + return singleResult, nil +} + +// GetRegionVirtualMachineClassById retrieves a VM Class by a given ID +func (vcdClient *VCDClient) GetRegionVirtualMachineClassById(id string) (*RegionVirtualMachineClass, error) { + c := crudConfig{ + entityLabel: labelRegionVirtualMachineClass, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVmClasses, + endpointParams: []string{id}, + requiresTm: true, + } + + outerType := RegionVirtualMachineClass{vcdClient: vcdClient} + return getOuterEntity(&vcdClient.Client, outerType, c) +} From 663cb3acc95cd446a9ee716c470ee7fa88317c18 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Thu, 6 Feb 2025 14:46:02 +0100 Subject: [PATCH 02/25] changelog Signed-off-by: abarreiro --- .changes/v3.0.0/720-features.md | 2 +- .changes/v3.0.0/748-features.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changes/v3.0.0/748-features.md diff --git a/.changes/v3.0.0/720-features.md b/.changes/v3.0.0/720-features.md index 56682dca6..ea4bf19b1 100644 --- a/.changes/v3.0.0/720-features.md +++ b/.changes/v3.0.0/720-features.md @@ -1,7 +1,7 @@ * Added types `TmVdc` and `types.TmVdc` for managing Tenant Manager Org VDCs with methods `VCDClient.CreateTmVdc`, `VCDClient.GetAllTmVdcs`, `VCDClient.GetTmVdcByName`, `VCDClient.GetTmVdcById`, `VCDClient.GetTmVdcByNameAndOrgId`, `TmVdc.Update`, `TmVdc.Delete` - [GH-720, GH-738] + [GH-720, GH-738, GH-748] * Added types `Zone` and `types.Zone` for reading Region Zones with methods `VCDClient.GetAllZones`, `VCDClient.GetZoneByName`, `VCDClient.GetZoneById`, `Region.GetAllZones`, `Region.GetZoneByName` [GH-720] diff --git a/.changes/v3.0.0/748-features.md b/.changes/v3.0.0/748-features.md new file mode 100644 index 000000000..b774b9a13 --- /dev/null +++ b/.changes/v3.0.0/748-features.md @@ -0,0 +1,3 @@ +* Added types `RegionVirtualMachineClass` to read Region VM Classes with methods + `VCDClient.GetAllRegionVirtualMachineClasses`, `VCDClient.GetRegionVirtualMachineClassByNameAndRegionId`, + `VCDClient.GetRegionVirtualMachineClassById` [GH-748] From d3573ef50c82a706c5a8e005bfec929fc1825411 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Thu, 6 Feb 2025 14:47:45 +0100 Subject: [PATCH 03/25] changelog Signed-off-by: abarreiro --- .changes/v3.0.0/720-features.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.changes/v3.0.0/720-features.md b/.changes/v3.0.0/720-features.md index ea4bf19b1..7e5f93d9b 100644 --- a/.changes/v3.0.0/720-features.md +++ b/.changes/v3.0.0/720-features.md @@ -1,6 +1,7 @@ * Added types `TmVdc` and `types.TmVdc` for managing Tenant Manager Org VDCs with methods `VCDClient.CreateTmVdc`, `VCDClient.GetAllTmVdcs`, `VCDClient.GetTmVdcByName`, - `VCDClient.GetTmVdcById`, `VCDClient.GetTmVdcByNameAndOrgId`, `TmVdc.Update`, `TmVdc.Delete` + `VCDClient.GetTmVdcById`, `VCDClient.GetTmVdcByNameAndOrgId`, `TmVdc.Update`, `TmVdc.Delete`, + `TmVdc.AssignVmClasses`, `VCDClient.GetVmClassesFromRegionQuota`, `VCDClient.AssignVmClassesToRegionQuota` [GH-720, GH-738, GH-748] * Added types `Zone` and `types.Zone` for reading Region Zones with methods `VCDClient.GetAllZones`, `VCDClient.GetZoneByName`, `VCDClient.GetZoneById`, `Region.GetAllZones`, `Region.GetZoneByName` From e1770ef8a65a5cafc65c89165288d39e46c3b423 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Fri, 7 Feb 2025 10:07:52 +0100 Subject: [PATCH 04/25] Fixed NSX Signed-off-by: abarreiro --- govcd/nsxt_manager_openapi_test.go | 9 ++-- govcd/tm_common_test.go | 9 ++-- .../{tm_vm_class.go => tm_region_vm_class.go} | 10 ++-- govcd/tm_region_vm_class_test.go | 47 +++++++++++++++++++ govcd/tm_vdc_test.go | 9 ++-- types/v56/openapi.go | 21 +++++++-- 6 files changed, 82 insertions(+), 23 deletions(-) rename govcd/{tm_vm_class.go => tm_region_vm_class.go} (85%) create mode 100644 govcd/tm_region_vm_class_test.go diff --git a/govcd/nsxt_manager_openapi_test.go b/govcd/nsxt_manager_openapi_test.go index 33d0b8237..19b22d3ca 100644 --- a/govcd/nsxt_manager_openapi_test.go +++ b/govcd/nsxt_manager_openapi_test.go @@ -18,10 +18,11 @@ func (vcd *TestVCD) Test_NsxtManagerOpenApi(check *C) { } cfg := &types.NsxtManagerOpenApi{ - Name: check.TestName(), - Username: vcd.config.Tm.NsxtManagerUsername, - Password: vcd.config.Tm.NsxtManagerPassword, - Url: vcd.config.Tm.NsxtManagerUrl, + Name: check.TestName(), + Username: vcd.config.Tm.NsxtManagerUsername, + Password: vcd.config.Tm.NsxtManagerPassword, + Url: vcd.config.Tm.NsxtManagerUrl, + Description: check.TestName(), // TODO: TM: Latest build throws error if not populated } // Certificate must be trusted before adding NSX-T Manager diff --git a/govcd/tm_common_test.go b/govcd/tm_common_test.go index 641e28a00..5d0768c4d 100644 --- a/govcd/tm_common_test.go +++ b/govcd/tm_common_test.go @@ -121,10 +121,11 @@ func getOrCreateNsxtManager(vcd *TestVCD, check *C) (*NsxtManagerOpenApi, func() printVerbose("# Will create NSX-T Manager %s\n", vcd.config.Tm.NsxtManagerUrl) nsxtCfg := &types.NsxtManagerOpenApi{ - Name: check.TestName(), - Username: vcd.config.Tm.NsxtManagerUsername, - Password: vcd.config.Tm.NsxtManagerPassword, - Url: vcd.config.Tm.NsxtManagerUrl, + Name: check.TestName(), + Username: vcd.config.Tm.NsxtManagerUsername, + Description: check.TestName(), // TODO: TM: Latest build throws SQL error if not populated + Password: vcd.config.Tm.NsxtManagerPassword, + Url: vcd.config.Tm.NsxtManagerUrl, } // Certificate must be trusted before adding NSX-T Manager url, err := url.Parse(nsxtCfg.Url) diff --git a/govcd/tm_vm_class.go b/govcd/tm_region_vm_class.go similarity index 85% rename from govcd/tm_vm_class.go rename to govcd/tm_region_vm_class.go index e18f07508..a8f232c64 100644 --- a/govcd/tm_vm_class.go +++ b/govcd/tm_region_vm_class.go @@ -11,9 +11,9 @@ import ( "github.com/vmware/go-vcloud-director/v3/types/v56" ) -const labelRegionVirtualMachineClass = "VM Class" +const labelRegionVirtualMachineClass = "Region VM Class" -// RegionVirtualMachineClass defines a VM Class in VCFA +// RegionVirtualMachineClass defines a Region VM Class in VCFA type RegionVirtualMachineClass struct { RegionVirtualMachineClass *types.RegionVirtualMachineClass vcdClient *VCDClient @@ -27,7 +27,7 @@ func (g RegionVirtualMachineClass) wrap(inner *types.RegionVirtualMachineClass) return &g } -// GetAllRegionVirtualMachineClasses retrieves all Tenant Manager VM Classes +// GetAllRegionVirtualMachineClasses retrieves all Region VM Classes func (vcdClient *VCDClient) GetAllRegionVirtualMachineClasses(queryParameters url.Values) ([]*RegionVirtualMachineClass, error) { c := crudConfig{ entityLabel: labelRegionVirtualMachineClass, @@ -40,7 +40,7 @@ func (vcdClient *VCDClient) GetAllRegionVirtualMachineClasses(queryParameters ur return getAllOuterEntities(&vcdClient.Client, outerType, c) } -// GetRegionVirtualMachineClassByNameAndRegionId retrieves a VM Class by a given name and Region ID +// GetRegionVirtualMachineClassByNameAndRegionId retrieves a Region VM Class by a given name and Region ID func (vcdClient *VCDClient) GetRegionVirtualMachineClassByNameAndRegionId(name, regionId string) (*RegionVirtualMachineClass, error) { if name == "" { return nil, fmt.Errorf("%s lookup requires name", labelTmOrgVdc) @@ -61,7 +61,7 @@ func (vcdClient *VCDClient) GetRegionVirtualMachineClassByNameAndRegionId(name, return singleResult, nil } -// GetRegionVirtualMachineClassById retrieves a VM Class by a given ID +// GetRegionVirtualMachineClassById retrieves a Region VM Class by a given ID func (vcdClient *VCDClient) GetRegionVirtualMachineClassById(id string) (*RegionVirtualMachineClass, error) { c := crudConfig{ entityLabel: labelRegionVirtualMachineClass, diff --git a/govcd/tm_region_vm_class_test.go b/govcd/tm_region_vm_class_test.go new file mode 100644 index 000000000..adae3ae21 --- /dev/null +++ b/govcd/tm_region_vm_class_test.go @@ -0,0 +1,47 @@ +//go:build tm || functional || ALL + +/* + * Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. + */ + +package govcd + +import ( + . "gopkg.in/check.v1" +) + +func (vcd *TestVCD) Test_RegionVmClass(check *C) { + skipNonTm(vcd, check) + sysadminOnly(vcd, check) + + nsxtManager, nsxtManagerCleanup := getOrCreateNsxtManager(vcd, check) + defer nsxtManagerCleanup() + vc, vcCleanup := getOrCreateVCenter(vcd, check) + defer vcCleanup() + + supervisor, err := vc.GetSupervisorByName(vcd.config.Tm.VcenterSupervisor) + check.Assert(err, IsNil) + region, regionCleanup := getOrCreateRegion(vcd, nsxtManager, supervisor, check) + defer regionCleanup() + + vmClasses, err := region.GetAllVmClasses(nil) + check.Assert(err, IsNil) + + vmClasses2, err := vcd.client.GetAllRegionVirtualMachineClasses(nil) + check.Assert(err, IsNil) + check.Assert(len(vmClasses2) >= len(vmClasses), Equals, true) + + // Remaining test requires at least one Region VM Class in VCFA + if len(vmClasses) == 0 { + check.Skip("there are not enough Region VM Classes to continue with test") + } + + vmClass, err := vcd.client.GetRegionVirtualMachineClassByNameAndRegionId(vmClasses[0].Name, region.Region.ID) + check.Assert(err, IsNil) + check.Assert(*vmClass.RegionVirtualMachineClass, DeepEquals, *vmClasses[0]) + + vmClass, err = vcd.client.GetRegionVirtualMachineClassById(vmClasses[0].ID) + check.Assert(err, IsNil) + check.Assert(*vmClass.RegionVirtualMachineClass, DeepEquals, *vmClasses[0]) + +} diff --git a/govcd/tm_vdc_test.go b/govcd/tm_vdc_test.go index 0b5c0082c..1745b7804 100644 --- a/govcd/tm_vdc_test.go +++ b/govcd/tm_vdc_test.go @@ -97,9 +97,8 @@ func (vcd *TestVCD) Test_TmVdc(check *C) { check.Assert(byIdInvalid, IsNil) // Update - // TODO: TM: It fails - /* createdVdc.TmVdc.Name = check.TestName() + "-update" - updatedVdc, err := createdVdc.Update(createdVdc.TmVdc) - check.Assert(err, IsNil) - check.Assert(updatedVdc.TmVdc, DeepEquals, createdVdc.TmVdc)*/ + createdVdc.TmVdc.Name = check.TestName() + "-update" + updatedVdc, err := createdVdc.Update(createdVdc.TmVdc) + check.Assert(err, IsNil) + check.Assert(updatedVdc.TmVdc, DeepEquals, createdVdc.TmVdc) } diff --git a/types/v56/openapi.go b/types/v56/openapi.go index e858dec15..6ba7d4f61 100644 --- a/types/v56/openapi.go +++ b/types/v56/openapi.go @@ -859,16 +859,27 @@ type NsxtManagerOpenApi struct { // Name of NSX-T Manager Name string `json:"name"` // Description of NSX-T Manager - Description string `json:"description"` + Description string `json:"description,omitempty"` // Username for authenticating to NSX-T Manager Username string `json:"username"` // Password for authenticating to NSX-T Manager - Password string `json:"password"` + Password string `json:"password,omitempty"` // Url for authenticating to NSX-T Manager Url string `json:"url"` - // NetworkProviderScope - NetworkProviderScope string `json:"networkProviderScope"` - // Status of NSX-T Manager + // Active indicates whether the NSX Manager can or cannot be used to manage networking constructs within Tenant Manager + Active bool `json:"active,omitempty"` + // ClusterId of the NSX Manager. Each NSX installation has a single cluster. This is not a Tenant Manager URN + ClusterId string `json:"clusterId,omitempty"` + // IsDedicatedForClassicTenants whether this NSX Manager is dedicated for legacy VRA-style tenants only and unable to + // participate in modern constructs such as Regions and Zones. Legacy VRA-style is deprecated and this field exists for + // the purpose of VRA backwards compatibility only + IsDedicatedForClassicTenants bool `json:"isDedicatedForClassicTenants,omitempty"` + // Status of NSX-T Manager. Possible values are: + // PENDING - Desired entity configuration has been received by system and is pending realization. + // CONFIGURING - The system is in process of realizing the entity. + // REALIZED - The entity is successfully realized in the system. + // REALIZATION_FAILED - There are some issues and the system is not able to realize the entity. + // UNKNOWN - Current state of entity is unknown. Status string `json:"status,omitempty"` } From e476de62e03b8228d6a20dd3cba1fef7d75dcc6c Mon Sep 17 00:00:00 2001 From: abarreiro Date: Fri, 7 Feb 2025 14:35:52 +0100 Subject: [PATCH 05/25] Rename VDC -> Region quota Signed-off-by: abarreiro --- govcd/tm_common_test.go | 8 +- govcd/tm_region_quota.go | 168 ++++++++++++++++++ ...tm_vdc_test.go => tm_region_quota_test.go} | 28 +-- govcd/tm_region_vm_class.go | 2 +- govcd/tm_vdc.go | 168 ------------------ govcd/tm_vdc_storage_policy.go | 36 +++- govcd/tm_vdc_storage_policy_test.go | 8 +- types/v56/tm.go | 14 +- 8 files changed, 231 insertions(+), 201 deletions(-) create mode 100644 govcd/tm_region_quota.go rename govcd/{tm_vdc_test.go => tm_region_quota_test.go} (67%) delete mode 100644 govcd/tm_vdc.go diff --git a/govcd/tm_common_test.go b/govcd/tm_common_test.go index 5d0768c4d..0650d6fe3 100644 --- a/govcd/tm_common_test.go +++ b/govcd/tm_common_test.go @@ -267,7 +267,7 @@ func createOrg(vcd *TestVCD, check *C, canManageOrgs bool) (*TmOrg, func()) { // Creates a VDC (Region Quota) for testing in Tenant Manager and configures it with // the first found VM class and the configured Storage Class. -func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*TmVdc, func()) { +func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*OrgRegionQuota, func()) { if vcd.config.Tm.StorageClass == "" { check.Fatal("testing configuration property 'tm.storageClass' is required") } @@ -310,11 +310,11 @@ func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*TmVdc, func }, }}, } - vdc, err := vcd.client.CreateTmVdc(cfg) + vdc, err := vcd.client.CreateOrgRegionQuota(cfg) check.Assert(err, IsNil) check.Assert(vdc, NotNil) - PrependToCleanupListOpenApi(vdc.TmVdc.ID, cfg.Name, types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+vdc.TmVdc.ID) + PrependToCleanupListOpenApi(vdc.OrgRegionQuota.ID, cfg.Name, types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+vdc.OrgRegionQuota.ID) err = vdc.AssignVmClasses(&types.RegionVirtualMachineClasses{ Values: types.OpenApiReferences{{Name: vmClasses[0].Name, ID: vmClasses[0].ID}}, @@ -328,7 +328,7 @@ func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*TmVdc, func }, StorageLimitMiB: 100, VirtualDatacenter: types.OpenApiReference{ - ID: vdc.TmVdc.ID, + ID: vdc.OrgRegionQuota.ID, }, }, }, diff --git a/govcd/tm_region_quota.go b/govcd/tm_region_quota.go new file mode 100644 index 000000000..ee64a863d --- /dev/null +++ b/govcd/tm_region_quota.go @@ -0,0 +1,168 @@ +package govcd + +/* + * Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. + */ + +import ( + "fmt" + "net/url" + + "github.com/vmware/go-vcloud-director/v3/types/v56" +) + +const labelTmOrgRegionQuota = "Org Region Quota" + +// OrgRegionQuota defines Tenant Manager Organization Virtual Data Center structure +type OrgRegionQuota struct { + OrgRegionQuota *types.TmVdc + 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 OrgRegionQuota) wrap(inner *types.TmVdc) *OrgRegionQuota { + g.OrgRegionQuota = inner + return &g +} + +// CreateOrgRegionQuota sets up a new Org Region Quota +func (vcdClient *VCDClient) CreateOrgRegionQuota(config *types.TmVdc) (*OrgRegionQuota, error) { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, + requiresTm: true, + } + outerType := OrgRegionQuota{vcdClient: vcdClient} + return createOuterEntity(&vcdClient.Client, outerType, c, config) +} + +// GetAllOrgRegionQuotas retrieves all Org Region Quotas +func (vcdClient *VCDClient) GetAllOrgRegionQuotas(queryParameters url.Values) ([]*OrgRegionQuota, error) { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, + queryParameters: queryParameters, + requiresTm: true, + } + + outerType := OrgRegionQuota{vcdClient: vcdClient} + return getAllOuterEntities(&vcdClient.Client, outerType, c) +} + +// GetOrgRegionQuotaByName retrieves an Org Region Quota by a given name +func (vcdClient *VCDClient) GetOrgRegionQuotaByName(name string) (*OrgRegionQuota, error) { + if name == "" { + return nil, fmt.Errorf("%s lookup requires name", labelTmOrgRegionQuota) + } + + queryParams := url.Values{} + queryParams.Add("filter", fmt.Sprintf("name==%s", name)) + filteredEntities, err := vcdClient.GetAllOrgRegionQuotas(queryParams) + if err != nil { + return nil, err + } + + singleResult, err := oneOrError("name", name, filteredEntities) + if err != nil { + return nil, err + } + + return singleResult, nil +} + +// GetOrgRegionQuotaByNameAndOrgId retrieves an Org Region Quota by Name and Org ID +func (vcdClient *VCDClient) GetOrgRegionQuotaByNameAndOrgId(name, orgId string) (*OrgRegionQuota, error) { + if name == "" { + return nil, fmt.Errorf("%s lookup requires name and Org ID to be present", labelTmOrgRegionQuota) + } + + queryParams := url.Values{} + queryParams.Add("filter", fmt.Sprintf("org.id==%s;name==%s", orgId, name)) + + filteredEntities, err := vcdClient.GetAllOrgRegionQuotas(queryParams) + if err != nil { + return nil, err + } + + singleResult, err := oneOrError("name", name, filteredEntities) + if err != nil { + return nil, err + } + + return singleResult, nil +} + +// GetOrgRegionQuotaById retrieves an Org Region Quota by a given ID +func (vcdClient *VCDClient) GetOrgRegionQuotaById(id string) (*OrgRegionQuota, error) { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, + endpointParams: []string{id}, + requiresTm: true, + } + + outerType := OrgRegionQuota{vcdClient: vcdClient} + return getOuterEntity(&vcdClient.Client, outerType, c) +} + +// Update updates the receiver Org Region Quota +func (o *OrgRegionQuota) Update(tmVdcConfig *types.TmVdc) (*OrgRegionQuota, error) { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, + endpointParams: []string{o.OrgRegionQuota.ID}, + requiresTm: true, + } + outerType := OrgRegionQuota{vcdClient: o.vcdClient} + return updateOuterEntity(&o.vcdClient.Client, outerType, c, tmVdcConfig) +} + +// Delete deletes the receiver Org Region Quota +func (o *OrgRegionQuota) Delete() error { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, + endpointParams: []string{o.OrgRegionQuota.ID}, + requiresTm: true, + } + return deleteEntityById(&o.vcdClient.Client, c) +} + +// AssignVmClassesToOrgRegionQuota assigns VM Classes to the receiver Org Region Quota +func (o *VCDClient) AssignVmClassesToOrgRegionQuota(regionQuotaId string, vmClasses *types.RegionVirtualMachineClasses) error { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, + endpointParams: []string{regionQuotaId}, + requiresTm: true, + } + // It's a PUT call with OpenAPI references, so we reuse generic functions for simplicity + _, err := updateInnerEntity[types.RegionVirtualMachineClasses](&o.Client, c, vmClasses) + if err != nil { + return err + } + return nil +} + +// AssignVmClasses assigns VM Classes to the receiver Org Region Quota +func (o *OrgRegionQuota) AssignVmClasses(vmClasses *types.RegionVirtualMachineClasses) error { + return o.vcdClient.AssignVmClassesToOrgRegionQuota(o.OrgRegionQuota.ID, vmClasses) +} + +// GetVmClassesFromOrgRegionQuota returns all VM Classes of the given Org Region Quota +func (o *VCDClient) GetVmClassesFromOrgRegionQuota(regionQuotaId string) (*types.RegionVirtualMachineClasses, error) { + c := crudConfig{ + entityLabel: labelTmOrgRegionQuota, + endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, + endpointParams: []string{regionQuotaId}, + requiresTm: true, + } + // It's a GET call with OpenAPI references, so we reuse generic functions for simplicity + result, err := getInnerEntity[types.RegionVirtualMachineClasses](&o.Client, c) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/govcd/tm_vdc_test.go b/govcd/tm_region_quota_test.go similarity index 67% rename from govcd/tm_vdc_test.go rename to govcd/tm_region_quota_test.go index 1745b7804..8c1166ecb 100644 --- a/govcd/tm_vdc_test.go +++ b/govcd/tm_region_quota_test.go @@ -52,11 +52,11 @@ func (vcd *TestVCD) Test_TmVdc(check *C) { }}, } - createdVdc, err := vcd.client.CreateTmVdc(vdcType) + createdVdc, err := vcd.client.CreateOrgRegionQuota(vdcType) check.Assert(err, IsNil) check.Assert(createdVdc, NotNil) // Add to cleanup list - PrependToCleanupListOpenApi(createdVdc.TmVdc.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.TmVdc.ID) + PrependToCleanupListOpenApi(createdVdc.OrgRegionQuota.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.OrgRegionQuota.ID) defer func() { err = createdVdc.Delete() check.Assert(err, IsNil) @@ -68,37 +68,37 @@ func (vcd *TestVCD) Test_TmVdc(check *C) { }) // Get TM VDC By Name - byName, err := vcd.client.GetTmVdcByName(vdcType.Name) + byName, err := vcd.client.GetOrgRegionQuotaByName(vdcType.Name) check.Assert(err, IsNil) - check.Assert(byName.TmVdc, DeepEquals, createdVdc.TmVdc) + check.Assert(byName.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) // Get TM VDC By Id - byId, err := vcd.client.GetTmVdcById(createdVdc.TmVdc.ID) + byId, err := vcd.client.GetOrgRegionQuotaById(createdVdc.OrgRegionQuota.ID) check.Assert(err, IsNil) - check.Assert(byId.TmVdc, DeepEquals, createdVdc.TmVdc) + check.Assert(byId.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) // Get By Name and Org ID - byNameAndOrgId, err := vcd.client.GetTmVdcByNameAndOrgId(createdVdc.TmVdc.Name, org.TmOrg.ID) + byNameAndOrgId, err := vcd.client.GetOrgRegionQuotaByNameAndOrgId(createdVdc.OrgRegionQuota.Name, org.TmOrg.ID) check.Assert(err, IsNil) - check.Assert(byNameAndOrgId.TmVdc, DeepEquals, createdVdc.TmVdc) + check.Assert(byNameAndOrgId.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) // Get By Name and Org ID in non existent Org - byNameAndInvalidOrgId, err := vcd.client.GetTmVdcByNameAndOrgId(createdVdc.TmVdc.Name, "urn:vcloud:org:a93c9db9-0000-0000-0000-a8f7eeda85f9") + byNameAndInvalidOrgId, err := vcd.client.GetOrgRegionQuotaByNameAndOrgId(createdVdc.OrgRegionQuota.Name, "urn:vcloud:org:a93c9db9-0000-0000-0000-a8f7eeda85f9") check.Assert(err, NotNil) check.Assert(byNameAndInvalidOrgId, IsNil) // Not Found tests - byNameInvalid, err := vcd.client.GetTmVdcByName("fake-name") + byNameInvalid, err := vcd.client.GetOrgRegionQuotaByName("fake-name") check.Assert(ContainsNotFound(err), Equals, true) check.Assert(byNameInvalid, IsNil) - byIdInvalid, err := vcd.client.GetTmVdcById("urn:vcloud:virtualDatacenter:5344b964-0000-0000-0000-d554913db643") + byIdInvalid, err := vcd.client.GetOrgRegionQuotaById("urn:vcloud:virtualDatacenter:5344b964-0000-0000-0000-d554913db643") check.Assert(ContainsNotFound(err), Equals, true) check.Assert(byIdInvalid, IsNil) // Update - createdVdc.TmVdc.Name = check.TestName() + "-update" - updatedVdc, err := createdVdc.Update(createdVdc.TmVdc) + createdVdc.OrgRegionQuota.Name = check.TestName() + "-update" + updatedVdc, err := createdVdc.Update(createdVdc.OrgRegionQuota) check.Assert(err, IsNil) - check.Assert(updatedVdc.TmVdc, DeepEquals, createdVdc.TmVdc) + check.Assert(updatedVdc.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) } diff --git a/govcd/tm_region_vm_class.go b/govcd/tm_region_vm_class.go index a8f232c64..98e64c73f 100644 --- a/govcd/tm_region_vm_class.go +++ b/govcd/tm_region_vm_class.go @@ -43,7 +43,7 @@ func (vcdClient *VCDClient) GetAllRegionVirtualMachineClasses(queryParameters ur // GetRegionVirtualMachineClassByNameAndRegionId retrieves a Region VM Class by a given name and Region ID func (vcdClient *VCDClient) GetRegionVirtualMachineClassByNameAndRegionId(name, regionId string) (*RegionVirtualMachineClass, error) { if name == "" { - return nil, fmt.Errorf("%s lookup requires name", labelTmOrgVdc) + return nil, fmt.Errorf("%s lookup requires name", labelTmOrgRegionQuota) } queryParams := url.Values{} diff --git a/govcd/tm_vdc.go b/govcd/tm_vdc.go deleted file mode 100644 index 9d06ce3ee..000000000 --- a/govcd/tm_vdc.go +++ /dev/null @@ -1,168 +0,0 @@ -package govcd - -/* - * Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. - */ - -import ( - "fmt" - "net/url" - - "github.com/vmware/go-vcloud-director/v3/types/v56" -) - -const labelTmOrgVdc = "TM Org Vdc" - -// TmVdc defines Tenant Manager Organization Virtual Data Center structure -type TmVdc struct { - TmVdc *types.TmVdc - 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 TmVdc) wrap(inner *types.TmVdc) *TmVdc { - g.TmVdc = inner - return &g -} - -// CreateTmVdc sets up a new Tenant Manager VDC -func (vcdClient *VCDClient) CreateTmVdc(config *types.TmVdc) (*TmVdc, error) { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - requiresTm: true, - } - outerType := TmVdc{vcdClient: vcdClient} - return createOuterEntity(&vcdClient.Client, outerType, c, config) -} - -// GetAllTmVdcs retrieves all Tenant Manager VDCs -func (vcdClient *VCDClient) GetAllTmVdcs(queryParameters url.Values) ([]*TmVdc, error) { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - queryParameters: queryParameters, - requiresTm: true, - } - - outerType := TmVdc{vcdClient: vcdClient} - return getAllOuterEntities(&vcdClient.Client, outerType, c) -} - -// GetTmVdcByName retrieves Tenant Manager by a given name -func (vcdClient *VCDClient) GetTmVdcByName(name string) (*TmVdc, error) { - if name == "" { - return nil, fmt.Errorf("%s lookup requires name", labelTmOrgVdc) - } - - queryParams := url.Values{} - queryParams.Add("filter", fmt.Sprintf("name==%s", name)) - filteredEntities, err := vcdClient.GetAllTmVdcs(queryParams) - if err != nil { - return nil, err - } - - singleResult, err := oneOrError("name", name, filteredEntities) - if err != nil { - return nil, err - } - - return singleResult, nil -} - -// GetTmVdcByNameAndOrgId retrieves VDC by Name and Org ID -func (vcdClient *VCDClient) GetTmVdcByNameAndOrgId(name, orgId string) (*TmVdc, error) { - if name == "" { - return nil, fmt.Errorf("%s lookup requires name and Org ID to be present", labelTmOrgVdc) - } - - queryParams := url.Values{} - queryParams.Add("filter", fmt.Sprintf("org.id==%s;name==%s", orgId, name)) - - filteredEntities, err := vcdClient.GetAllTmVdcs(queryParams) - if err != nil { - return nil, err - } - - singleResult, err := oneOrError("name", name, filteredEntities) - if err != nil { - return nil, err - } - - return singleResult, nil -} - -// GetTmVdcById retrieves a Tenant Manager VDC by a given ID -func (vcdClient *VCDClient) GetTmVdcById(id string) (*TmVdc, error) { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - endpointParams: []string{id}, - requiresTm: true, - } - - outerType := TmVdc{vcdClient: vcdClient} - return getOuterEntity(&vcdClient.Client, outerType, c) -} - -// Update Tenant Manager VDC -func (o *TmVdc) Update(tmVdcConfig *types.TmVdc) (*TmVdc, error) { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - endpointParams: []string{o.TmVdc.ID}, - requiresTm: true, - } - outerType := TmVdc{vcdClient: o.vcdClient} - return updateOuterEntity(&o.vcdClient.Client, outerType, c, tmVdcConfig) -} - -// Delete Tenant Manager VDC -func (o *TmVdc) Delete() error { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - endpointParams: []string{o.TmVdc.ID}, - requiresTm: true, - } - return deleteEntityById(&o.vcdClient.Client, c) -} - -// AssignVmClassesToRegionQuota assigns VM Classes to the receiver VDC -func (o *VCDClient) AssignVmClassesToRegionQuota(regionQuotaId string, vmClasses *types.RegionVirtualMachineClasses) error { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, - endpointParams: []string{regionQuotaId}, - requiresTm: true, - } - // It's a PUT call with OpenAPI references, so we reuse generic functions for simplicity - _, err := updateInnerEntity[types.RegionVirtualMachineClasses](&o.Client, c, vmClasses) - if err != nil { - return err - } - return nil -} - -// AssignVmClasses assigns VM Classes to the receiver VDC -func (o *TmVdc) AssignVmClasses(vmClasses *types.RegionVirtualMachineClasses) error { - return o.vcdClient.AssignVmClassesToRegionQuota(o.TmVdc.ID, vmClasses) -} - -// GetVmClassesFromRegionQuota returns all VM Classes of the given Region Quota -func (o *VCDClient) GetVmClassesFromRegionQuota(regionQuotaId string) (*types.RegionVirtualMachineClasses, error) { - c := crudConfig{ - entityLabel: labelTmOrgVdc, - endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, - endpointParams: []string{regionQuotaId}, - requiresTm: true, - } - // It's a GET call with OpenAPI references, so we reuse generic functions for simplicity - result, err := getInnerEntity[types.RegionVirtualMachineClasses](&o.Client, c) - if err != nil { - return nil, err - } - return result, nil -} diff --git a/govcd/tm_vdc_storage_policy.go b/govcd/tm_vdc_storage_policy.go index 1de4e02a0..a9cd7419a 100644 --- a/govcd/tm_vdc_storage_policy.go +++ b/govcd/tm_vdc_storage_policy.go @@ -30,7 +30,7 @@ func (g TmVdcStoragePolicy) wrap(inner *types.VirtualDatacenterStoragePolicy) *T // CreateStoragePolicies creates new VDC Storage Policies in a VDC. // The request will fail if the list of VDC Storage Policies is empty. // It returns the list of all VCD Storage Policies that are available in the VDC after creation. -func (o *TmVdc) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*TmVdcStoragePolicy, error) { +func (o *OrgRegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*TmVdcStoragePolicy, error) { c := crudConfig{ entityLabel: labelTmOrgVdcStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, @@ -68,12 +68,34 @@ func (vcdClient *VCDClient) GetAllTmVdcStoragePolicies(queryParameters url.Value } // GetAllStoragePolicies retrieves all VDC Storage Policies from the given VDC -func (vdc *TmVdc) GetAllStoragePolicies(queryParameters url.Values) ([]*TmVdcStoragePolicy, error) { - params := queryParameterFilterAnd("virtualDatacenter.id=="+vdc.TmVdc.ID, queryParameters) +func (vdc *OrgRegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*TmVdcStoragePolicy, error) { + params := queryParameterFilterAnd("virtualDatacenter.id=="+vdc.OrgRegionQuota.ID, queryParameters) return vdc.vcdClient.GetAllTmVdcStoragePolicies(params) } -// GetTmVdcStoragePolicyById retrieves a Tenant Manager VDC Storage Policy by a given ID +// GetTmVdcStoragePolicyByName retrieves a VDC Storage Policy by the given name +func (vdc *OrgRegionQuota) GetTmVdcStoragePolicyByName(name string) (*TmVdcStoragePolicy, error) { + if name == "" { + return nil, fmt.Errorf("%s lookup requires name to be present", labelTmOrgVdcStoragePolicies) + } + + queryParams := url.Values{} + queryParams.Add("filter", fmt.Sprintf("virtualDatacenter.id==%s;name==%s", vdc.OrgRegionQuota.ID, name)) + + filteredEntities, err := vdc.vcdClient.GetAllTmVdcStoragePolicies(queryParams) + if err != nil { + return nil, err + } + + singleResult, err := oneOrError("name", name, filteredEntities) + if err != nil { + return nil, err + } + + return singleResult, nil +} + +// GetTmVdcStoragePolicyById retrieves a VDC Storage Policy by a given ID func (vcdClient *VCDClient) GetTmVdcStoragePolicyById(id string) (*TmVdcStoragePolicy, error) { c := crudConfig{ entityLabel: labelTmOrgVdcStoragePolicies, @@ -88,13 +110,13 @@ func (vcdClient *VCDClient) GetTmVdcStoragePolicyById(id string) (*TmVdcStorageP // GetStoragePolicyById retrieves a Tenant Manager VDC Storage Policy by a given ID that must belong // to the receiver VDC -func (vdc *TmVdc) GetStoragePolicyById(id string) (*TmVdcStoragePolicy, error) { +func (vdc *OrgRegionQuota) GetStoragePolicyById(id string) (*TmVdcStoragePolicy, error) { policy, err := vdc.vcdClient.GetTmVdcStoragePolicyById(id) if err != nil { return nil, err } - if policy.VirtualDatacenterStoragePolicy.VirtualDatacenter.ID != vdc.TmVdc.ID { - return nil, fmt.Errorf("no VDC Storage Policy with ID '%s' found in VDC '%s': %s", id, vdc.TmVdc.ID, ErrorEntityNotFound) + if policy.VirtualDatacenterStoragePolicy.VirtualDatacenter.ID != vdc.OrgRegionQuota.ID { + return nil, fmt.Errorf("no VDC Storage Policy with ID '%s' found in VDC '%s': %s", id, vdc.OrgRegionQuota.ID, ErrorEntityNotFound) } return policy, err } diff --git a/govcd/tm_vdc_storage_policy_test.go b/govcd/tm_vdc_storage_policy_test.go index 7bcbc315b..5731c30d2 100644 --- a/govcd/tm_vdc_storage_policy_test.go +++ b/govcd/tm_vdc_storage_policy_test.go @@ -58,11 +58,11 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { }}, } - createdVdc, err := vcd.client.CreateTmVdc(vdcType) + createdVdc, err := vcd.client.CreateOrgRegionQuota(vdcType) check.Assert(err, IsNil) check.Assert(createdVdc, NotNil) // Add to cleanup list - PrependToCleanupListOpenApi(createdVdc.TmVdc.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.TmVdc.ID) + PrependToCleanupListOpenApi(createdVdc.OrgRegionQuota.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.OrgRegionQuota.ID) defer func() { err = createdVdc.Delete() check.Assert(err, IsNil) @@ -77,7 +77,7 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { }, StorageLimitMiB: 100, VirtualDatacenter: types.OpenApiReference{ - ID: createdVdc.TmVdc.ID, + ID: createdVdc.OrgRegionQuota.ID, }, }, }, @@ -106,7 +106,7 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { // Getting policies with general client params := url.Values{} - params.Add("filter", "virtualDatacenter.id=="+createdVdc.TmVdc.ID) + params.Add("filter", "virtualDatacenter.id=="+createdVdc.OrgRegionQuota.ID) filteredPolicies, err := vcd.client.GetAllTmVdcStoragePolicies(params) check.Assert(err, IsNil) check.Assert(len(filteredPolicies), Equals, len(vdcPolicies)) diff --git a/types/v56/tm.go b/types/v56/tm.go index cc24acd9c..b5651989e 100644 --- a/types/v56/tm.go +++ b/types/v56/tm.go @@ -40,10 +40,18 @@ type VirtualDatacenterStoragePolicies struct { // VirtualDatacenterStoragePolicy describes a Virtual Datacenter Storage Policy type VirtualDatacenterStoragePolicy struct { - ID string `json:"id,omitempty"` + // The identifier of the VDC Storage Policy in URN format + ID string `json:"id,omitempty"` + // The parent Region Storage Policy for this VDC Storage Policy RegionStoragePolicy OpenApiReference `json:"regionStoragePolicy"` - StorageLimitMiB int64 `json:"storageLimitMiB"` - VirtualDatacenter OpenApiReference `json:"virtualDatacenter"` + // The name of the VDC Storage Policy. It must follow RFC 1123 Label Names to conform with Kubernetes standards + Name string `json:"name,omitempty"` + // Maximum allowed storage allocation in mebibytes. Minimum Value: 0 + StorageLimitMiB int64 `json:"storageLimitMiB"` + // Amount of storage used in mebibytes. Minimum Value: 0 + StorageUsedMiB int64 `json:"storageUsedMiB,omitempty"` + // A reference to the VDC that the policy applies to + VirtualDatacenter OpenApiReference `json:"virtualDatacenter"` } // ContentLibrary is an object representing a VCF Content Library From 23f9caa2524c89d77f71145c31d55fce045b5855 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Fri, 7 Feb 2025 14:45:19 +0100 Subject: [PATCH 06/25] Rename VDC -> Region quota Signed-off-by: abarreiro --- govcd/tm_common_test.go | 8 +-- govcd/tm_region_quota.go | 90 ++++++++++++++--------------- govcd/tm_region_quota_test.go | 28 ++++----- govcd/tm_region_vm_class.go | 2 +- govcd/tm_vdc_storage_policy.go | 90 ++++++++++++++--------------- govcd/tm_vdc_storage_policy_test.go | 14 ++--- 6 files changed, 116 insertions(+), 116 deletions(-) diff --git a/govcd/tm_common_test.go b/govcd/tm_common_test.go index 0650d6fe3..ef714b34f 100644 --- a/govcd/tm_common_test.go +++ b/govcd/tm_common_test.go @@ -267,7 +267,7 @@ func createOrg(vcd *TestVCD, check *C, canManageOrgs bool) (*TmOrg, func()) { // Creates a VDC (Region Quota) for testing in Tenant Manager and configures it with // the first found VM class and the configured Storage Class. -func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*OrgRegionQuota, func()) { +func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*RegionQuota, func()) { if vcd.config.Tm.StorageClass == "" { check.Fatal("testing configuration property 'tm.storageClass' is required") } @@ -310,11 +310,11 @@ func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*OrgRegionQu }, }}, } - vdc, err := vcd.client.CreateOrgRegionQuota(cfg) + vdc, err := vcd.client.CreateRegionQuota(cfg) check.Assert(err, IsNil) check.Assert(vdc, NotNil) - PrependToCleanupListOpenApi(vdc.OrgRegionQuota.ID, cfg.Name, types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+vdc.OrgRegionQuota.ID) + PrependToCleanupListOpenApi(vdc.TmVdc.ID, cfg.Name, types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+vdc.TmVdc.ID) err = vdc.AssignVmClasses(&types.RegionVirtualMachineClasses{ Values: types.OpenApiReferences{{Name: vmClasses[0].Name, ID: vmClasses[0].ID}}, @@ -328,7 +328,7 @@ func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*OrgRegionQu }, StorageLimitMiB: 100, VirtualDatacenter: types.OpenApiReference{ - ID: vdc.OrgRegionQuota.ID, + ID: vdc.TmVdc.ID, }, }, }, diff --git a/govcd/tm_region_quota.go b/govcd/tm_region_quota.go index ee64a863d..354eb1cbf 100644 --- a/govcd/tm_region_quota.go +++ b/govcd/tm_region_quota.go @@ -11,55 +11,55 @@ import ( "github.com/vmware/go-vcloud-director/v3/types/v56" ) -const labelTmOrgRegionQuota = "Org Region Quota" +const labelRegionQuota = "Org Region Quota" -// OrgRegionQuota defines Tenant Manager Organization Virtual Data Center structure -type OrgRegionQuota struct { - OrgRegionQuota *types.TmVdc - vcdClient *VCDClient +// RegionQuota defines Region Quota structure in Tenant Manager +type RegionQuota struct { + TmVdc *types.TmVdc + 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 OrgRegionQuota) wrap(inner *types.TmVdc) *OrgRegionQuota { - g.OrgRegionQuota = inner +func (g RegionQuota) wrap(inner *types.TmVdc) *RegionQuota { + g.TmVdc = inner return &g } -// CreateOrgRegionQuota sets up a new Org Region Quota -func (vcdClient *VCDClient) CreateOrgRegionQuota(config *types.TmVdc) (*OrgRegionQuota, error) { +// CreateRegionQuota sets up a new Region Quota +func (vcdClient *VCDClient) CreateRegionQuota(config *types.TmVdc) (*RegionQuota, error) { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, requiresTm: true, } - outerType := OrgRegionQuota{vcdClient: vcdClient} + outerType := RegionQuota{vcdClient: vcdClient} return createOuterEntity(&vcdClient.Client, outerType, c, config) } -// GetAllOrgRegionQuotas retrieves all Org Region Quotas -func (vcdClient *VCDClient) GetAllOrgRegionQuotas(queryParameters url.Values) ([]*OrgRegionQuota, error) { +// GetAllRegionQuotas retrieves all Region Quotas +func (vcdClient *VCDClient) GetAllRegionQuotas(queryParameters url.Values) ([]*RegionQuota, error) { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, queryParameters: queryParameters, requiresTm: true, } - outerType := OrgRegionQuota{vcdClient: vcdClient} + outerType := RegionQuota{vcdClient: vcdClient} return getAllOuterEntities(&vcdClient.Client, outerType, c) } -// GetOrgRegionQuotaByName retrieves an Org Region Quota by a given name -func (vcdClient *VCDClient) GetOrgRegionQuotaByName(name string) (*OrgRegionQuota, error) { +// GetRegionQuotaByName retrieves a Region Quota by a given name +func (vcdClient *VCDClient) GetRegionQuotaByName(name string) (*RegionQuota, error) { if name == "" { - return nil, fmt.Errorf("%s lookup requires name", labelTmOrgRegionQuota) + return nil, fmt.Errorf("%s lookup requires name", labelRegionQuota) } queryParams := url.Values{} queryParams.Add("filter", fmt.Sprintf("name==%s", name)) - filteredEntities, err := vcdClient.GetAllOrgRegionQuotas(queryParams) + filteredEntities, err := vcdClient.GetAllRegionQuotas(queryParams) if err != nil { return nil, err } @@ -72,16 +72,16 @@ func (vcdClient *VCDClient) GetOrgRegionQuotaByName(name string) (*OrgRegionQuot return singleResult, nil } -// GetOrgRegionQuotaByNameAndOrgId retrieves an Org Region Quota by Name and Org ID -func (vcdClient *VCDClient) GetOrgRegionQuotaByNameAndOrgId(name, orgId string) (*OrgRegionQuota, error) { +// GetRegionQuotaByNameAndOrgId retrieves a Region Quota by Name and Org ID +func (vcdClient *VCDClient) GetRegionQuotaByNameAndOrgId(name, orgId string) (*RegionQuota, error) { if name == "" { - return nil, fmt.Errorf("%s lookup requires name and Org ID to be present", labelTmOrgRegionQuota) + return nil, fmt.Errorf("%s lookup requires name and Org ID to be present", labelRegionQuota) } queryParams := url.Values{} queryParams.Add("filter", fmt.Sprintf("org.id==%s;name==%s", orgId, name)) - filteredEntities, err := vcdClient.GetAllOrgRegionQuotas(queryParams) + filteredEntities, err := vcdClient.GetAllRegionQuotas(queryParams) if err != nil { return nil, err } @@ -94,46 +94,46 @@ func (vcdClient *VCDClient) GetOrgRegionQuotaByNameAndOrgId(name, orgId string) return singleResult, nil } -// GetOrgRegionQuotaById retrieves an Org Region Quota by a given ID -func (vcdClient *VCDClient) GetOrgRegionQuotaById(id string) (*OrgRegionQuota, error) { +// GetRegionQuotaById retrieves a Region Quota by a given ID +func (vcdClient *VCDClient) GetRegionQuotaById(id string) (*RegionQuota, error) { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, endpointParams: []string{id}, requiresTm: true, } - outerType := OrgRegionQuota{vcdClient: vcdClient} + outerType := RegionQuota{vcdClient: vcdClient} return getOuterEntity(&vcdClient.Client, outerType, c) } -// Update updates the receiver Org Region Quota -func (o *OrgRegionQuota) Update(tmVdcConfig *types.TmVdc) (*OrgRegionQuota, error) { +// Update updates the receiver Region Quota +func (o *RegionQuota) Update(tmVdcConfig *types.TmVdc) (*RegionQuota, error) { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - endpointParams: []string{o.OrgRegionQuota.ID}, + endpointParams: []string{o.TmVdc.ID}, requiresTm: true, } - outerType := OrgRegionQuota{vcdClient: o.vcdClient} + outerType := RegionQuota{vcdClient: o.vcdClient} return updateOuterEntity(&o.vcdClient.Client, outerType, c, tmVdcConfig) } -// Delete deletes the receiver Org Region Quota -func (o *OrgRegionQuota) Delete() error { +// Delete deletes the receiver Region Quota +func (o *RegionQuota) Delete() error { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcs, - endpointParams: []string{o.OrgRegionQuota.ID}, + endpointParams: []string{o.TmVdc.ID}, requiresTm: true, } return deleteEntityById(&o.vcdClient.Client, c) } -// AssignVmClassesToOrgRegionQuota assigns VM Classes to the receiver Org Region Quota -func (o *VCDClient) AssignVmClassesToOrgRegionQuota(regionQuotaId string, vmClasses *types.RegionVirtualMachineClasses) error { +// AssignVmClassesToRegionQuota assigns VM Classes to the receiver Region Quota +func (o *VCDClient) AssignVmClassesToRegionQuota(regionQuotaId string, vmClasses *types.RegionVirtualMachineClasses) error { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, endpointParams: []string{regionQuotaId}, requiresTm: true, @@ -146,15 +146,15 @@ func (o *VCDClient) AssignVmClassesToOrgRegionQuota(regionQuotaId string, vmClas return nil } -// AssignVmClasses assigns VM Classes to the receiver Org Region Quota -func (o *OrgRegionQuota) AssignVmClasses(vmClasses *types.RegionVirtualMachineClasses) error { - return o.vcdClient.AssignVmClassesToOrgRegionQuota(o.OrgRegionQuota.ID, vmClasses) +// AssignVmClasses assigns VM Classes to the receiver Region Quota +func (o *RegionQuota) AssignVmClasses(vmClasses *types.RegionVirtualMachineClasses) error { + return o.vcdClient.AssignVmClassesToRegionQuota(o.TmVdc.ID, vmClasses) } -// GetVmClassesFromOrgRegionQuota returns all VM Classes of the given Org Region Quota -func (o *VCDClient) GetVmClassesFromOrgRegionQuota(regionQuotaId string) (*types.RegionVirtualMachineClasses, error) { +// GetVmClassesFromRegionQuota returns all VM Classes of the given Region Quota +func (o *VCDClient) GetVmClassesFromRegionQuota(regionQuotaId string) (*types.RegionVirtualMachineClasses, error) { c := crudConfig{ - entityLabel: labelTmOrgRegionQuota, + entityLabel: labelRegionQuota, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcsVmClasses, endpointParams: []string{regionQuotaId}, requiresTm: true, diff --git a/govcd/tm_region_quota_test.go b/govcd/tm_region_quota_test.go index 8c1166ecb..22bf9d81a 100644 --- a/govcd/tm_region_quota_test.go +++ b/govcd/tm_region_quota_test.go @@ -52,11 +52,11 @@ func (vcd *TestVCD) Test_TmVdc(check *C) { }}, } - createdVdc, err := vcd.client.CreateOrgRegionQuota(vdcType) + createdVdc, err := vcd.client.CreateRegionQuota(vdcType) check.Assert(err, IsNil) check.Assert(createdVdc, NotNil) // Add to cleanup list - PrependToCleanupListOpenApi(createdVdc.OrgRegionQuota.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.OrgRegionQuota.ID) + PrependToCleanupListOpenApi(createdVdc.TmVdc.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.TmVdc.ID) defer func() { err = createdVdc.Delete() check.Assert(err, IsNil) @@ -68,37 +68,37 @@ func (vcd *TestVCD) Test_TmVdc(check *C) { }) // Get TM VDC By Name - byName, err := vcd.client.GetOrgRegionQuotaByName(vdcType.Name) + byName, err := vcd.client.GetRegionQuotaByName(vdcType.Name) check.Assert(err, IsNil) - check.Assert(byName.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) + check.Assert(byName.TmVdc, DeepEquals, createdVdc.TmVdc) // Get TM VDC By Id - byId, err := vcd.client.GetOrgRegionQuotaById(createdVdc.OrgRegionQuota.ID) + byId, err := vcd.client.GetRegionQuotaById(createdVdc.TmVdc.ID) check.Assert(err, IsNil) - check.Assert(byId.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) + check.Assert(byId.TmVdc, DeepEquals, createdVdc.TmVdc) // Get By Name and Org ID - byNameAndOrgId, err := vcd.client.GetOrgRegionQuotaByNameAndOrgId(createdVdc.OrgRegionQuota.Name, org.TmOrg.ID) + byNameAndOrgId, err := vcd.client.GetRegionQuotaByNameAndOrgId(createdVdc.TmVdc.Name, org.TmOrg.ID) check.Assert(err, IsNil) - check.Assert(byNameAndOrgId.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) + check.Assert(byNameAndOrgId.TmVdc, DeepEquals, createdVdc.TmVdc) // Get By Name and Org ID in non existent Org - byNameAndInvalidOrgId, err := vcd.client.GetOrgRegionQuotaByNameAndOrgId(createdVdc.OrgRegionQuota.Name, "urn:vcloud:org:a93c9db9-0000-0000-0000-a8f7eeda85f9") + byNameAndInvalidOrgId, err := vcd.client.GetRegionQuotaByNameAndOrgId(createdVdc.TmVdc.Name, "urn:vcloud:org:a93c9db9-0000-0000-0000-a8f7eeda85f9") check.Assert(err, NotNil) check.Assert(byNameAndInvalidOrgId, IsNil) // Not Found tests - byNameInvalid, err := vcd.client.GetOrgRegionQuotaByName("fake-name") + byNameInvalid, err := vcd.client.GetRegionQuotaByName("fake-name") check.Assert(ContainsNotFound(err), Equals, true) check.Assert(byNameInvalid, IsNil) - byIdInvalid, err := vcd.client.GetOrgRegionQuotaById("urn:vcloud:virtualDatacenter:5344b964-0000-0000-0000-d554913db643") + byIdInvalid, err := vcd.client.GetRegionQuotaById("urn:vcloud:virtualDatacenter:5344b964-0000-0000-0000-d554913db643") check.Assert(ContainsNotFound(err), Equals, true) check.Assert(byIdInvalid, IsNil) // Update - createdVdc.OrgRegionQuota.Name = check.TestName() + "-update" - updatedVdc, err := createdVdc.Update(createdVdc.OrgRegionQuota) + createdVdc.TmVdc.Name = check.TestName() + "-update" + updatedVdc, err := createdVdc.Update(createdVdc.TmVdc) check.Assert(err, IsNil) - check.Assert(updatedVdc.OrgRegionQuota, DeepEquals, createdVdc.OrgRegionQuota) + check.Assert(updatedVdc.TmVdc, DeepEquals, createdVdc.TmVdc) } diff --git a/govcd/tm_region_vm_class.go b/govcd/tm_region_vm_class.go index 98e64c73f..db99c14d5 100644 --- a/govcd/tm_region_vm_class.go +++ b/govcd/tm_region_vm_class.go @@ -43,7 +43,7 @@ func (vcdClient *VCDClient) GetAllRegionVirtualMachineClasses(queryParameters ur // GetRegionVirtualMachineClassByNameAndRegionId retrieves a Region VM Class by a given name and Region ID func (vcdClient *VCDClient) GetRegionVirtualMachineClassByNameAndRegionId(name, regionId string) (*RegionVirtualMachineClass, error) { if name == "" { - return nil, fmt.Errorf("%s lookup requires name", labelTmOrgRegionQuota) + return nil, fmt.Errorf("%s lookup requires name", labelRegionQuota) } queryParams := url.Values{} diff --git a/govcd/tm_vdc_storage_policy.go b/govcd/tm_vdc_storage_policy.go index a9cd7419a..e1b3841e9 100644 --- a/govcd/tm_vdc_storage_policy.go +++ b/govcd/tm_vdc_storage_policy.go @@ -11,10 +11,10 @@ import ( "strings" ) -const labelTmOrgVdcStoragePolicies = "TM Org Vdc Storage Policies" +const labelRegionQuotaStoragePolicies = "Region Quota Storage Policies" -// TmVdcStoragePolicy defines Tenant Manager Virtual Datacenter Storage Policy structure -type TmVdcStoragePolicy struct { +// OrgRegionQuotaStoragePolicy defines Tenant Manager Virtual Datacenter Storage Policy structure +type OrgRegionQuotaStoragePolicy struct { VirtualDatacenterStoragePolicy *types.VirtualDatacenterStoragePolicy vcdClient *VCDClient } @@ -22,17 +22,17 @@ type TmVdcStoragePolicy struct { // 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 TmVdcStoragePolicy) wrap(inner *types.VirtualDatacenterStoragePolicy) *TmVdcStoragePolicy { +func (g OrgRegionQuotaStoragePolicy) wrap(inner *types.VirtualDatacenterStoragePolicy) *OrgRegionQuotaStoragePolicy { g.VirtualDatacenterStoragePolicy = inner return &g } -// CreateStoragePolicies creates new VDC Storage Policies in a VDC. -// The request will fail if the list of VDC Storage Policies is empty. -// It returns the list of all VCD Storage Policies that are available in the VDC after creation. -func (o *OrgRegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*TmVdcStoragePolicy, error) { +// CreateStoragePolicies creates new Region Quota Storage Policies in a Region Quota. +// The request will fail if the list of Storage Policies is empty. +// It returns the list of all Storage Policies that are available in the Region Quota after creation. +func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*OrgRegionQuotaStoragePolicy, error) { c := crudConfig{ - entityLabel: labelTmOrgVdcStoragePolicies, + entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, requiresTm: true, } @@ -46,43 +46,43 @@ func (o *OrgRegionQuota) CreateStoragePolicies(regionStoragePolicies *types.Virt } } - // Get all the storage policies from the VDC and return them + // Get all the storage policies from the Region Quota and return them allPolicies, err := o.GetAllStoragePolicies(nil) if err != nil { - return nil, fmt.Errorf("could not retrieve all the VDC Storage Policies after creation: %s", err) + return nil, fmt.Errorf("could not retrieve all the %s after creation: %s", labelRegionQuotaStoragePolicies, err) } return allPolicies, nil } -// GetAllTmVdcStoragePolicies retrieves all Tenant Manager VDC Storage Policies -func (vcdClient *VCDClient) GetAllTmVdcStoragePolicies(queryParameters url.Values) ([]*TmVdcStoragePolicy, error) { +// GetAllRegionQuotaStoragePolicies retrieves all Region Quota Storage Policies +func (vcdClient *VCDClient) GetAllRegionQuotaStoragePolicies(queryParameters url.Values) ([]*OrgRegionQuotaStoragePolicy, error) { c := crudConfig{ - entityLabel: labelTmOrgVdcStoragePolicies, + entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, queryParameters: queryParameters, requiresTm: true, } - outerType := TmVdcStoragePolicy{vcdClient: vcdClient} + outerType := OrgRegionQuotaStoragePolicy{vcdClient: vcdClient} return getAllOuterEntities(&vcdClient.Client, outerType, c) } -// GetAllStoragePolicies retrieves all VDC Storage Policies from the given VDC -func (vdc *OrgRegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*TmVdcStoragePolicy, error) { - params := queryParameterFilterAnd("virtualDatacenter.id=="+vdc.OrgRegionQuota.ID, queryParameters) - return vdc.vcdClient.GetAllTmVdcStoragePolicies(params) +// GetAllStoragePolicies retrieves all Region Quota Storage Policies from the given Region Quota +func (vdc *RegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*OrgRegionQuotaStoragePolicy, error) { + params := queryParameterFilterAnd("virtualDatacenter.id=="+vdc.TmVdc.ID, queryParameters) + return vdc.vcdClient.GetAllRegionQuotaStoragePolicies(params) } -// GetTmVdcStoragePolicyByName retrieves a VDC Storage Policy by the given name -func (vdc *OrgRegionQuota) GetTmVdcStoragePolicyByName(name string) (*TmVdcStoragePolicy, error) { +// GetStoragePolicyByName retrieves a Region Quota Storage Policy by the given name +func (vdc *RegionQuota) GetStoragePolicyByName(name string) (*OrgRegionQuotaStoragePolicy, error) { if name == "" { - return nil, fmt.Errorf("%s lookup requires name to be present", labelTmOrgVdcStoragePolicies) + return nil, fmt.Errorf("%s lookup requires name to be present", labelRegionQuotaStoragePolicies) } queryParams := url.Values{} - queryParams.Add("filter", fmt.Sprintf("virtualDatacenter.id==%s;name==%s", vdc.OrgRegionQuota.ID, name)) + queryParams.Add("filter", fmt.Sprintf("virtualDatacenter.id==%s;name==%s", vdc.TmVdc.ID, name)) - filteredEntities, err := vdc.vcdClient.GetAllTmVdcStoragePolicies(queryParams) + filteredEntities, err := vdc.vcdClient.GetAllRegionQuotaStoragePolicies(queryParams) if err != nil { return nil, err } @@ -95,51 +95,51 @@ func (vdc *OrgRegionQuota) GetTmVdcStoragePolicyByName(name string) (*TmVdcStora return singleResult, nil } -// GetTmVdcStoragePolicyById retrieves a VDC Storage Policy by a given ID -func (vcdClient *VCDClient) GetTmVdcStoragePolicyById(id string) (*TmVdcStoragePolicy, error) { +// GetRegionQuotaStoragePolicyById retrieves a Region Quota Storage Policy by a given ID +func (vcdClient *VCDClient) GetRegionQuotaStoragePolicyById(id string) (*OrgRegionQuotaStoragePolicy, error) { c := crudConfig{ - entityLabel: labelTmOrgVdcStoragePolicies, + entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, endpointParams: []string{id}, requiresTm: true, } - outerType := TmVdcStoragePolicy{vcdClient: vcdClient} + outerType := OrgRegionQuotaStoragePolicy{vcdClient: vcdClient} return getOuterEntity(&vcdClient.Client, outerType, c) } -// GetStoragePolicyById retrieves a Tenant Manager VDC Storage Policy by a given ID that must belong -// to the receiver VDC -func (vdc *OrgRegionQuota) GetStoragePolicyById(id string) (*TmVdcStoragePolicy, error) { - policy, err := vdc.vcdClient.GetTmVdcStoragePolicyById(id) +// GetStoragePolicyById retrieves a Region Quota Storage Policy by a given ID that must belong +// to the receiver Region Quota +func (rq *RegionQuota) GetStoragePolicyById(id string) (*OrgRegionQuotaStoragePolicy, error) { + policy, err := rq.vcdClient.GetRegionQuotaStoragePolicyById(id) if err != nil { return nil, err } - if policy.VirtualDatacenterStoragePolicy.VirtualDatacenter.ID != vdc.OrgRegionQuota.ID { - return nil, fmt.Errorf("no VDC Storage Policy with ID '%s' found in VDC '%s': %s", id, vdc.OrgRegionQuota.ID, ErrorEntityNotFound) + if policy.VirtualDatacenterStoragePolicy.VirtualDatacenter.ID != rq.TmVdc.ID { + return nil, fmt.Errorf("no %s with ID '%s' found in %s '%s': %s", labelRegionQuotaStoragePolicies, id, labelRegionQuota, rq.TmVdc.ID, ErrorEntityNotFound) } return policy, err } -// Update Tenant Manager VDC -func (vsp *TmVdcStoragePolicy) Update(tmVdcConfig *types.VirtualDatacenterStoragePolicy) (*TmVdcStoragePolicy, error) { +// Update updates the receiver Region Quota Storage Policy +func (sp *OrgRegionQuotaStoragePolicy) Update(tmVdcConfig *types.VirtualDatacenterStoragePolicy) (*OrgRegionQuotaStoragePolicy, error) { c := crudConfig{ - entityLabel: labelTmOrgVdcStoragePolicies, + entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, - endpointParams: []string{vsp.VirtualDatacenterStoragePolicy.ID}, + endpointParams: []string{sp.VirtualDatacenterStoragePolicy.ID}, requiresTm: true, } - outerType := TmVdcStoragePolicy{vcdClient: vsp.vcdClient} - return updateOuterEntity(&vsp.vcdClient.Client, outerType, c, tmVdcConfig) + outerType := OrgRegionQuotaStoragePolicy{vcdClient: sp.vcdClient} + return updateOuterEntity(&sp.vcdClient.Client, outerType, c, tmVdcConfig) } -// Delete deletes a VDC Storage Policy -func (vsp *TmVdcStoragePolicy) Delete() error { +// Delete deletes a Region Quota Storage Policy +func (sp *OrgRegionQuotaStoragePolicy) Delete() error { c := crudConfig{ - entityLabel: labelTmOrgVdcStoragePolicies, + entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, - endpointParams: []string{vsp.VirtualDatacenterStoragePolicy.ID}, + endpointParams: []string{sp.VirtualDatacenterStoragePolicy.ID}, requiresTm: true, } - return deleteEntityById(&vsp.vcdClient.Client, c) + return deleteEntityById(&sp.vcdClient.Client, c) } diff --git a/govcd/tm_vdc_storage_policy_test.go b/govcd/tm_vdc_storage_policy_test.go index 5731c30d2..3781264b3 100644 --- a/govcd/tm_vdc_storage_policy_test.go +++ b/govcd/tm_vdc_storage_policy_test.go @@ -58,11 +58,11 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { }}, } - createdVdc, err := vcd.client.CreateOrgRegionQuota(vdcType) + createdVdc, err := vcd.client.CreateRegionQuota(vdcType) check.Assert(err, IsNil) check.Assert(createdVdc, NotNil) // Add to cleanup list - PrependToCleanupListOpenApi(createdVdc.OrgRegionQuota.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.OrgRegionQuota.ID) + PrependToCleanupListOpenApi(createdVdc.TmVdc.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.TmVdc.ID) defer func() { err = createdVdc.Delete() check.Assert(err, IsNil) @@ -77,7 +77,7 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { }, StorageLimitMiB: 100, VirtualDatacenter: types.OpenApiReference{ - ID: createdVdc.OrgRegionQuota.ID, + ID: createdVdc.TmVdc.ID, }, }, }, @@ -106,8 +106,8 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { // Getting policies with general client params := url.Values{} - params.Add("filter", "virtualDatacenter.id=="+createdVdc.OrgRegionQuota.ID) - filteredPolicies, err := vcd.client.GetAllTmVdcStoragePolicies(params) + params.Add("filter", "virtualDatacenter.id=="+createdVdc.TmVdc.ID) + filteredPolicies, err := vcd.client.GetAllRegionQuotaStoragePolicies(params) check.Assert(err, IsNil) check.Assert(len(filteredPolicies), Equals, len(vdcPolicies)) check.Assert(filteredPolicies[0].VirtualDatacenterStoragePolicy, NotNil) @@ -126,13 +126,13 @@ func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { check.Assert(updatedPolicy.VirtualDatacenterStoragePolicy.StorageLimitMiB, Equals, int64(200)) - policy, err = vcd.client.GetTmVdcStoragePolicyById(vdcPolicies[0].VirtualDatacenterStoragePolicy.ID) + policy, err = vcd.client.GetRegionQuotaStoragePolicyById(vdcPolicies[0].VirtualDatacenterStoragePolicy.ID) check.Assert(err, IsNil) check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *vdcPolicies[0].VirtualDatacenterStoragePolicy) // Not Found tests - byNameInvalid, err := vcd.client.GetTmVdcStoragePolicyById("urn:vcloud:virtualDatacenterStoragePolicy:5344b964-0000-0000-0000-d554913db643") + byNameInvalid, err := vcd.client.GetRegionQuotaStoragePolicyById("urn:vcloud:virtualDatacenterStoragePolicy:5344b964-0000-0000-0000-d554913db643") check.Assert(ContainsNotFound(err), Equals, true) check.Assert(byNameInvalid, IsNil) From 799542539b9753d21d818a01964306c2977c2058 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Fri, 7 Feb 2025 15:16:39 +0100 Subject: [PATCH 07/25] Rename Signed-off-by: abarreiro --- ...y.go => tm_region_quota_storage_policy.go} | 28 +++++++++---------- ...=> tm_region_quota_storage_policy_test.go} | 2 +- govcd/tm_region_quota_test.go | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) rename govcd/{tm_vdc_storage_policy.go => tm_region_quota_storage_policy.go} (81%) rename govcd/{tm_vdc_storage_policy_test.go => tm_region_quota_storage_policy_test.go} (98%) diff --git a/govcd/tm_vdc_storage_policy.go b/govcd/tm_region_quota_storage_policy.go similarity index 81% rename from govcd/tm_vdc_storage_policy.go rename to govcd/tm_region_quota_storage_policy.go index e1b3841e9..3dfa43cda 100644 --- a/govcd/tm_vdc_storage_policy.go +++ b/govcd/tm_region_quota_storage_policy.go @@ -13,8 +13,8 @@ import ( const labelRegionQuotaStoragePolicies = "Region Quota Storage Policies" -// OrgRegionQuotaStoragePolicy defines Tenant Manager Virtual Datacenter Storage Policy structure -type OrgRegionQuotaStoragePolicy struct { +// RegionQuotaStoragePolicy defines Tenant Manager Virtual Datacenter Storage Policy structure +type RegionQuotaStoragePolicy struct { VirtualDatacenterStoragePolicy *types.VirtualDatacenterStoragePolicy vcdClient *VCDClient } @@ -22,7 +22,7 @@ type OrgRegionQuotaStoragePolicy struct { // 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 OrgRegionQuotaStoragePolicy) wrap(inner *types.VirtualDatacenterStoragePolicy) *OrgRegionQuotaStoragePolicy { +func (g RegionQuotaStoragePolicy) wrap(inner *types.VirtualDatacenterStoragePolicy) *RegionQuotaStoragePolicy { g.VirtualDatacenterStoragePolicy = inner return &g } @@ -30,7 +30,7 @@ func (g OrgRegionQuotaStoragePolicy) wrap(inner *types.VirtualDatacenterStorageP // CreateStoragePolicies creates new Region Quota Storage Policies in a Region Quota. // The request will fail if the list of Storage Policies is empty. // It returns the list of all Storage Policies that are available in the Region Quota after creation. -func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*OrgRegionQuotaStoragePolicy, error) { +func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*RegionQuotaStoragePolicy, error) { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, @@ -55,7 +55,7 @@ func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.Virtual } // GetAllRegionQuotaStoragePolicies retrieves all Region Quota Storage Policies -func (vcdClient *VCDClient) GetAllRegionQuotaStoragePolicies(queryParameters url.Values) ([]*OrgRegionQuotaStoragePolicy, error) { +func (vcdClient *VCDClient) GetAllRegionQuotaStoragePolicies(queryParameters url.Values) ([]*RegionQuotaStoragePolicy, error) { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, @@ -63,18 +63,18 @@ func (vcdClient *VCDClient) GetAllRegionQuotaStoragePolicies(queryParameters url requiresTm: true, } - outerType := OrgRegionQuotaStoragePolicy{vcdClient: vcdClient} + outerType := RegionQuotaStoragePolicy{vcdClient: vcdClient} return getAllOuterEntities(&vcdClient.Client, outerType, c) } // GetAllStoragePolicies retrieves all Region Quota Storage Policies from the given Region Quota -func (vdc *RegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*OrgRegionQuotaStoragePolicy, error) { +func (vdc *RegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*RegionQuotaStoragePolicy, error) { params := queryParameterFilterAnd("virtualDatacenter.id=="+vdc.TmVdc.ID, queryParameters) return vdc.vcdClient.GetAllRegionQuotaStoragePolicies(params) } // GetStoragePolicyByName retrieves a Region Quota Storage Policy by the given name -func (vdc *RegionQuota) GetStoragePolicyByName(name string) (*OrgRegionQuotaStoragePolicy, error) { +func (vdc *RegionQuota) GetStoragePolicyByName(name string) (*RegionQuotaStoragePolicy, error) { if name == "" { return nil, fmt.Errorf("%s lookup requires name to be present", labelRegionQuotaStoragePolicies) } @@ -96,7 +96,7 @@ func (vdc *RegionQuota) GetStoragePolicyByName(name string) (*OrgRegionQuotaStor } // GetRegionQuotaStoragePolicyById retrieves a Region Quota Storage Policy by a given ID -func (vcdClient *VCDClient) GetRegionQuotaStoragePolicyById(id string) (*OrgRegionQuotaStoragePolicy, error) { +func (vcdClient *VCDClient) GetRegionQuotaStoragePolicyById(id string) (*RegionQuotaStoragePolicy, error) { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, @@ -104,13 +104,13 @@ func (vcdClient *VCDClient) GetRegionQuotaStoragePolicyById(id string) (*OrgRegi requiresTm: true, } - outerType := OrgRegionQuotaStoragePolicy{vcdClient: vcdClient} + outerType := RegionQuotaStoragePolicy{vcdClient: vcdClient} return getOuterEntity(&vcdClient.Client, outerType, c) } // GetStoragePolicyById retrieves a Region Quota Storage Policy by a given ID that must belong // to the receiver Region Quota -func (rq *RegionQuota) GetStoragePolicyById(id string) (*OrgRegionQuotaStoragePolicy, error) { +func (rq *RegionQuota) GetStoragePolicyById(id string) (*RegionQuotaStoragePolicy, error) { policy, err := rq.vcdClient.GetRegionQuotaStoragePolicyById(id) if err != nil { return nil, err @@ -122,19 +122,19 @@ func (rq *RegionQuota) GetStoragePolicyById(id string) (*OrgRegionQuotaStoragePo } // Update updates the receiver Region Quota Storage Policy -func (sp *OrgRegionQuotaStoragePolicy) Update(tmVdcConfig *types.VirtualDatacenterStoragePolicy) (*OrgRegionQuotaStoragePolicy, error) { +func (sp *RegionQuotaStoragePolicy) Update(tmVdcConfig *types.VirtualDatacenterStoragePolicy) (*RegionQuotaStoragePolicy, error) { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, endpointParams: []string{sp.VirtualDatacenterStoragePolicy.ID}, requiresTm: true, } - outerType := OrgRegionQuotaStoragePolicy{vcdClient: sp.vcdClient} + outerType := RegionQuotaStoragePolicy{vcdClient: sp.vcdClient} return updateOuterEntity(&sp.vcdClient.Client, outerType, c, tmVdcConfig) } // Delete deletes a Region Quota Storage Policy -func (sp *OrgRegionQuotaStoragePolicy) Delete() error { +func (sp *RegionQuotaStoragePolicy) Delete() error { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, diff --git a/govcd/tm_vdc_storage_policy_test.go b/govcd/tm_region_quota_storage_policy_test.go similarity index 98% rename from govcd/tm_vdc_storage_policy_test.go rename to govcd/tm_region_quota_storage_policy_test.go index 3781264b3..07038eff5 100644 --- a/govcd/tm_vdc_storage_policy_test.go +++ b/govcd/tm_region_quota_storage_policy_test.go @@ -13,7 +13,7 @@ import ( . "gopkg.in/check.v1" ) -func (vcd *TestVCD) Test_TmVdcStoragePolicy(check *C) { +func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { skipNonTm(vcd, check) sysadminOnly(vcd, check) diff --git a/govcd/tm_region_quota_test.go b/govcd/tm_region_quota_test.go index 22bf9d81a..1ecdeeff6 100644 --- a/govcd/tm_region_quota_test.go +++ b/govcd/tm_region_quota_test.go @@ -11,7 +11,7 @@ import ( . "gopkg.in/check.v1" ) -func (vcd *TestVCD) Test_TmVdc(check *C) { +func (vcd *TestVCD) Test_TmRegionQuota(check *C) { skipNonTm(vcd, check) sysadminOnly(vcd, check) From 165446958e0469f6e6820738f86e96a1dcb49959 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Mon, 10 Feb 2025 17:28:22 +0100 Subject: [PATCH 08/25] Fixes Signed-off-by: abarreiro --- govcd/api_vcd_test.go | 7 +- govcd/tm_region_quota_storage_policy.go | 45 +++++--- govcd/tm_region_quota_storage_policy_test.go | 105 ++++++++++--------- 3 files changed, 90 insertions(+), 67 deletions(-) diff --git a/govcd/api_vcd_test.go b/govcd/api_vcd_test.go index abc8e9679..20e619d71 100644 --- a/govcd/api_vcd_test.go +++ b/govcd/api_vcd_test.go @@ -141,10 +141,9 @@ type TestConfig struct { } Tenants []Tenant `yaml:"tenants,omitempty"` Tm struct { - CreateRegion bool `yaml:"createRegion"` - Region string `yaml:"region"` - StorageClass string `yaml:"storageClass"` - + CreateRegion bool `yaml:"createRegion"` + Region string `yaml:"region"` + StorageClass string `yaml:"storageClass"` ContentLibrary string `yaml:"contentLibrary"` SubscriptionContentLibraryUrl string `yaml:"subscriptionContentLibraryUrl"` diff --git a/govcd/tm_region_quota_storage_policy.go b/govcd/tm_region_quota_storage_policy.go index 3dfa43cda..6cb09f873 100644 --- a/govcd/tm_region_quota_storage_policy.go +++ b/govcd/tm_region_quota_storage_policy.go @@ -27,17 +27,17 @@ func (g RegionQuotaStoragePolicy) wrap(inner *types.VirtualDatacenterStoragePoli return &g } -// CreateStoragePolicies creates new Region Quota Storage Policies in a Region Quota. +// CreateRegionQuotaStoragePolicies creates new Region Quota Storage Policies in a Region Quota. // The request will fail if the list of Storage Policies is empty. // It returns the list of all Storage Policies that are available in the Region Quota after creation. -func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*RegionQuotaStoragePolicy, error) { +func (vcdClient *VCDClient) CreateRegionQuotaStoragePolicies(regionQuotaId string, regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*RegionQuotaStoragePolicy, error) { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, requiresTm: true, } - _, err := createInnerEntity[types.VirtualDatacenterStoragePolicies](&o.vcdClient.Client, c, regionStoragePolicies) + _, err := createInnerEntity[types.VirtualDatacenterStoragePolicies](&vcdClient.Client, c, regionStoragePolicies) if err != nil { // TODO: TM: The returned task contains a wrong URN in the "Owner" field, so the VDC can't be retrieved. // We don't really need it either, so we ignore this error. @@ -47,13 +47,20 @@ func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.Virtual } // Get all the storage policies from the Region Quota and return them - allPolicies, err := o.GetAllStoragePolicies(nil) + allPolicies, err := vcdClient.GetAllRegionQuotaStoragePolicies(nil) if err != nil { return nil, fmt.Errorf("could not retrieve all the %s after creation: %s", labelRegionQuotaStoragePolicies, err) } return allPolicies, nil } +// CreateStoragePolicies creates new Region Quota Storage Policies in a Region Quota. +// The request will fail if the list of Storage Policies is empty. +// It returns the list of all Storage Policies that are available in the Region Quota after creation. +func (o *RegionQuota) CreateStoragePolicies(regionStoragePolicies *types.VirtualDatacenterStoragePolicies) ([]*RegionQuotaStoragePolicy, error) { + return o.vcdClient.CreateRegionQuotaStoragePolicies(o.TmVdc.ID, regionStoragePolicies) +} + // GetAllRegionQuotaStoragePolicies retrieves all Region Quota Storage Policies func (vcdClient *VCDClient) GetAllRegionQuotaStoragePolicies(queryParameters url.Values) ([]*RegionQuotaStoragePolicy, error) { c := crudConfig{ @@ -80,7 +87,7 @@ func (vdc *RegionQuota) GetStoragePolicyByName(name string) (*RegionQuotaStorage } queryParams := url.Values{} - queryParams.Add("filter", fmt.Sprintf("virtualDatacenter.id==%s;name==%s", vdc.TmVdc.ID, name)) + queryParams.Add("filter", fmt.Sprintf("virtualDatacenter.id==%s;name==%s", vdc.TmVdc.ID, "*")) filteredEntities, err := vdc.vcdClient.GetAllRegionQuotaStoragePolicies(queryParams) if err != nil { @@ -121,25 +128,35 @@ func (rq *RegionQuota) GetStoragePolicyById(id string) (*RegionQuotaStoragePolic return policy, err } -// Update updates the receiver Region Quota Storage Policy -func (sp *RegionQuotaStoragePolicy) Update(tmVdcConfig *types.VirtualDatacenterStoragePolicy) (*RegionQuotaStoragePolicy, error) { +// UpdateRegionQuotaStoragePolicy updates the Region Quota Storage Policy with given ID +func (vcdClient *VCDClient) UpdateRegionQuotaStoragePolicy(regionQuotaStoragePolicyId string, tmVdcConfig *types.VirtualDatacenterStoragePolicy) (*RegionQuotaStoragePolicy, error) { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, - endpointParams: []string{sp.VirtualDatacenterStoragePolicy.ID}, + endpointParams: []string{regionQuotaStoragePolicyId}, requiresTm: true, } - outerType := RegionQuotaStoragePolicy{vcdClient: sp.vcdClient} - return updateOuterEntity(&sp.vcdClient.Client, outerType, c, tmVdcConfig) + outerType := RegionQuotaStoragePolicy{vcdClient: vcdClient} + return updateOuterEntity(&vcdClient.Client, outerType, c, tmVdcConfig) } -// Delete deletes a Region Quota Storage Policy -func (sp *RegionQuotaStoragePolicy) Delete() error { +// Update updates the receiver Region Quota Storage Policy +func (sp *RegionQuotaStoragePolicy) Update(spConfig *types.VirtualDatacenterStoragePolicy) (*RegionQuotaStoragePolicy, error) { + return sp.vcdClient.UpdateRegionQuotaStoragePolicy(sp.VirtualDatacenterStoragePolicy.ID, spConfig) +} + +// DeleteRegionQuotaStoragePolicy deletes a Region Quota Storage Policy with given ID +func (vcdClient *VCDClient) DeleteRegionQuotaStoragePolicy(regionQuotaStoragePolicyId string) error { c := crudConfig{ entityLabel: labelRegionQuotaStoragePolicies, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmVdcStoragePolicies, - endpointParams: []string{sp.VirtualDatacenterStoragePolicy.ID}, + endpointParams: []string{regionQuotaStoragePolicyId}, requiresTm: true, } - return deleteEntityById(&sp.vcdClient.Client, c) + return deleteEntityById(&vcdClient.Client, c) +} + +// Delete deletes a Region Quota Storage Policy +func (sp *RegionQuotaStoragePolicy) Delete() error { + return sp.vcdClient.DeleteRegionQuotaStoragePolicy(sp.VirtualDatacenterStoragePolicy.ID) } diff --git a/govcd/tm_region_quota_storage_policy_test.go b/govcd/tm_region_quota_storage_policy_test.go index 07038eff5..c72abb97a 100644 --- a/govcd/tm_region_quota_storage_policy_test.go +++ b/govcd/tm_region_quota_storage_policy_test.go @@ -8,6 +8,7 @@ package govcd import ( "net/url" + "strings" "github.com/vmware/go-vcloud-director/v3/types/v56" . "gopkg.in/check.v1" @@ -58,18 +59,18 @@ func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { }}, } - createdVdc, err := vcd.client.CreateRegionQuota(vdcType) + createdRegionQuota, err := vcd.client.CreateRegionQuota(vdcType) check.Assert(err, IsNil) - check.Assert(createdVdc, NotNil) + check.Assert(createdRegionQuota, NotNil) // Add to cleanup list - PrependToCleanupListOpenApi(createdVdc.TmVdc.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdVdc.TmVdc.ID) + PrependToCleanupListOpenApi(createdRegionQuota.TmVdc.ID, check.TestName(), types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+createdRegionQuota.TmVdc.ID) defer func() { - err = createdVdc.Delete() + err = createdRegionQuota.Delete() check.Assert(err, IsNil) }() check.Assert(err, IsNil) - vdcPolicies, err := createdVdc.CreateStoragePolicies(&types.VirtualDatacenterStoragePolicies{ + rqPolicies, err := createdRegionQuota.CreateStoragePolicies(&types.VirtualDatacenterStoragePolicies{ Values: []types.VirtualDatacenterStoragePolicy{ { RegionStoragePolicy: types.OpenApiReference{ @@ -77,67 +78,73 @@ func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { }, StorageLimitMiB: 100, VirtualDatacenter: types.OpenApiReference{ - ID: createdVdc.TmVdc.ID, + ID: createdRegionQuota.TmVdc.ID, }, }, }, }) check.Assert(err, IsNil) - // TODO: TM: Does not work - //defer func() { - // err = vdcPolicies[0].Delete() - // check.Assert(err, IsNil) - //}() - check.Assert(len(vdcPolicies), Equals, 1) - check.Assert(vdcPolicies[0].VirtualDatacenterStoragePolicy, NotNil) - - // Getting policies by VDC (the parent) - allPolicies, err := createdVdc.GetAllStoragePolicies(nil) + check.Assert(len(rqPolicies), Equals, 1) + check.Assert(rqPolicies[0].VirtualDatacenterStoragePolicy, NotNil) + + // Getting policies by Region Quota (the parent) + allPolicies, err := createdRegionQuota.GetAllStoragePolicies(nil) check.Assert(err, IsNil) - check.Assert(len(allPolicies), Equals, len(vdcPolicies)) + check.Assert(len(allPolicies), Equals, len(rqPolicies)) check.Assert(allPolicies[0].VirtualDatacenterStoragePolicy, NotNil) - check.Assert(*allPolicies[0].VirtualDatacenterStoragePolicy, DeepEquals, *vdcPolicies[0].VirtualDatacenterStoragePolicy) + check.Assert(*allPolicies[0].VirtualDatacenterStoragePolicy, DeepEquals, *rqPolicies[0].VirtualDatacenterStoragePolicy) - // TODO: TM: Does not work - /* policy, err := createdVdc.GetStoragePolicyById(vdcPolicies[0].VirtualDatacenterStoragePolicy.ID) - check.Assert(err, IsNil) - check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) - check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *vdcPolicies[0].VirtualDatacenterStoragePolicy)*/ + policy, err := createdRegionQuota.GetStoragePolicyById(rqPolicies[0].VirtualDatacenterStoragePolicy.ID) + check.Assert(err, IsNil) + check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) + check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *rqPolicies[0].VirtualDatacenterStoragePolicy) + + policy, err = createdRegionQuota.GetStoragePolicyByName(rqPolicies[0].VirtualDatacenterStoragePolicy.Name) + check.Assert(err, IsNil) + check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) + check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *rqPolicies[0].VirtualDatacenterStoragePolicy) // Getting policies with general client params := url.Values{} - params.Add("filter", "virtualDatacenter.id=="+createdVdc.TmVdc.ID) + params.Add("filter", "virtualDatacenter.id=="+createdRegionQuota.TmVdc.ID) filteredPolicies, err := vcd.client.GetAllRegionQuotaStoragePolicies(params) check.Assert(err, IsNil) - check.Assert(len(filteredPolicies), Equals, len(vdcPolicies)) + check.Assert(len(filteredPolicies), Equals, len(rqPolicies)) check.Assert(filteredPolicies[0].VirtualDatacenterStoragePolicy, NotNil) - check.Assert(*filteredPolicies[0].VirtualDatacenterStoragePolicy, DeepEquals, *vdcPolicies[0].VirtualDatacenterStoragePolicy) - - // TODO: TM: Does not work - /* - // Update policy - updatedPolicy, err := vdcPolicies[0].Update(&types.VirtualDatacenterStoragePolicy{ - RegionStoragePolicy: vdcPolicies[0].VirtualDatacenterStoragePolicy.RegionStoragePolicy, - StorageLimitMiB: 200, - VirtualDatacenter: vdcPolicies[0].VirtualDatacenterStoragePolicy.VirtualDatacenter, - }) - check.Assert(err, IsNil) - check.Assert(updatedPolicy, NotNil) - check.Assert(updatedPolicy.VirtualDatacenterStoragePolicy.StorageLimitMiB, Equals, int64(200)) + check.Assert(*filteredPolicies[0].VirtualDatacenterStoragePolicy, DeepEquals, *rqPolicies[0].VirtualDatacenterStoragePolicy) + // Update policy + updatedPolicy, err := rqPolicies[0].Update(&types.VirtualDatacenterStoragePolicy{ + RegionStoragePolicy: rqPolicies[0].VirtualDatacenterStoragePolicy.RegionStoragePolicy, + StorageLimitMiB: 200, + VirtualDatacenter: rqPolicies[0].VirtualDatacenterStoragePolicy.VirtualDatacenter, + }) + check.Assert(err, IsNil) + check.Assert(updatedPolicy, NotNil) + check.Assert(updatedPolicy.VirtualDatacenterStoragePolicy.StorageLimitMiB, Equals, int64(200)) - policy, err = vcd.client.GetRegionQuotaStoragePolicyById(vdcPolicies[0].VirtualDatacenterStoragePolicy.ID) - check.Assert(err, IsNil) - check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) - check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *vdcPolicies[0].VirtualDatacenterStoragePolicy) + policy, err = vcd.client.GetRegionQuotaStoragePolicyById(rqPolicies[0].VirtualDatacenterStoragePolicy.ID) + check.Assert(err, IsNil) + check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) + check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *updatedPolicy.VirtualDatacenterStoragePolicy) + + // Delete the policy + err = policy.Delete() + if len(rqPolicies) == 1 { + // If there's only one policy, expect an error. There must be always one Storage Policy + check.Assert(err, NotNil) + check.Assert(strings.Contains(err.Error(), "Storage policy is not set for the entity in VDC"), Equals, true) + } else { + check.Assert(err, IsNil) + } - // Not Found tests - byNameInvalid, err := vcd.client.GetRegionQuotaStoragePolicyById("urn:vcloud:virtualDatacenterStoragePolicy:5344b964-0000-0000-0000-d554913db643") - check.Assert(ContainsNotFound(err), Equals, true) - check.Assert(byNameInvalid, IsNil) + // Not Found tests + byNameInvalid, err := vcd.client.GetRegionQuotaStoragePolicyById("urn:vcloud:virtualDatacenterStoragePolicy:5344b964-0000-0000-0000-d554913db643") + check.Assert(ContainsNotFound(err), Equals, true) + check.Assert(byNameInvalid, IsNil) - byIdInvalid, err := createdVdc.GetStoragePolicyById("urn:vcloud:virtualDatacenter:5344b964-0000-0000-0000-d554913db643") - check.Assert(ContainsNotFound(err), Equals, true) - check.Assert(byIdInvalid, IsNil)*/ + byIdInvalid, err := createdRegionQuota.GetStoragePolicyById("urn:vcloud:virtualDatacenterStoragePolicy:5344b964-0000-0000-0000-d554913db643") + check.Assert(ContainsNotFound(err), Equals, true) + check.Assert(byIdInvalid, IsNil) } From bcd0515d05cd80da545a342644f5dbe7861ed83c Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 10:38:45 +0100 Subject: [PATCH 09/25] # Signed-off-by: abarreiro --- govcd/tm_region_quota_storage_policy.go | 27 +++++++++----------- govcd/tm_region_quota_storage_policy_test.go | 12 +-------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/govcd/tm_region_quota_storage_policy.go b/govcd/tm_region_quota_storage_policy.go index 6cb09f873..d928508ed 100644 --- a/govcd/tm_region_quota_storage_policy.go +++ b/govcd/tm_region_quota_storage_policy.go @@ -75,31 +75,28 @@ func (vcdClient *VCDClient) GetAllRegionQuotaStoragePolicies(queryParameters url } // GetAllStoragePolicies retrieves all Region Quota Storage Policies from the given Region Quota -func (vdc *RegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*RegionQuotaStoragePolicy, error) { - params := queryParameterFilterAnd("virtualDatacenter.id=="+vdc.TmVdc.ID, queryParameters) - return vdc.vcdClient.GetAllRegionQuotaStoragePolicies(params) +func (regionQuota *RegionQuota) GetAllStoragePolicies(queryParameters url.Values) ([]*RegionQuotaStoragePolicy, error) { + params := queryParameterFilterAnd("virtualDatacenter.id=="+regionQuota.TmVdc.ID, queryParameters) + return regionQuota.vcdClient.GetAllRegionQuotaStoragePolicies(params) } -// GetStoragePolicyByName retrieves a Region Quota Storage Policy by the given name -func (vdc *RegionQuota) GetStoragePolicyByName(name string) (*RegionQuotaStoragePolicy, error) { +// GetStoragePolicyByName retrieves a Region Quota Storage Policy by the given name. This method runs in O(n) +// where n is the number of Storage Policies in the receiver Region Quota, as the endpoint does not support filtering. +func (regionQuota *RegionQuota) GetStoragePolicyByName(name string) (*RegionQuotaStoragePolicy, error) { if name == "" { return nil, fmt.Errorf("%s lookup requires name to be present", labelRegionQuotaStoragePolicies) } - queryParams := url.Values{} - queryParams.Add("filter", fmt.Sprintf("virtualDatacenter.id==%s;name==%s", vdc.TmVdc.ID, "*")) - - filteredEntities, err := vdc.vcdClient.GetAllRegionQuotaStoragePolicies(queryParams) + allSps, err := regionQuota.GetAllStoragePolicies(nil) if err != nil { return nil, err } - - singleResult, err := oneOrError("name", name, filteredEntities) - if err != nil { - return nil, err + for _, sp := range allSps { + if sp.VirtualDatacenterStoragePolicy.Name == name { + return sp, nil + } } - - return singleResult, nil + return nil, fmt.Errorf("unable to find storage policy with name '%s' after lookup: %s", name, ErrorEntityNotFound) } // GetRegionQuotaStoragePolicyById retrieves a Region Quota Storage Policy by a given ID diff --git a/govcd/tm_region_quota_storage_policy_test.go b/govcd/tm_region_quota_storage_policy_test.go index c72abb97a..a2bee93df 100644 --- a/govcd/tm_region_quota_storage_policy_test.go +++ b/govcd/tm_region_quota_storage_policy_test.go @@ -7,7 +7,6 @@ package govcd import ( - "net/url" "strings" "github.com/vmware/go-vcloud-director/v3/types/v56" @@ -87,7 +86,7 @@ func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { check.Assert(len(rqPolicies), Equals, 1) check.Assert(rqPolicies[0].VirtualDatacenterStoragePolicy, NotNil) - // Getting policies by Region Quota (the parent) + // Getting policies allPolicies, err := createdRegionQuota.GetAllStoragePolicies(nil) check.Assert(err, IsNil) check.Assert(len(allPolicies), Equals, len(rqPolicies)) @@ -104,15 +103,6 @@ func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { check.Assert(policy.VirtualDatacenterStoragePolicy, NotNil) check.Assert(*policy.VirtualDatacenterStoragePolicy, DeepEquals, *rqPolicies[0].VirtualDatacenterStoragePolicy) - // Getting policies with general client - params := url.Values{} - params.Add("filter", "virtualDatacenter.id=="+createdRegionQuota.TmVdc.ID) - filteredPolicies, err := vcd.client.GetAllRegionQuotaStoragePolicies(params) - check.Assert(err, IsNil) - check.Assert(len(filteredPolicies), Equals, len(rqPolicies)) - check.Assert(filteredPolicies[0].VirtualDatacenterStoragePolicy, NotNil) - check.Assert(*filteredPolicies[0].VirtualDatacenterStoragePolicy, DeepEquals, *rqPolicies[0].VirtualDatacenterStoragePolicy) - // Update policy updatedPolicy, err := rqPolicies[0].Update(&types.VirtualDatacenterStoragePolicy{ RegionStoragePolicy: rqPolicies[0].VirtualDatacenterStoragePolicy.RegionStoragePolicy, From 92d448bb59a34dd913b789ce08a3bf1bcf02d895 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 11:04:25 +0100 Subject: [PATCH 10/25] Changelog Signed-off-by: abarreiro --- .changes/v3.0.0/720-features.md | 10 +++++----- .changes/v3.0.0/734-features.md | 10 ++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.changes/v3.0.0/720-features.md b/.changes/v3.0.0/720-features.md index 7e5f93d9b..01ae45799 100644 --- a/.changes/v3.0.0/720-features.md +++ b/.changes/v3.0.0/720-features.md @@ -1,8 +1,8 @@ -* Added types `TmVdc` and `types.TmVdc` for managing Tenant Manager Org VDCs with methods - `VCDClient.CreateTmVdc`, `VCDClient.GetAllTmVdcs`, `VCDClient.GetTmVdcByName`, - `VCDClient.GetTmVdcById`, `VCDClient.GetTmVdcByNameAndOrgId`, `TmVdc.Update`, `TmVdc.Delete`, - `TmVdc.AssignVmClasses`, `VCDClient.GetVmClassesFromRegionQuota`, `VCDClient.AssignVmClassesToRegionQuota` - [GH-720, GH-738, GH-748] +* Added types `RegionQuota` and `types.TmVdc` for managing Tenant Manager Org VDCs with methods + `VCDClient.CreateRegionQuota`, `VCDClient.GetAllRegionQuotas`, `VCDClient.GetRegionQuotaByName`, + `VCDClient.GetRegionQuotaByNameAndOrgId`, `VCDClient.GetRegionQuotaById`, `RegionQuota.Update`, `RegionQuota.Delete`, + `VCDClient.AssignVmClassesToRegionQuota`, `RegionQuota.AssignVmClasses`, + `VCDClient.GetVmClassesFromRegionQuota` [GH-720, GH-738, GH-748] * Added types `Zone` and `types.Zone` for reading Region Zones with methods `VCDClient.GetAllZones`, `VCDClient.GetZoneByName`, `VCDClient.GetZoneById`, `Region.GetAllZones`, `Region.GetZoneByName` [GH-720] diff --git a/.changes/v3.0.0/734-features.md b/.changes/v3.0.0/734-features.md index a2b255228..c3bcee597 100644 --- a/.changes/v3.0.0/734-features.md +++ b/.changes/v3.0.0/734-features.md @@ -1,4 +1,6 @@ -* Added types `TmVdcStoragePolicy`, `types.VirtualDatacenterStoragePolicies` and `types.VirtualDatacenterStoragePolicy` - to manage VDC Storage Policies, with methods `TmVdc.CreateStoragePolicies`, `VCDClient.GetAllTmVdcStoragePolicies`, - `TmVdc.GetAllStoragePolicies`, `VCDClient.GetTmVdcStoragePolicyById`, - `TmVdc.GetStoragePolicyById`, `TmVdc.Update`, `TmVdc.Delete` [GH-734] +* Added types `RegionQuotaStoragePolicy`, `types.VirtualDatacenterStoragePolicies` and `types.VirtualDatacenterStoragePolicy` + to manage VDC Storage Policies, with methods `VCDClient.CreateRegionQuotaStoragePolicies`, `RegionQuota.CreateStoragePolicies`, + `VCDClient.GetAllTmVdcStoragePolicies`, `VCDClient.GetAllRegionQuotaStoragePolicies`, `RegionQuota.GetAllStoragePolicies`, + `VCDClient.GetTmVdcStoragePolicyById`, `RegionQuota.GetStoragePolicyByName`, `VCDClient.GetRegionQuotaStoragePolicyById`, + `RegionQuota.GetStoragePolicyById`, `VCDClient.UpdateRegionQuotaStoragePolicy`, `RegionQuotaStoragePolicy.Update`, + `VCDClient.DeleteRegionQuotaStoragePolicy`, `RegionQuotaStoragePolicy.Delete` [GH-734, GH-748] From 326ae57fc80b6bfbdbae8f79891c9fc4dbb41934 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 11:04:49 +0100 Subject: [PATCH 11/25] Changelog Signed-off-by: abarreiro --- .changes/v3.0.0/734-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/v3.0.0/734-features.md b/.changes/v3.0.0/734-features.md index c3bcee597..c2571a7b0 100644 --- a/.changes/v3.0.0/734-features.md +++ b/.changes/v3.0.0/734-features.md @@ -1,6 +1,6 @@ * Added types `RegionQuotaStoragePolicy`, `types.VirtualDatacenterStoragePolicies` and `types.VirtualDatacenterStoragePolicy` to manage VDC Storage Policies, with methods `VCDClient.CreateRegionQuotaStoragePolicies`, `RegionQuota.CreateStoragePolicies`, `VCDClient.GetAllTmVdcStoragePolicies`, `VCDClient.GetAllRegionQuotaStoragePolicies`, `RegionQuota.GetAllStoragePolicies`, - `VCDClient.GetTmVdcStoragePolicyById`, `RegionQuota.GetStoragePolicyByName`, `VCDClient.GetRegionQuotaStoragePolicyById`, + `RegionQuota.GetStoragePolicyByName`, `VCDClient.GetRegionQuotaStoragePolicyById`, `RegionQuota.GetStoragePolicyById`, `VCDClient.UpdateRegionQuotaStoragePolicy`, `RegionQuotaStoragePolicy.Update`, `VCDClient.DeleteRegionQuotaStoragePolicy`, `RegionQuotaStoragePolicy.Delete` [GH-734, GH-748] From 4af615e383f726d452eefa0edd3c23d70167257e Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 11:05:35 +0100 Subject: [PATCH 12/25] Changelog Signed-off-by: abarreiro --- .changes/v3.0.0/734-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/v3.0.0/734-features.md b/.changes/v3.0.0/734-features.md index c2571a7b0..4b1dec8ec 100644 --- a/.changes/v3.0.0/734-features.md +++ b/.changes/v3.0.0/734-features.md @@ -1,6 +1,6 @@ * Added types `RegionQuotaStoragePolicy`, `types.VirtualDatacenterStoragePolicies` and `types.VirtualDatacenterStoragePolicy` to manage VDC Storage Policies, with methods `VCDClient.CreateRegionQuotaStoragePolicies`, `RegionQuota.CreateStoragePolicies`, - `VCDClient.GetAllTmVdcStoragePolicies`, `VCDClient.GetAllRegionQuotaStoragePolicies`, `RegionQuota.GetAllStoragePolicies`, + `VCDClient.GetAllRegionQuotaStoragePolicies`, `RegionQuota.GetAllStoragePolicies`, `RegionQuota.GetStoragePolicyByName`, `VCDClient.GetRegionQuotaStoragePolicyById`, `RegionQuota.GetStoragePolicyById`, `VCDClient.UpdateRegionQuotaStoragePolicy`, `RegionQuotaStoragePolicy.Update`, `VCDClient.DeleteRegionQuotaStoragePolicy`, `RegionQuotaStoragePolicy.Delete` [GH-734, GH-748] From b1d1ca08cf30efa61988343f4b23538c5029b4d1 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 11:06:53 +0100 Subject: [PATCH 13/25] self-review Signed-off-by: abarreiro --- govcd/tm_region_quota_storage_policy_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/govcd/tm_region_quota_storage_policy_test.go b/govcd/tm_region_quota_storage_policy_test.go index a2bee93df..2b93d5e07 100644 --- a/govcd/tm_region_quota_storage_policy_test.go +++ b/govcd/tm_region_quota_storage_policy_test.go @@ -86,7 +86,7 @@ func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { check.Assert(len(rqPolicies), Equals, 1) check.Assert(rqPolicies[0].VirtualDatacenterStoragePolicy, NotNil) - // Getting policies + // Getting policies. We just test methods with RegionQuota receiver as these wrap the generic ones. allPolicies, err := createdRegionQuota.GetAllStoragePolicies(nil) check.Assert(err, IsNil) check.Assert(len(allPolicies), Equals, len(rqPolicies)) From 1f79ee51f4625a48e87864272c9d571dd74b6648 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 11:08:33 +0100 Subject: [PATCH 14/25] self-review Signed-off-by: abarreiro --- govcd/api_vcd_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/govcd/api_vcd_test.go b/govcd/api_vcd_test.go index 20e619d71..abc8e9679 100644 --- a/govcd/api_vcd_test.go +++ b/govcd/api_vcd_test.go @@ -141,9 +141,10 @@ type TestConfig struct { } Tenants []Tenant `yaml:"tenants,omitempty"` Tm struct { - CreateRegion bool `yaml:"createRegion"` - Region string `yaml:"region"` - StorageClass string `yaml:"storageClass"` + CreateRegion bool `yaml:"createRegion"` + Region string `yaml:"region"` + StorageClass string `yaml:"storageClass"` + ContentLibrary string `yaml:"contentLibrary"` SubscriptionContentLibraryUrl string `yaml:"subscriptionContentLibraryUrl"` From 61776ffd9fb01a0efdbdfd42ac66927d368d7ffe Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 11:42:12 +0100 Subject: [PATCH 15/25] self-review Signed-off-by: abarreiro --- govcd/tm_common_test.go | 20 ++++++++++---------- govcd/tm_content_library_test.go | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/govcd/tm_common_test.go b/govcd/tm_common_test.go index ef714b34f..28aa297c1 100644 --- a/govcd/tm_common_test.go +++ b/govcd/tm_common_test.go @@ -265,9 +265,9 @@ func createOrg(vcd *TestVCD, check *C, canManageOrgs bool) (*TmOrg, func()) { } } -// Creates a VDC (Region Quota) for testing in Tenant Manager and configures it with +// Creates a Region Quota for testing in Tenant Manager and configures it with // the first found VM class and the configured Storage Class. -func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*RegionQuota, func()) { +func createRegionQuota(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*RegionQuota, func()) { if vcd.config.Tm.StorageClass == "" { check.Fatal("testing configuration property 'tm.storageClass' is required") } @@ -310,17 +310,17 @@ func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*RegionQuota }, }}, } - vdc, err := vcd.client.CreateRegionQuota(cfg) + rq, err := vcd.client.CreateRegionQuota(cfg) check.Assert(err, IsNil) - check.Assert(vdc, NotNil) + check.Assert(rq, NotNil) - PrependToCleanupListOpenApi(vdc.TmVdc.ID, cfg.Name, types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+vdc.TmVdc.ID) + PrependToCleanupListOpenApi(rq.TmVdc.ID, cfg.Name, types.OpenApiPathVcf+types.OpenApiEndpointTmVdcs+rq.TmVdc.ID) - err = vdc.AssignVmClasses(&types.RegionVirtualMachineClasses{ + err = rq.AssignVmClasses(&types.RegionVirtualMachineClasses{ Values: types.OpenApiReferences{{Name: vmClasses[0].Name, ID: vmClasses[0].ID}}, }) check.Assert(err, IsNil) - _, err = vdc.CreateStoragePolicies(&types.VirtualDatacenterStoragePolicies{ + _, err = rq.CreateStoragePolicies(&types.VirtualDatacenterStoragePolicies{ Values: []types.VirtualDatacenterStoragePolicy{ { RegionStoragePolicy: types.OpenApiReference{ @@ -328,15 +328,15 @@ func createVdc(vcd *TestVCD, org *TmOrg, region *Region, check *C) (*RegionQuota }, StorageLimitMiB: 100, VirtualDatacenter: types.OpenApiReference{ - ID: vdc.TmVdc.ID, + ID: rq.TmVdc.ID, }, }, }, }) check.Assert(err, IsNil) - return vdc, func() { - err = vdc.Delete() + return rq, func() { + err = rq.Delete() check.Assert(err, IsNil) } } diff --git a/govcd/tm_content_library_test.go b/govcd/tm_content_library_test.go index 23d116ca7..972ef75fd 100644 --- a/govcd/tm_content_library_test.go +++ b/govcd/tm_content_library_test.go @@ -130,7 +130,7 @@ func (vcd *TestVCD) Test_ContentLibraryTenant(check *C) { defer orgCleanup() // A Region Quota is needed to have Storage classes available in the Organization - _, regionQuotaCleanup := createVdc(vcd, org, region, check) + _, regionQuotaCleanup := createRegionQuota(vcd, org, region, check) defer regionQuotaCleanup() cls, err := org.GetAllContentLibraries(nil) From 94f9be94ac51427088f20b180c9fd5c0766b10cb Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 12:16:19 +0100 Subject: [PATCH 16/25] self-review Signed-off-by: abarreiro --- govcd/tm_region_quota_storage_policy_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/govcd/tm_region_quota_storage_policy_test.go b/govcd/tm_region_quota_storage_policy_test.go index 2b93d5e07..bea1af058 100644 --- a/govcd/tm_region_quota_storage_policy_test.go +++ b/govcd/tm_region_quota_storage_policy_test.go @@ -120,6 +120,7 @@ func (vcd *TestVCD) Test_TmRegionQuotaStoragePolicy(check *C) { // Delete the policy err = policy.Delete() + // TODO: TM: Test with more storage policies when possible, right now the Region Quota always has 1 if len(rqPolicies) == 1 { // If there's only one policy, expect an error. There must be always one Storage Policy check.Assert(err, NotNil) From 12b2457498520a2f713349af6d579c462218e434 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 15:40:44 +0100 Subject: [PATCH 17/25] Bump API if VCFA Signed-off-by: abarreiro --- govcd/api_vcd.go | 1 + govcd/api_vcd_versions.go | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/govcd/api_vcd.go b/govcd/api_vcd.go index 53323a31b..03dac97da 100644 --- a/govcd/api_vcd.go +++ b/govcd/api_vcd.go @@ -30,6 +30,7 @@ func init() { } var minVcdApiVersion = "37.0" // supported by 10.4+ +var minVcfaApiVersion = "40.0" // VCDClientOption defines signature for customizing VCDClient using // functional options pattern. diff --git a/govcd/api_vcd_versions.go b/govcd/api_vcd_versions.go index 432aa735d..1113c3dd1 100644 --- a/govcd/api_vcd_versions.go +++ b/govcd/api_vcd_versions.go @@ -182,6 +182,7 @@ func (client *Client) vcdCheckSupportedVersion(version string) error { // Checks if there is at least one specified version matching the list returned by vCD. // Constraint format can be in format ">= 27.0, < 32",">= 30" ,"= 27.0". func (client *Client) checkSupportedVersionConstraint(versionConstraint string) error { + isVcfa := false for _, versionInfo := range client.supportedVersions.VersionInfos { versionMatch, err := client.apiVersionMatchesConstraint(versionInfo.Version, versionConstraint) if err != nil { @@ -191,6 +192,15 @@ func (client *Client) checkSupportedVersionConstraint(versionConstraint string) if versionMatch { return nil } + + if versionInfo.Version == minVcfaApiVersion { + isVcfa = true + } + } + // TODO: TM: Improve this as does not respect GOVCD_API_VERSION + if isVcfa { + client.APIVersion = minVcfaApiVersion + return nil } return fmt.Errorf("version %s is not supported", versionConstraint) } From 0853addf16dcf3fa63f0b2e17b38c275f32ccd43 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Tue, 11 Feb 2025 15:45:40 +0100 Subject: [PATCH 18/25] remove todo Signed-off-by: abarreiro --- govcd/nsxt_manager_openapi_test.go | 9 ++++----- govcd/tm_common_test.go | 9 ++++----- types/v56/openapi.go | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/govcd/nsxt_manager_openapi_test.go b/govcd/nsxt_manager_openapi_test.go index 19b22d3ca..33d0b8237 100644 --- a/govcd/nsxt_manager_openapi_test.go +++ b/govcd/nsxt_manager_openapi_test.go @@ -18,11 +18,10 @@ func (vcd *TestVCD) Test_NsxtManagerOpenApi(check *C) { } cfg := &types.NsxtManagerOpenApi{ - Name: check.TestName(), - Username: vcd.config.Tm.NsxtManagerUsername, - Password: vcd.config.Tm.NsxtManagerPassword, - Url: vcd.config.Tm.NsxtManagerUrl, - Description: check.TestName(), // TODO: TM: Latest build throws error if not populated + Name: check.TestName(), + Username: vcd.config.Tm.NsxtManagerUsername, + Password: vcd.config.Tm.NsxtManagerPassword, + Url: vcd.config.Tm.NsxtManagerUrl, } // Certificate must be trusted before adding NSX-T Manager diff --git a/govcd/tm_common_test.go b/govcd/tm_common_test.go index 28aa297c1..09961cc21 100644 --- a/govcd/tm_common_test.go +++ b/govcd/tm_common_test.go @@ -121,11 +121,10 @@ func getOrCreateNsxtManager(vcd *TestVCD, check *C) (*NsxtManagerOpenApi, func() printVerbose("# Will create NSX-T Manager %s\n", vcd.config.Tm.NsxtManagerUrl) nsxtCfg := &types.NsxtManagerOpenApi{ - Name: check.TestName(), - Username: vcd.config.Tm.NsxtManagerUsername, - Description: check.TestName(), // TODO: TM: Latest build throws SQL error if not populated - Password: vcd.config.Tm.NsxtManagerPassword, - Url: vcd.config.Tm.NsxtManagerUrl, + Name: check.TestName(), + Username: vcd.config.Tm.NsxtManagerUsername, + Password: vcd.config.Tm.NsxtManagerPassword, + Url: vcd.config.Tm.NsxtManagerUrl, } // Certificate must be trusted before adding NSX-T Manager url, err := url.Parse(nsxtCfg.Url) diff --git a/types/v56/openapi.go b/types/v56/openapi.go index 6ba7d4f61..9ebbe0334 100644 --- a/types/v56/openapi.go +++ b/types/v56/openapi.go @@ -859,7 +859,7 @@ type NsxtManagerOpenApi struct { // Name of NSX-T Manager Name string `json:"name"` // Description of NSX-T Manager - Description string `json:"description,omitempty"` + Description string `json:"description"` // This one is documented as optional (omitempty), but it is mandatory (it fails if not sent) // Username for authenticating to NSX-T Manager Username string `json:"username"` // Password for authenticating to NSX-T Manager From 404ffbdbdb3a2ab4b4807e1830654d299db22b97 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 10:20:57 +0100 Subject: [PATCH 19/25] # Signed-off-by: abarreiro --- govcd/api_vcd.go | 25 +++++++++++++++---------- govcd/api_vcd_versions.go | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/govcd/api_vcd.go b/govcd/api_vcd.go index 03dac97da..ad52a5b7f 100644 --- a/govcd/api_vcd.go +++ b/govcd/api_vcd.go @@ -141,16 +141,7 @@ func (vcdClient *VCDClient) vcdCloudApiAuthorize(user, pass, org string) (*http. // NewVCDClient initializes VMware VMware Cloud Director client with reasonable defaults. // It accepts functions of type VCDClientOption for adjusting defaults. func NewVCDClient(vcdEndpoint url.URL, insecure bool, options ...VCDClientOption) *VCDClient { - userDefinedApiVersion := os.Getenv("GOVCD_API_VERSION") - if userDefinedApiVersion != "" { - _, err := semver.NewVersion(userDefinedApiVersion) - if err != nil { - // We do not have error in return of this function signature. - // To avoid breaking API the only thing we can do is panic. - panic(fmt.Sprintf("unable to initialize VCD client from environment variable GOVCD_API_VERSION. Version '%s' is not valid: %s", userDefinedApiVersion, err)) - } - minVcdApiVersion = userDefinedApiVersion - } + overrideApiVersion() // Setting defaults // #nosec G402 -- InsecureSkipVerify: insecure - This allows connecting to VCDs with self-signed certificates @@ -193,6 +184,20 @@ func NewVCDClient(vcdEndpoint url.URL, insecure bool, options ...VCDClientOption return vcdClient } +func overrideApiVersion() { + userDefinedApiVersion := os.Getenv("GOVCD_API_VERSION") + if userDefinedApiVersion != "" { + _, err := semver.NewVersion(userDefinedApiVersion) + if err != nil { + // We do not have error in return of this function signature. + // To avoid breaking API the only thing we can do is panic. + panic(fmt.Sprintf("unable to initialize VCD client from environment variable GOVCD_API_VERSION. Version '%s' is not valid: %s", userDefinedApiVersion, err)) + } + minVcdApiVersion = userDefinedApiVersion + minVcfaApiVersion = userDefinedApiVersion + } +} + // Authenticate is a helper function that performs a login in VMware Cloud Director. func (vcdClient *VCDClient) Authenticate(username, password, org string) error { _, err := vcdClient.GetAuthResponse(username, password, org) diff --git a/govcd/api_vcd_versions.go b/govcd/api_vcd_versions.go index 1113c3dd1..ec1f3b921 100644 --- a/govcd/api_vcd_versions.go +++ b/govcd/api_vcd_versions.go @@ -197,8 +197,8 @@ func (client *Client) checkSupportedVersionConstraint(versionConstraint string) isVcfa = true } } - // TODO: TM: Improve this as does not respect GOVCD_API_VERSION if isVcfa { + overrideApiVersion() client.APIVersion = minVcfaApiVersion return nil } From deb284708f5e04ab39fd7e18422be4052cfc4dc1 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 10:22:10 +0100 Subject: [PATCH 20/25] # Signed-off-by: abarreiro --- govcd/api_vcd_versions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/govcd/api_vcd_versions.go b/govcd/api_vcd_versions.go index ec1f3b921..43372ccd5 100644 --- a/govcd/api_vcd_versions.go +++ b/govcd/api_vcd_versions.go @@ -197,6 +197,7 @@ func (client *Client) checkSupportedVersionConstraint(versionConstraint string) isVcfa = true } } + // TODO: TM: Improve this as feels odd and out of place if isVcfa { overrideApiVersion() client.APIVersion = minVcfaApiVersion From 1ceae96df84d918f121e7a1abca4790f0af48c58 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 10:24:27 +0100 Subject: [PATCH 21/25] # Signed-off-by: abarreiro --- govcd/api_vcd_versions.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/govcd/api_vcd_versions.go b/govcd/api_vcd_versions.go index 43372ccd5..5f0b10518 100644 --- a/govcd/api_vcd_versions.go +++ b/govcd/api_vcd_versions.go @@ -193,8 +193,9 @@ func (client *Client) checkSupportedVersionConstraint(versionConstraint string) return nil } - if versionInfo.Version == minVcfaApiVersion { - isVcfa = true + isVcfa, err = client.apiVersionMatchesConstraint(versionInfo.Version, ">= 40.0") + if err != nil { + return fmt.Errorf("cannot match VCFA version: %s", err) } } // TODO: TM: Improve this as feels odd and out of place From c86489068a2ab06b5b895f6da32f4765420fafbd Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 10:25:45 +0100 Subject: [PATCH 22/25] # Signed-off-by: abarreiro --- govcd/api_vcd_versions.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/govcd/api_vcd_versions.go b/govcd/api_vcd_versions.go index 5f0b10518..11060df6c 100644 --- a/govcd/api_vcd_versions.go +++ b/govcd/api_vcd_versions.go @@ -193,16 +193,16 @@ func (client *Client) checkSupportedVersionConstraint(versionConstraint string) return nil } + // TODO: TM: Improve this as feels odd and out of place isVcfa, err = client.apiVersionMatchesConstraint(versionInfo.Version, ">= 40.0") if err != nil { return fmt.Errorf("cannot match VCFA version: %s", err) } - } - // TODO: TM: Improve this as feels odd and out of place - if isVcfa { - overrideApiVersion() - client.APIVersion = minVcfaApiVersion - return nil + if isVcfa { + overrideApiVersion() + client.APIVersion = minVcfaApiVersion + return nil + } } return fmt.Errorf("version %s is not supported", versionConstraint) } From fc2ee8a84091cf1d1855d165fbf6208e925b8211 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 11:34:03 +0100 Subject: [PATCH 23/25] Refactor Signed-off-by: abarreiro --- govcd/api_vcd.go | 9 ++++----- govcd/api_vcd_versions.go | 4 ++-- govcd/openapi_endpoints_unit_test.go | 10 +++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/govcd/api_vcd.go b/govcd/api_vcd.go index ad52a5b7f..69e8cee42 100644 --- a/govcd/api_vcd.go +++ b/govcd/api_vcd.go @@ -29,8 +29,8 @@ func init() { requestCounter = &counter } -var minVcdApiVersion = "37.0" // supported by 10.4+ -var minVcfaApiVersion = "40.0" +var minApiVersion = "37.0" // supported by 10.4+ +const minVcfaApiVersion = "40.0" // Minimum version for VCFA // VCDClientOption defines signature for customizing VCDClient using // functional options pattern. @@ -147,7 +147,7 @@ func NewVCDClient(vcdEndpoint url.URL, insecure bool, options ...VCDClientOption // #nosec G402 -- InsecureSkipVerify: insecure - This allows connecting to VCDs with self-signed certificates vcdClient := &VCDClient{ Client: Client{ - APIVersion: minVcdApiVersion, + APIVersion: minApiVersion, // UserAgent cannot embed exact version by default because this is source code and is supposed to be used by programs, // but any client can customize or disable it at all using WithHttpUserAgent() configuration options function. UserAgent: "go-vcloud-director", @@ -193,8 +193,7 @@ func overrideApiVersion() { // To avoid breaking API the only thing we can do is panic. panic(fmt.Sprintf("unable to initialize VCD client from environment variable GOVCD_API_VERSION. Version '%s' is not valid: %s", userDefinedApiVersion, err)) } - minVcdApiVersion = userDefinedApiVersion - minVcfaApiVersion = userDefinedApiVersion + minApiVersion = userDefinedApiVersion } } diff --git a/govcd/api_vcd_versions.go b/govcd/api_vcd_versions.go index 11060df6c..5f1627d28 100644 --- a/govcd/api_vcd_versions.go +++ b/govcd/api_vcd_versions.go @@ -194,13 +194,13 @@ func (client *Client) checkSupportedVersionConstraint(versionConstraint string) } // TODO: TM: Improve this as feels odd and out of place - isVcfa, err = client.apiVersionMatchesConstraint(versionInfo.Version, ">= 40.0") + isVcfa, err = client.apiVersionMatchesConstraint(versionInfo.Version, fmt.Sprintf(">= %s", minVcfaApiVersion)) if err != nil { return fmt.Errorf("cannot match VCFA version: %s", err) } if isVcfa { - overrideApiVersion() client.APIVersion = minVcfaApiVersion + overrideApiVersion() return nil } } diff --git a/govcd/openapi_endpoints_unit_test.go b/govcd/openapi_endpoints_unit_test.go index 132560a8f..551e4eb0b 100644 --- a/govcd/openapi_endpoints_unit_test.go +++ b/govcd/openapi_endpoints_unit_test.go @@ -18,9 +18,9 @@ import ( // * Automatically generated tests where available VCD version does not satisfy it // * Automatically generated tests to check if each elevated API version is returned for endpoints that have it defined func TestClient_getOpenApiHighestElevatedVersion(t *testing.T) { - semverMinVcdApiVersion, err := semver.NewSemver(minVcdApiVersion) + semverMinVcdApiVersion, err := semver.NewSemver(minApiVersion) if err != nil { - t.Fatalf("error parsing 'minVcdApiVersion': %s", err) + t.Fatalf("error parsing 'minApiVersion': %s", err) } type testCase struct { @@ -30,7 +30,7 @@ func TestClient_getOpenApiHighestElevatedVersion(t *testing.T) { wantVersion string wantErr bool // overrideClientMinApiVersion is an option to override default expected version that is - // defined in global variable`minVcdApiVersion` + // defined in global variable`minApiVersion` overrideClientMinApiVersion string } @@ -64,7 +64,7 @@ func TestClient_getOpenApiHighestElevatedVersion(t *testing.T) { name: "VCD_version_higher_than_elevated_version_entries", supportedVersions: renderSupportedVersions([]string{"37.0", "37.1", "37.2", "37.3", "38.0", "38.1", "39.0"}), endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups, - wantVersion: minVcdApiVersion, + wantVersion: minApiVersion, wantErr: false, }, } @@ -165,7 +165,7 @@ func TestClient_getOpenApiHighestElevatedVersion(t *testing.T) { t.Run(tt.name, func(t *testing.T) { client := &Client{ supportedVersions: tt.supportedVersions, - APIVersion: minVcdApiVersion, + APIVersion: minApiVersion, } if tt.overrideClientMinApiVersion != "" { From f3874d45089f0bb32d1188efde28d1384c876b5d Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 12:03:54 +0100 Subject: [PATCH 24/25] Fix pagesize Signed-off-by: abarreiro --- govcd/tm_regional_networking_settings.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/govcd/tm_regional_networking_settings.go b/govcd/tm_regional_networking_settings.go index 0df660c45..bd2e2dd54 100644 --- a/govcd/tm_regional_networking_settings.go +++ b/govcd/tm_regional_networking_settings.go @@ -49,10 +49,12 @@ func (vcdClient *VCDClient) CreateTmRegionalNetworkingSettingAsync(config *types // GetAllTmRegionalNetworkingSettings retrieves all Regional Networking Settings with an optional filter func (vcdClient *VCDClient) GetAllTmRegionalNetworkingSettings(queryParameters url.Values) ([]*TmRegionalNetworkingSetting, error) { + queryparams := copyOrNewUrlValues(queryParameters) + queryparams.Set("pageSize", "32") c := crudConfig{ entityLabel: labelTmRegionalNetworkingSetting, endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmRegionalNetworkingSettings, - queryParameters: queryParameters, + queryParameters: queryparams, requiresTm: true, } From 90b366a54914e8b431024b910d1ed74e3a640bd5 Mon Sep 17 00:00:00 2001 From: abarreiro Date: Wed, 12 Feb 2025 12:42:26 +0100 Subject: [PATCH 25/25] Fix task Signed-off-by: abarreiro --- govcd/task.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/govcd/task.go b/govcd/task.go index a15c558a0..b82719e5a 100644 --- a/govcd/task.go +++ b/govcd/task.go @@ -59,6 +59,18 @@ func (task *Task) Refresh() error { return fmt.Errorf("cannot refresh, Object is empty") } + // TODO: TM: There's a bug where VCFA returns local K8s service hostname instead of public VCFA url, + // like https://xxxxxxx.svc.cluster.local/api/task/1f344a7a-cdb0-435c-82f6-c47fb4847798 + if strings.Contains(task.Task.HREF, "svc.cluster.local") { + util.Logger.Printf("[WARN] Caught task with malformed HREF: %s", task.Task.HREF) + fixedTaskUrl, err := url.ParseRequestURI(task.Task.HREF) + if err != nil { + return fmt.Errorf("error parsing task href: %s", err) + } + fixedTaskUrl.Host = task.client.VCDHREF.Host + task.Task.HREF = fixedTaskUrl.String() + } + refreshUrl := urlParseRequestURI(task.Task.HREF) req := task.client.NewRequest(map[string]string{}, http.MethodGet, *refreshUrl, nil)