From d05517b2b2c8c101678e94ab001e64890853db28 Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Tue, 25 Aug 2020 08:55:53 +0300 Subject: [PATCH 1/8] add main implementation --- govcd/api.go | 5 ++ govcd/api_vcd_test.go | 22 +++++ govcd/openapi_endpoints.go | 3 +- govcd/vdcComputePolicy.go | 150 +++++++++++++++++++++++++++++++++ govcd/vdcComputePolicy_test.go | 104 +++++++++++++++++++++++ types/v56/constants.go | 5 +- types/v56/openapi.go | 41 +++++++++ 7 files changed, 327 insertions(+), 3 deletions(-) create mode 100644 govcd/vdcComputePolicy.go create mode 100644 govcd/vdcComputePolicy_test.go diff --git a/govcd/api.go b/govcd/api.go index 5b1c8b61f..050a63f54 100644 --- a/govcd/api.go +++ b/govcd/api.go @@ -636,3 +636,8 @@ func takeIntAddress(x int) *int { func takeStringPointer(x string) *string { return &x } + +// takeFloatAddress is a helper that returns the address of an `float64` +func takeFloatAddress(x float64) *float64 { + return &x +} diff --git a/govcd/api_vcd_test.go b/govcd/api_vcd_test.go index 004f80dd2..44e289316 100644 --- a/govcd/api_vcd_test.go +++ b/govcd/api_vcd_test.go @@ -1302,6 +1302,28 @@ func (vcd *TestVCD) removeLeftoverEntities(entity CleanupEntity) { } vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy) return + case "vcdComputePolicy": + if entity.Parent == "" { + vcd.infoCleanup("removeLeftoverEntries: [ERROR] No ORG provided for vcdComputePolicy '%s'\n", entity.Name) + return + } + org, err := vcd.client.GetAdminOrgByName(entity.Parent) + if err != nil { + vcd.infoCleanup(notFoundMsg, "org", entity.Parent) + return + } + policy, err := org.GetVdcComputePolicyById(entity.Name) + if policy == nil || err != nil { + vcd.infoCleanup(notFoundMsg, "vcdComputePolicy", entity.Name) + return + } + err = policy.Delete() + if err == nil { + vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy) + } else { + vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err) + } + return default: // If we reach this point, we are trying to clean up an entity that diff --git a/govcd/openapi_endpoints.go b/govcd/openapi_endpoints.go index c546fcac6..5005722c6 100644 --- a/govcd/openapi_endpoints.go +++ b/govcd/openapi_endpoints.go @@ -11,7 +11,8 @@ import ( // endpointMinApiVersions holds mapping of OpenAPI endpoints and API versions they were introduced in. var endpointMinApiVersions = map[string]string{ - types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRoles: "31.0", + types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRoles: "31.0", + types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies: "32.0", } // checkOpenApiEndpointCompatibility checks if VCD version (to which the client is connected) is sufficient to work with diff --git a/govcd/vdcComputePolicy.go b/govcd/vdcComputePolicy.go new file mode 100644 index 000000000..8f67ddd35 --- /dev/null +++ b/govcd/vdcComputePolicy.go @@ -0,0 +1,150 @@ +package govcd + +import ( + "fmt" + "net/url" + + "github.com/vmware/go-vcloud-director/v2/types/v56" +) + +type VdcComputePolicy struct { + VdcComputePolicy *types.VdcComputePolicy + client *Client +} + +// GetVdcComputePolicyById retrieves VDC compute policy by given ID +func (org *AdminOrg) GetVdcComputePolicyById(id string) (*VdcComputePolicy, error) { + endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies + minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint) + if err != nil { + return nil, err + } + + if id == "" { + return nil, fmt.Errorf("empty VDC id") + } + + urlRef, err := org.client.OpenApiBuildEndpoint(endpoint, id) + + if err != nil { + return nil, err + } + + vdcComputePolicy := &VdcComputePolicy{ + VdcComputePolicy: &types.VdcComputePolicy{}, + client: org.client, + } + + err = org.client.OpenApiGetItem(minimumApiVersion, urlRef, nil, vdcComputePolicy.VdcComputePolicy) + if err != nil { + return nil, err + } + + return vdcComputePolicy, nil +} + +// GetAllVdcComputePolicies retrieves all VDC compute policies using OpenAPI endpoint. Query parameters can be supplied to perform additional +// filtering +func (org *AdminOrg) GetAllVdcComputePolicies(queryParameters url.Values) ([]*types.VdcComputePolicy, error) { + endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies + minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint) + if err != nil { + return nil, err + } + + urlRef, err := org.client.OpenApiBuildEndpoint(endpoint) + if err != nil { + return nil, err + } + + responses := []*types.VdcComputePolicy{{}} + + err = org.client.OpenApiGetAllItems(minimumApiVersion, urlRef, queryParameters, &responses) + if err != nil { + return nil, err + } + + return responses, nil +} + +// Create creates a new VDC Compute Policy using OpenAPI endpoint +func (org *AdminOrg) CreateVdcComputePolicy(newVdcComputePolicy *types.VdcComputePolicy) (*VdcComputePolicy, error) { + endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies + minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint) + if err != nil { + return nil, err + } + + urlRef, err := org.client.OpenApiBuildEndpoint(endpoint) + if err != nil { + return nil, err + } + + returnVdcComputePolicy := &VdcComputePolicy{ + VdcComputePolicy: &types.VdcComputePolicy{}, + client: org.client, + } + + err = org.client.OpenApiPostItem(minimumApiVersion, urlRef, nil, newVdcComputePolicy, returnVdcComputePolicy.VdcComputePolicy) + if err != nil { + return nil, fmt.Errorf("error creating VDC compute policy: %s", err) + } + + return returnVdcComputePolicy, nil +} + +// Update updates existing VDC compute policy +func (vdcComputePolicy *VdcComputePolicy) Update() (*VdcComputePolicy, error) { + endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies + minimumApiVersion, err := vdcComputePolicy.client.checkOpenApiEndpointCompatibility(endpoint) + if err != nil { + return nil, err + } + + if vdcComputePolicy.VdcComputePolicy.ID == "" { + return nil, fmt.Errorf("cannot update VDC compute policy without id") + } + + urlRef, err := vdcComputePolicy.client.OpenApiBuildEndpoint(endpoint, vdcComputePolicy.VdcComputePolicy.ID) + if err != nil { + return nil, err + } + + returnVdcComputePolicy := &VdcComputePolicy{ + VdcComputePolicy: &types.VdcComputePolicy{}, + client: vdcComputePolicy.client, + } + + err = vdcComputePolicy.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, vdcComputePolicy.VdcComputePolicy, returnVdcComputePolicy.VdcComputePolicy) + if err != nil { + return nil, fmt.Errorf("error updating VDC compute policy: %s", err) + } + + return returnVdcComputePolicy, nil +} + +// Delete deletes VDC compute policy +func (vdcComputePolicy *VdcComputePolicy) Delete() error { + endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies + minimumApiVersion, err := vdcComputePolicy.client.checkOpenApiEndpointCompatibility(endpoint) + if err != nil { + return err + } + + if vdcComputePolicy.VdcComputePolicy.ID == "" { + return fmt.Errorf("cannot delete VDC compute policy without id") + } + + urlRef, err := vdcComputePolicy.client.OpenApiBuildEndpoint(endpoint, vdcComputePolicy.VdcComputePolicy.ID) + if err != nil { + return err + } + + err = vdcComputePolicy.client.OpenApiDeleteItem(minimumApiVersion, urlRef, nil) + + if err != nil { + return fmt.Errorf("error deleting VDC compute policy: %s", err) + } + + return nil +} diff --git a/govcd/vdcComputePolicy_test.go b/govcd/vdcComputePolicy_test.go new file mode 100644 index 000000000..fca8e2a05 --- /dev/null +++ b/govcd/vdcComputePolicy_test.go @@ -0,0 +1,104 @@ +// +build functional openapi ALL + +package govcd + +import ( + "net/url" + + "github.com/vmware/go-vcloud-director/v2/types/v56" + . "gopkg.in/check.v1" +) + +func (vcd *TestVCD) Test_VdcComputePolicies(check *C) { + org, err := vcd.client.GetAdminOrgByName(vcd.org.Org.Name) + check.Assert(err, IsNil) + check.Assert(org, NotNil) + + // Step 1 - Create a new VDC compute policies + newComputePolicy := &VdcComputePolicy{ + client: org.client, + VdcComputePolicy: &types.VdcComputePolicy{ + Name: check.TestName() + "_empty", + Description: "Empty policy created by test", + }, + } + + createdPolicy, err := org.CreateVdcComputePolicy(newComputePolicy.VdcComputePolicy) + check.Assert(err, IsNil) + check.Assert(createdPolicy.VdcComputePolicy.Name, Equals, newComputePolicy.VdcComputePolicy.Name) + check.Assert(createdPolicy.VdcComputePolicy.Description, Equals, newComputePolicy.VdcComputePolicy.Description) + + AddToCleanupList(createdPolicy.VdcComputePolicy.ID, "vcdComputePolicy", vcd.org.Org.Name, "Test_VdcComputePolicies") + + newComputePolicy2 := &VdcComputePolicy{ + client: org.client, + VdcComputePolicy: &types.VdcComputePolicy{ + Name: check.TestName(), + Description: "Not Empty policy created by test", + CPUSpeed: takeIntAddress(100), + CPUCount: takeIntAddress(2), + CoresPerSocket: takeIntAddress(1), + CPUReservationGuarantee: takeFloatAddress(0.26), + CPULimit: takeIntAddress(200), + CPUShares: takeIntAddress(5), + Memory: takeIntAddress(1600), + MemoryReservationGuarantee: takeFloatAddress(0.5), + MemoryLimit: takeIntAddress(1200), + MemoryShares: takeIntAddress(500), + }, + } + + createdPolicy2, err := org.CreateVdcComputePolicy(newComputePolicy2.VdcComputePolicy) + check.Assert(err, IsNil) + check.Assert(createdPolicy2.VdcComputePolicy.Name, Equals, newComputePolicy2.VdcComputePolicy.Name) + check.Assert(createdPolicy2.VdcComputePolicy.Description, Equals, newComputePolicy2.VdcComputePolicy.Description) + + AddToCleanupList(createdPolicy2.VdcComputePolicy.ID, "vcdComputePolicy", vcd.org.Org.Name, "Test_VdcComputePolicies") + // Step 2 - update + createdPolicy2.VdcComputePolicy.Description = "Updated description" + updatedPolicy, err := createdPolicy2.Update() + check.Assert(err, IsNil) + check.Assert(updatedPolicy.VdcComputePolicy, DeepEquals, createdPolicy2.VdcComputePolicy) + + // Step 3 - Get all VDC compute policies + allExistingPolicies, err := org.GetAllVdcComputePolicies(nil) + check.Assert(err, IsNil) + check.Assert(allExistingPolicies, NotNil) + + // Step 4 - Get all VDC compute policies using query filters + for _, onePolicy := range allExistingPolicies { + + // Step 3.1 - retrieve using FIQL filter + queryParams := url.Values{} + queryParams.Add("filter", "id=="+onePolicy.ID) + + expectOnePolicyResultById, err := org.GetAllVdcComputePolicies(queryParams) + check.Assert(err, IsNil) + check.Assert(len(expectOnePolicyResultById) == 1, Equals, true) + + // Step 2.2 - retrieve + exactItem, err := org.GetVdcComputePolicyById(onePolicy.ID) + check.Assert(err, IsNil) + + check.Assert(err, IsNil) + check.Assert(exactItem, NotNil) + + // Step 2.3 - compare struct retrieved by using filter and the one retrieved by exact ID + check.Assert(onePolicy, DeepEquals, expectOnePolicyResultById[0]) + + } + + // Step 5 - delete + err = createdPolicy.Delete() + check.Assert(err, IsNil) + // Step 5 - try to read deleted VDC computed policy should end up with error 'ErrorEntityNotFound' + deletedPolicy, err := org.GetVdcComputePolicyById(createdPolicy.VdcComputePolicy.ID) + check.Assert(ContainsNotFound(err), Equals, true) + check.Assert(deletedPolicy, IsNil) + + err = createdPolicy2.Delete() + check.Assert(err, IsNil) + deletedPolicy2, err := org.GetVdcComputePolicyById(createdPolicy2.VdcComputePolicy.ID) + check.Assert(ContainsNotFound(err), Equals, true) + check.Assert(deletedPolicy2, IsNil) +} diff --git a/types/v56/constants.go b/types/v56/constants.go index be46e9db5..124608a72 100644 --- a/types/v56/constants.go +++ b/types/v56/constants.go @@ -296,6 +296,7 @@ const ( // These constants allow to construct OpenAPI endpoint paths and avoid strings in code for easy replacement in future. const ( - OpenApiPathVersion1_0_0 = "1.0.0/" - OpenApiEndpointRoles = "roles/" + OpenApiPathVersion1_0_0 = "1.0.0/" + OpenApiEndpointRoles = "roles/" + OpenApiEndpointVdcComputePolicies = "vdcComputePolicies/" ) diff --git a/types/v56/openapi.go b/types/v56/openapi.go index 33c7ce13e..5f90a18ec 100644 --- a/types/v56/openapi.go +++ b/types/v56/openapi.go @@ -50,3 +50,44 @@ type Role struct { BundleKey string `json:"bundleKey"` ReadOnly bool `json:"readOnly"` } + +type VdcComputePolicy struct { + ID string `json:"id,omitempty"` + Description string `json:"description,omitempty"` + Name string `json:"name"` + CPUSpeed *int `json:"cpuSpeed,omitempty"` + Memory *int `json:"memory,omitempty"` + CPUCount *int `json:"cpuCount,omitempty"` + CoresPerSocket *int `json:"coresPerSocket,omitempty"` + MemoryReservationGuarantee *float64 `json:"memoryReservationGuarantee,omitempty"` + CPUReservationGuarantee *float64 `json:"cpuReservationGuarantee,omitempty"` + CPULimit *int `json:"cpuLimit,omitempty"` + MemoryLimit *int `json:"memoryLimit,omitempty"` + CPUShares *int `json:"cpuShares,omitempty"` + MemoryShares *int `json:"memoryShares,omitempty"` + ExtraConfigs *struct { + AdditionalProp1 string `json:"additionalProp1,omitempty"` + AdditionalProp2 string `json:"additionalProp2,omitempty"` + AdditionalProp3 string `json:"additionalProp3,omitempty"` + } `json:"extraConfigs,omitempty"` + PvdcComputePolicyRef *struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + } `json:"pvdcComputePolicyRef,omitempty"` + PvdcComputePolicy *struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + } `json:"pvdcComputePolicy,omitempty"` + CompatibleVdcTypes []string `json:"compatibleVdcTypes,omitempty"` + IsSizingOnly bool `json:"isSizingOnly,omitempty"` + PvdcID string `json:"pvdcId,omitempty"` + NamedVMGroups [][]struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + } `json:"namedVmGroups,omitempty"` + LogicalVMGroupReferences []struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + } `json:"logicalVmGroupReferences,omitempty"` + IsAutoGenerated bool `json:"isAutoGenerated,omitempty"` +} From 808752b648f7ff312c106a60abf34463ef916cc0 Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Thu, 29 Oct 2020 11:55:44 +0200 Subject: [PATCH 2/8] removed not needed after merge --- govcd/vdcComputePolicy.go | 150 --------------------------------- govcd/vdcComputePolicy_test.go | 104 ----------------------- 2 files changed, 254 deletions(-) delete mode 100644 govcd/vdcComputePolicy.go delete mode 100644 govcd/vdcComputePolicy_test.go diff --git a/govcd/vdcComputePolicy.go b/govcd/vdcComputePolicy.go deleted file mode 100644 index 8f67ddd35..000000000 --- a/govcd/vdcComputePolicy.go +++ /dev/null @@ -1,150 +0,0 @@ -package govcd - -import ( - "fmt" - "net/url" - - "github.com/vmware/go-vcloud-director/v2/types/v56" -) - -type VdcComputePolicy struct { - VdcComputePolicy *types.VdcComputePolicy - client *Client -} - -// GetVdcComputePolicyById retrieves VDC compute policy by given ID -func (org *AdminOrg) GetVdcComputePolicyById(id string) (*VdcComputePolicy, error) { - endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies - minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint) - if err != nil { - return nil, err - } - - if id == "" { - return nil, fmt.Errorf("empty VDC id") - } - - urlRef, err := org.client.OpenApiBuildEndpoint(endpoint, id) - - if err != nil { - return nil, err - } - - vdcComputePolicy := &VdcComputePolicy{ - VdcComputePolicy: &types.VdcComputePolicy{}, - client: org.client, - } - - err = org.client.OpenApiGetItem(minimumApiVersion, urlRef, nil, vdcComputePolicy.VdcComputePolicy) - if err != nil { - return nil, err - } - - return vdcComputePolicy, nil -} - -// GetAllVdcComputePolicies retrieves all VDC compute policies using OpenAPI endpoint. Query parameters can be supplied to perform additional -// filtering -func (org *AdminOrg) GetAllVdcComputePolicies(queryParameters url.Values) ([]*types.VdcComputePolicy, error) { - endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies - minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint) - if err != nil { - return nil, err - } - - urlRef, err := org.client.OpenApiBuildEndpoint(endpoint) - if err != nil { - return nil, err - } - - responses := []*types.VdcComputePolicy{{}} - - err = org.client.OpenApiGetAllItems(minimumApiVersion, urlRef, queryParameters, &responses) - if err != nil { - return nil, err - } - - return responses, nil -} - -// Create creates a new VDC Compute Policy using OpenAPI endpoint -func (org *AdminOrg) CreateVdcComputePolicy(newVdcComputePolicy *types.VdcComputePolicy) (*VdcComputePolicy, error) { - endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies - minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint) - if err != nil { - return nil, err - } - - urlRef, err := org.client.OpenApiBuildEndpoint(endpoint) - if err != nil { - return nil, err - } - - returnVdcComputePolicy := &VdcComputePolicy{ - VdcComputePolicy: &types.VdcComputePolicy{}, - client: org.client, - } - - err = org.client.OpenApiPostItem(minimumApiVersion, urlRef, nil, newVdcComputePolicy, returnVdcComputePolicy.VdcComputePolicy) - if err != nil { - return nil, fmt.Errorf("error creating VDC compute policy: %s", err) - } - - return returnVdcComputePolicy, nil -} - -// Update updates existing VDC compute policy -func (vdcComputePolicy *VdcComputePolicy) Update() (*VdcComputePolicy, error) { - endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies - minimumApiVersion, err := vdcComputePolicy.client.checkOpenApiEndpointCompatibility(endpoint) - if err != nil { - return nil, err - } - - if vdcComputePolicy.VdcComputePolicy.ID == "" { - return nil, fmt.Errorf("cannot update VDC compute policy without id") - } - - urlRef, err := vdcComputePolicy.client.OpenApiBuildEndpoint(endpoint, vdcComputePolicy.VdcComputePolicy.ID) - if err != nil { - return nil, err - } - - returnVdcComputePolicy := &VdcComputePolicy{ - VdcComputePolicy: &types.VdcComputePolicy{}, - client: vdcComputePolicy.client, - } - - err = vdcComputePolicy.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, vdcComputePolicy.VdcComputePolicy, returnVdcComputePolicy.VdcComputePolicy) - if err != nil { - return nil, fmt.Errorf("error updating VDC compute policy: %s", err) - } - - return returnVdcComputePolicy, nil -} - -// Delete deletes VDC compute policy -func (vdcComputePolicy *VdcComputePolicy) Delete() error { - endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies - minimumApiVersion, err := vdcComputePolicy.client.checkOpenApiEndpointCompatibility(endpoint) - if err != nil { - return err - } - - if vdcComputePolicy.VdcComputePolicy.ID == "" { - return fmt.Errorf("cannot delete VDC compute policy without id") - } - - urlRef, err := vdcComputePolicy.client.OpenApiBuildEndpoint(endpoint, vdcComputePolicy.VdcComputePolicy.ID) - if err != nil { - return err - } - - err = vdcComputePolicy.client.OpenApiDeleteItem(minimumApiVersion, urlRef, nil) - - if err != nil { - return fmt.Errorf("error deleting VDC compute policy: %s", err) - } - - return nil -} diff --git a/govcd/vdcComputePolicy_test.go b/govcd/vdcComputePolicy_test.go deleted file mode 100644 index fca8e2a05..000000000 --- a/govcd/vdcComputePolicy_test.go +++ /dev/null @@ -1,104 +0,0 @@ -// +build functional openapi ALL - -package govcd - -import ( - "net/url" - - "github.com/vmware/go-vcloud-director/v2/types/v56" - . "gopkg.in/check.v1" -) - -func (vcd *TestVCD) Test_VdcComputePolicies(check *C) { - org, err := vcd.client.GetAdminOrgByName(vcd.org.Org.Name) - check.Assert(err, IsNil) - check.Assert(org, NotNil) - - // Step 1 - Create a new VDC compute policies - newComputePolicy := &VdcComputePolicy{ - client: org.client, - VdcComputePolicy: &types.VdcComputePolicy{ - Name: check.TestName() + "_empty", - Description: "Empty policy created by test", - }, - } - - createdPolicy, err := org.CreateVdcComputePolicy(newComputePolicy.VdcComputePolicy) - check.Assert(err, IsNil) - check.Assert(createdPolicy.VdcComputePolicy.Name, Equals, newComputePolicy.VdcComputePolicy.Name) - check.Assert(createdPolicy.VdcComputePolicy.Description, Equals, newComputePolicy.VdcComputePolicy.Description) - - AddToCleanupList(createdPolicy.VdcComputePolicy.ID, "vcdComputePolicy", vcd.org.Org.Name, "Test_VdcComputePolicies") - - newComputePolicy2 := &VdcComputePolicy{ - client: org.client, - VdcComputePolicy: &types.VdcComputePolicy{ - Name: check.TestName(), - Description: "Not Empty policy created by test", - CPUSpeed: takeIntAddress(100), - CPUCount: takeIntAddress(2), - CoresPerSocket: takeIntAddress(1), - CPUReservationGuarantee: takeFloatAddress(0.26), - CPULimit: takeIntAddress(200), - CPUShares: takeIntAddress(5), - Memory: takeIntAddress(1600), - MemoryReservationGuarantee: takeFloatAddress(0.5), - MemoryLimit: takeIntAddress(1200), - MemoryShares: takeIntAddress(500), - }, - } - - createdPolicy2, err := org.CreateVdcComputePolicy(newComputePolicy2.VdcComputePolicy) - check.Assert(err, IsNil) - check.Assert(createdPolicy2.VdcComputePolicy.Name, Equals, newComputePolicy2.VdcComputePolicy.Name) - check.Assert(createdPolicy2.VdcComputePolicy.Description, Equals, newComputePolicy2.VdcComputePolicy.Description) - - AddToCleanupList(createdPolicy2.VdcComputePolicy.ID, "vcdComputePolicy", vcd.org.Org.Name, "Test_VdcComputePolicies") - // Step 2 - update - createdPolicy2.VdcComputePolicy.Description = "Updated description" - updatedPolicy, err := createdPolicy2.Update() - check.Assert(err, IsNil) - check.Assert(updatedPolicy.VdcComputePolicy, DeepEquals, createdPolicy2.VdcComputePolicy) - - // Step 3 - Get all VDC compute policies - allExistingPolicies, err := org.GetAllVdcComputePolicies(nil) - check.Assert(err, IsNil) - check.Assert(allExistingPolicies, NotNil) - - // Step 4 - Get all VDC compute policies using query filters - for _, onePolicy := range allExistingPolicies { - - // Step 3.1 - retrieve using FIQL filter - queryParams := url.Values{} - queryParams.Add("filter", "id=="+onePolicy.ID) - - expectOnePolicyResultById, err := org.GetAllVdcComputePolicies(queryParams) - check.Assert(err, IsNil) - check.Assert(len(expectOnePolicyResultById) == 1, Equals, true) - - // Step 2.2 - retrieve - exactItem, err := org.GetVdcComputePolicyById(onePolicy.ID) - check.Assert(err, IsNil) - - check.Assert(err, IsNil) - check.Assert(exactItem, NotNil) - - // Step 2.3 - compare struct retrieved by using filter and the one retrieved by exact ID - check.Assert(onePolicy, DeepEquals, expectOnePolicyResultById[0]) - - } - - // Step 5 - delete - err = createdPolicy.Delete() - check.Assert(err, IsNil) - // Step 5 - try to read deleted VDC computed policy should end up with error 'ErrorEntityNotFound' - deletedPolicy, err := org.GetVdcComputePolicyById(createdPolicy.VdcComputePolicy.ID) - check.Assert(ContainsNotFound(err), Equals, true) - check.Assert(deletedPolicy, IsNil) - - err = createdPolicy2.Delete() - check.Assert(err, IsNil) - deletedPolicy2, err := org.GetVdcComputePolicyById(createdPolicy2.VdcComputePolicy.ID) - check.Assert(ContainsNotFound(err), Equals, true) - check.Assert(deletedPolicy2, IsNil) -} From b612837972ae5bcabf1a8af5aad29a6a9d887a01 Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Wed, 2 Feb 2022 16:02:07 +0200 Subject: [PATCH 3/8] fix storage profile disablement for VDC --- govcd/adminvdc.go | 2 +- govcd/adminvdc_nsxt_test.go | 2 +- govcd/adminvdc_test.go | 38 ++++++++++++++++++++++++++++++++----- govcd/common_test.go | 2 +- govcd/org_test.go | 8 ++++---- govcd/vdc_group_test.go | 2 +- types/v56/types.go | 4 ++-- 7 files changed, 43 insertions(+), 15 deletions(-) diff --git a/govcd/adminvdc.go b/govcd/adminvdc.go index 5f58785bb..b8966f40b 100644 --- a/govcd/adminvdc.go +++ b/govcd/adminvdc.go @@ -483,7 +483,7 @@ func (vdc *AdminVdc) RemoveStorageProfile(storageProfileName string) (Task, erro if err != nil { return Task{}, fmt.Errorf("cannot retrieve VDC storage profile '%s' details: %s", storageProfileName, err) } - if vdcStorageProfileDetails.Enabled { + if *vdcStorageProfileDetails.Enabled { _, err = vdc.UpdateStorageProfile(extractUuid(storageProfile.HREF), &types.AdminVdcStorageProfile{ Name: vdcStorageProfileDetails.Name, Units: vdcStorageProfileDetails.Units, diff --git a/govcd/adminvdc_nsxt_test.go b/govcd/adminvdc_nsxt_test.go index e1311097f..87bd6f043 100644 --- a/govcd/adminvdc_nsxt_test.go +++ b/govcd/adminvdc_nsxt_test.go @@ -69,7 +69,7 @@ func (vcd *TestVCD) Test_CreateNsxtOrgVdc(check *C) { }, }, VdcStorageProfile: []*types.VdcStorageProfileConfiguration{&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: true, diff --git a/govcd/adminvdc_test.go b/govcd/adminvdc_test.go index 836a61e75..f061ebae7 100644 --- a/govcd/adminvdc_test.go +++ b/govcd/adminvdc_test.go @@ -41,11 +41,19 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) { providerVdcHref := getVdcProviderVdcHref(vcd, check) - storageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.ProviderVdc.StorageProfile, providerVdcHref) + storageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.StorageProfile.SP1, providerVdcHref) check.Assert(err, IsNil) - providerVdcStorageProfileHref := storageProfile.HREF + firstStorageProfileHref := storageProfile.HREF networkPoolHref := getVdcNetworkPoolHref(vcd, check) + secondStorageProfileHref := "" + // Make test more robust and tests additionally disabled storage profile + if vcd.config.VCD.StorageProfile.SP2 != "" { + storageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.StorageProfile.SP2, providerVdcHref) + check.Assert(err, IsNil) + secondStorageProfileHref = storageProfile.HREF + } + allocationModels := []string{"AllocationVApp", "AllocationPool", "ReservationPool", "Flex"} trueValue := true for i, allocationModel := range allocationModels { @@ -67,12 +75,12 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) { }, }, VdcStorageProfile: []*types.VdcStorageProfileConfiguration{&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: true, ProviderVdcStorageProfile: &types.Reference{ - HREF: providerVdcStorageProfileHref, + HREF: firstStorageProfileHref, }, }, }, @@ -92,6 +100,18 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) { vdcConfiguration.IncludeMemoryOverhead = &trueValue } + if secondStorageProfileHref != "" { + vdcConfiguration.VdcStorageProfile = append(vdcConfiguration.VdcStorageProfile, &types.VdcStorageProfileConfiguration{ + Enabled: takeBoolPointer(false), + Units: "MB", + Limit: 1024, + Default: false, + ProviderVdcStorageProfile: &types.Reference{ + HREF: secondStorageProfileHref, + }, + }) + } + vdc, _ := adminOrg.GetVDCByName(vdcConfiguration.Name, false) if vdc != nil { err = vdc.DeleteWait(true, true) @@ -108,8 +128,8 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) { vdcConfiguration.ComputeCapacity[0].Memory.Units = "MB" vdc, err = adminOrg.CreateOrgVdc(vdcConfiguration) - check.Assert(vdc, NotNil) check.Assert(err, IsNil) + check.Assert(vdc, NotNil) AddToCleanupList(vdcConfiguration.Name, "vdc", vcd.org.Org.Name, "Test_CreateVdcWithFlex") @@ -119,6 +139,14 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) { check.Assert(vdc.Vdc.Name, Equals, vdcConfiguration.Name) check.Assert(vdc.Vdc.IsEnabled, Equals, vdcConfiguration.IsEnabled) check.Assert(vdc.Vdc.AllocationModel, Equals, vdcConfiguration.AllocationModel) + if secondStorageProfileHref != "" { + check.Assert(vdc.Vdc.VdcStorageProfiles, NotNil) + check.Assert(vdc.Vdc.VdcStorageProfiles.VdcStorageProfile, NotNil) + check.Assert(vdc.Vdc.VdcStorageProfiles.VdcStorageProfile[1], NotNil) + } + + vdcStorageProfileDetails, err := adminOrg.client.GetStorageProfileByHref(vdc.Vdc.VdcStorageProfiles.VdcStorageProfile[1].HREF) + check.Assert(*vdcStorageProfileDetails.Enabled, Equals, false) err = vdc.DeleteWait(true, true) check.Assert(err, IsNil) diff --git a/govcd/common_test.go b/govcd/common_test.go index 035bad0bc..55d4d54c2 100644 --- a/govcd/common_test.go +++ b/govcd/common_test.go @@ -764,7 +764,7 @@ func spawnTestVdc(vcd *TestVCD, check *C, adminOrgName string) *Vdc { }, }, VdcStorageProfile: []*types.VdcStorageProfileConfiguration{&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: true, diff --git a/govcd/org_test.go b/govcd/org_test.go index 83f7776fa..6a03ef1ff 100644 --- a/govcd/org_test.go +++ b/govcd/org_test.go @@ -282,7 +282,7 @@ func (vcd *TestVCD) Test_CreateVdc(check *C) { }, }, VdcStorageProfile: []*types.VdcStorageProfileConfiguration{&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: true, @@ -651,7 +651,7 @@ func setupVdc(vcd *TestVCD, check *C, allocationModel string) (AdminOrg, *types. }, }, VdcStorageProfile: []*types.VdcStorageProfileConfiguration{&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: true, @@ -822,7 +822,7 @@ func (vcd *TestVCD) Test_AddRemoveVdcStorageProfiles(check *C) { // Add another storage profile err = adminVdc.AddStorageProfileWait(&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: false, @@ -846,7 +846,7 @@ func (vcd *TestVCD) Test_AddRemoveVdcStorageProfiles(check *C) { // Add the second storage profile again err = adminVdc.AddStorageProfileWait(&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: false, diff --git a/govcd/vdc_group_test.go b/govcd/vdc_group_test.go index a8cb8b97d..44fc74d71 100644 --- a/govcd/vdc_group_test.go +++ b/govcd/vdc_group_test.go @@ -128,7 +128,7 @@ func createNewVdc(vcd *TestVCD, check *C, vdcName string) *Vdc { }, }, VdcStorageProfile: []*types.VdcStorageProfileConfiguration{&types.VdcStorageProfileConfiguration{ - Enabled: true, + Enabled: takeBoolPointer(true), Units: "MB", Limit: 1024, Default: true, diff --git a/types/v56/types.go b/types/v56/types.go index a75ae4fa5..dd5d868ef 100644 --- a/types/v56/types.go +++ b/types/v56/types.go @@ -470,7 +470,7 @@ type AdminVdc struct { // Since: 5.1 // https://code.vmware.com/apis/220/vcloud#/doc/doc/types/VdcStorageProfileParamsType.html type VdcStorageProfileConfiguration struct { - Enabled bool `xml:"Enabled,omitempty"` + Enabled *bool `xml:"Enabled,omitempty"` Units string `xml:"Units"` Limit int64 `xml:"Limit"` Default bool `xml:"Default"` @@ -485,7 +485,7 @@ type VdcStorageProfileConfiguration struct { type VdcStorageProfile struct { Xmlns string `xml:"xmlns,attr"` Name string `xml:"name,attr"` - Enabled bool `xml:"Enabled,omitempty"` + Enabled *bool `xml:"Enabled,omitempty"` Units string `xml:"Units"` Limit int64 `xml:"Limit"` Default bool `xml:"Default"` From d1e125d3f3472d6f4cebafca2ac0e0d1da530d6f Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Wed, 2 Feb 2022 16:04:12 +0200 Subject: [PATCH 4/8] fix task deserialization issue when VDC updated --- govcd/adminvdc_test.go | 35 +++++++++++++++++++++++++++++++++++ types/v56/types.go | 11 ++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/govcd/adminvdc_test.go b/govcd/adminvdc_test.go index f061ebae7..ed58a1f5a 100644 --- a/govcd/adminvdc_test.go +++ b/govcd/adminvdc_test.go @@ -175,6 +175,41 @@ func (vcd *TestVCD) Test_UpdateVdcFlex(check *C) { check.Assert(adminVdc.AdminVdc.IsEnabled, Equals, vdcConfiguration.IsEnabled) check.Assert(adminVdc.AdminVdc.AllocationModel, Equals, vdcConfiguration.AllocationModel) + // test part to reproduce https://github.com/vmware/go-vcloud-director/issues/431 + // this part manages to create task error which later on VDC update fails if type properties order is bad + providerVdcHref := getVdcProviderVdcHref(vcd, check) + pvdcStorageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.StorageProfile.SP2, providerVdcHref) + check.Assert(err, IsNil) + + err = adminVdc.AddStorageProfileWait(&types.VdcStorageProfileConfiguration{ + Enabled: takeBoolPointer(true), + Default: false, + Units: "MB", + ProviderVdcStorageProfile: &types.Reference{HREF: pvdcStorageProfile.HREF}, + }, + "") + check.Assert(err, IsNil) + + vdc, err := adminOrg.GetVDCByName(vdcConfiguration.Name, true) + check.Assert(err, IsNil) + + vappName := check.TestName() + vmName := check.TestName() + vapp, err := makeEmptyVapp(vdc, vappName, "") + check.Assert(err, IsNil) + _, err = makeEmptyVm(vapp, vmName) + check.Assert(err, IsNil) + AddToCleanupList(vappName, "vapp", "", vappName) + + err = adminVdc.SetDefaultStorageProfile(vcd.config.VCD.StorageProfile.SP2) + check.Assert(err, IsNil) + err = adminVdc.RemoveStorageProfileWait(vcd.config.VCD.StorageProfile.SP1) + // fails with error in task which stays referenced in VDC as `history` element + check.Assert(err, NotNil) + err = adminVdc.Refresh() + check.Assert(err, IsNil) + // end + updateDescription := "updateDescription" computeCapacity := []*types.ComputeCapacity{ &types.ComputeCapacity{ diff --git a/types/v56/types.go b/types/v56/types.go index dd5d868ef..8267d0fa1 100644 --- a/types/v56/types.go +++ b/types/v56/types.go @@ -576,15 +576,16 @@ type Task struct { EndTime string `xml:"endTime,attr,omitempty"` // The date and time that processing of the task was completed. May not be present if the task is still being executed. ExpiryTime string `xml:"expiryTime,attr,omitempty"` // The date and time at which the task resource will be destroyed and no longer available for retrieval. May not be present if the task has not been executed or is still being executed. CancelRequested bool `xml:"cancelRequested,attr,omitempty"` // Whether user has requested this processing to be canceled. + Link *Link `xml:"Link,omitempty"` // A reference to an entity or operation associated with this object. Description string `xml:"Description,omitempty"` // Optional description. - Details string `xml:"Details,omitempty"` // Detailed message about the task. Also contained by the Owner entity when task status is preRunning. + Tasks *TasksInProgress `xml:"Tasks,omitempty"` // A list of queued, running, or recently completed tasks associated with this entity. + Owner *Reference `xml:"Owner,omitempty"` // Reference to the owner of the task. This is typically the object that the task is creating or updating. Error *Error `xml:"Error,omitempty"` // Represents error information from a failed task. - Link *Link `xml:"Link,omitempty"` // A reference to an entity or operation associated with this object. + User *Reference `xml:"User,omitempty"` // The user who started the task. Organization *Reference `xml:"Organization,omitempty"` // The organization to which the User belongs. - Owner *Reference `xml:"Owner,omitempty"` // Reference to the owner of the task. This is typically the object that the task is creating or updating. Progress int `xml:"Progress,omitempty"` // Read-only indicator of task progress as an approximate percentage between 0 and 100. Not available for all tasks. - Tasks *TasksInProgress `xml:"Tasks,omitempty"` // A list of queued, running, or recently completed tasks associated with this entity. - User *Reference `xml:"User,omitempty"` // The user who started the task. + Details string `xml:"Details,omitempty"` // Detailed message about the task. Also contained by the Owner entity when task status is preRunning. + // // TODO: add the following fields // Params anyType The parameters with which this task was started. From ea6edadee878d8233b0f672913ed67e7eb820b66 Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Wed, 2 Feb 2022 17:07:42 +0200 Subject: [PATCH 5/8] add changelog --- .changes/v2.15.0/433-bug-fixes.md | 2 ++ govcd/adminvdc_test.go | 1 + 2 files changed, 3 insertions(+) create mode 100644 .changes/v2.15.0/433-bug-fixes.md diff --git a/.changes/v2.15.0/433-bug-fixes.md b/.changes/v2.15.0/433-bug-fixes.md new file mode 100644 index 000000000..d7c15bef1 --- /dev/null +++ b/.changes/v2.15.0/433-bug-fixes.md @@ -0,0 +1,2 @@ +* Fixes Issue #431 "Wrong order in Task structure" [GH-433] +* Fixes Issue where VDC storage profile `enabled=false` wasn't working diff --git a/govcd/adminvdc_test.go b/govcd/adminvdc_test.go index ed58a1f5a..ccae4b143 100644 --- a/govcd/adminvdc_test.go +++ b/govcd/adminvdc_test.go @@ -146,6 +146,7 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) { } vdcStorageProfileDetails, err := adminOrg.client.GetStorageProfileByHref(vdc.Vdc.VdcStorageProfiles.VdcStorageProfile[1].HREF) + check.Assert(err, IsNil) check.Assert(*vdcStorageProfileDetails.Enabled, Equals, false) err = vdc.DeleteWait(true, true) From 366c1d11cca456c70fc3827891af19013dcc68af Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Wed, 2 Feb 2022 17:10:23 +0200 Subject: [PATCH 6/8] improve changelog --- .changes/v2.15.0/433-bug-fixes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/v2.15.0/433-bug-fixes.md b/.changes/v2.15.0/433-bug-fixes.md index d7c15bef1..5cfc89763 100644 --- a/.changes/v2.15.0/433-bug-fixes.md +++ b/.changes/v2.15.0/433-bug-fixes.md @@ -1,2 +1,2 @@ * Fixes Issue #431 "Wrong order in Task structure" [GH-433] -* Fixes Issue where VDC storage profile `enabled=false` wasn't working +* Fixes Issue where VDC creation with storage profile `enabled=false` wasn't working From df41819dd18dffb10f7ee663056fe6587afc741b Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Thu, 17 Feb 2022 11:37:37 +0200 Subject: [PATCH 7/8] add check --- govcd/adminvdc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/govcd/adminvdc.go b/govcd/adminvdc.go index b8966f40b..e43753b90 100644 --- a/govcd/adminvdc.go +++ b/govcd/adminvdc.go @@ -483,7 +483,7 @@ func (vdc *AdminVdc) RemoveStorageProfile(storageProfileName string) (Task, erro if err != nil { return Task{}, fmt.Errorf("cannot retrieve VDC storage profile '%s' details: %s", storageProfileName, err) } - if *vdcStorageProfileDetails.Enabled { + if vdcStorageProfileDetails.Enabled != nil && *vdcStorageProfileDetails.Enabled { _, err = vdc.UpdateStorageProfile(extractUuid(storageProfile.HREF), &types.AdminVdcStorageProfile{ Name: vdcStorageProfileDetails.Name, Units: vdcStorageProfileDetails.Units, From 861ea7bea56216339369a0d8d380359582d8cea6 Mon Sep 17 00:00:00 2001 From: Vaidotas Bauzys Date: Fri, 18 Feb 2022 18:32:47 +0200 Subject: [PATCH 8/8] update changelog --- .changes/v2.15.0/433-bug-fixes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/v2.15.0/433-bug-fixes.md b/.changes/v2.15.0/433-bug-fixes.md index 5cfc89763..ac30ce087 100644 --- a/.changes/v2.15.0/433-bug-fixes.md +++ b/.changes/v2.15.0/433-bug-fixes.md @@ -1,2 +1,2 @@ * Fixes Issue #431 "Wrong order in Task structure" [GH-433] -* Fixes Issue where VDC creation with storage profile `enabled=false` wasn't working +* Fixes Issue where VDC creation with storage profile `enabled=false` wasn't working. `VdcStorageProfile.enabled` and `VdcStorageProfileConfiguration.enabled` changed to pointers [GH-433]