diff --git a/resourcecontrollerv2/resource_controller_v2.go b/resourcecontrollerv2/resource_controller_v2.go index f2b6ac9c..eeb57dbb 100644 --- a/resourcecontrollerv2/resource_controller_v2.go +++ b/resourcecontrollerv2/resource_controller_v2.go @@ -790,6 +790,67 @@ func (resourceController *ResourceControllerV2) UnlockResourceInstanceWithContex return } +// CancelLastopResourceInstance : Cancel the in progress last operation of the resource instance +// Cancel the in progress last operation of the resource instance. After successful cancellation, the resource instance +// is removed. +func (resourceController *ResourceControllerV2) CancelLastopResourceInstance(cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { + return resourceController.CancelLastopResourceInstanceWithContext(context.Background(), cancelLastopResourceInstanceOptions) +} + +// CancelLastopResourceInstanceWithContext is an alternate form of the CancelLastopResourceInstance method which supports a Context parameter +func (resourceController *ResourceControllerV2) CancelLastopResourceInstanceWithContext(ctx context.Context, cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions) (result *ResourceInstance, response *core.DetailedResponse, err error) { + err = core.ValidateNotNil(cancelLastopResourceInstanceOptions, "cancelLastopResourceInstanceOptions cannot be nil") + if err != nil { + return + } + err = core.ValidateStruct(cancelLastopResourceInstanceOptions, "cancelLastopResourceInstanceOptions") + if err != nil { + return + } + + pathParamsMap := map[string]string{ + "id": *cancelLastopResourceInstanceOptions.ID, + } + + builder := core.NewRequestBuilder(core.DELETE) + builder = builder.WithContext(ctx) + builder.EnableGzipCompression = resourceController.GetEnableGzipCompression() + _, err = builder.ResolveRequestURL(resourceController.Service.Options.URL, `/v2/resource_instances/{id}/last_operation`, pathParamsMap) + if err != nil { + return + } + + for headerName, headerValue := range cancelLastopResourceInstanceOptions.Headers { + builder.AddHeader(headerName, headerValue) + } + + sdkHeaders := common.GetSdkHeaders("resource_controller", "V2", "CancelLastopResourceInstance") + for headerName, headerValue := range sdkHeaders { + builder.AddHeader(headerName, headerValue) + } + builder.AddHeader("Accept", "application/json") + + request, err := builder.Build() + if err != nil { + return + } + + var rawResponse map[string]json.RawMessage + response, err = resourceController.Service.Request(request, &rawResponse) + if err != nil { + return + } + if rawResponse != nil { + err = core.UnmarshalModel(rawResponse, "", &result, UnmarshalResourceInstance) + if err != nil { + return + } + response.Result = result + } + + return +} + // ListResourceKeys : Get a list of all of the resource keys // View all of the resource keys that exist for all of your resource instances. func (resourceController *ResourceControllerV2) ListResourceKeys(listResourceKeysOptions *ListResourceKeysOptions) (result *ResourceKeysList, response *core.DetailedResponse, err error) { @@ -1937,7 +1998,7 @@ func (resourceController *ResourceControllerV2) RunReclamationActionWithContext( } pathParamsMap := map[string]string{ - "id": *runReclamationActionOptions.ID, + "id": *runReclamationActionOptions.ID, "action_name": *runReclamationActionOptions.ActionName, } @@ -1993,6 +2054,34 @@ func (resourceController *ResourceControllerV2) RunReclamationActionWithContext( return } +// CancelLastopResourceInstanceOptions : The CancelLastopResourceInstance options. +type CancelLastopResourceInstanceOptions struct { + // The resource instance URL-encoded CRN or GUID. + ID *string `json:"id" validate:"required,ne="` + + // Allows users to set headers on API requests + Headers map[string]string +} + +// NewCancelLastopResourceInstanceOptions : Instantiate CancelLastopResourceInstanceOptions +func (*ResourceControllerV2) NewCancelLastopResourceInstanceOptions(id string) *CancelLastopResourceInstanceOptions { + return &CancelLastopResourceInstanceOptions{ + ID: core.StringPtr(id), + } +} + +// SetID : Allow user to set ID +func (_options *CancelLastopResourceInstanceOptions) SetID(id string) *CancelLastopResourceInstanceOptions { + _options.ID = core.StringPtr(id) + return _options +} + +// SetHeaders : Allow user to set Headers +func (options *CancelLastopResourceInstanceOptions) SetHeaders(param map[string]string) *CancelLastopResourceInstanceOptions { + options.Headers = param + return options +} + // CreateResourceAliasOptions : The CreateResourceAlias options. type CreateResourceAliasOptions struct { // The name of the alias. Must be 180 characters or less and cannot include any special characters other than `(space) @@ -2012,7 +2101,7 @@ type CreateResourceAliasOptions struct { // NewCreateResourceAliasOptions : Instantiate CreateResourceAliasOptions func (*ResourceControllerV2) NewCreateResourceAliasOptions(name string, source string, target string) *CreateResourceAliasOptions { return &CreateResourceAliasOptions{ - Name: core.StringPtr(name), + Name: core.StringPtr(name), Source: core.StringPtr(source), Target: core.StringPtr(target), } @@ -2146,9 +2235,9 @@ type CreateResourceInstanceOptions struct { // NewCreateResourceInstanceOptions : Instantiate CreateResourceInstanceOptions func (*ResourceControllerV2) NewCreateResourceInstanceOptions(name string, target string, resourceGroup string, resourcePlanID string) *CreateResourceInstanceOptions { return &CreateResourceInstanceOptions{ - Name: core.StringPtr(name), - Target: core.StringPtr(target), - ResourceGroup: core.StringPtr(resourceGroup), + Name: core.StringPtr(name), + Target: core.StringPtr(target), + ResourceGroup: core.StringPtr(resourceGroup), ResourcePlanID: core.StringPtr(resourcePlanID), } } @@ -2229,7 +2318,7 @@ type CreateResourceKeyOptions struct { // NewCreateResourceKeyOptions : Instantiate CreateResourceKeyOptions func (*ResourceControllerV2) NewCreateResourceKeyOptions(name string, source string) *CreateResourceKeyOptions { return &CreateResourceKeyOptions{ - Name: core.StringPtr(name), + Name: core.StringPtr(name), Source: core.StringPtr(source), } } @@ -2266,6 +2355,12 @@ func (options *CreateResourceKeyOptions) SetHeaders(param map[string]string) *Cr // Credentials : The credentials for a resource. type Credentials struct { + // If present, the user doesn't have the correct access to view the credentials and the details are redacted. The + // string value identifies the level of access that's required to view the credential. For additional information, see + // [viewing a + // credential](https://cloud.ibm.com/docs/account?topic=account-service_credentials&interface=ui#viewing-credentials-ui). + Redacted *string `json:"REDACTED,omitempty"` + // The API key for the credentials. Apikey *string `json:"apikey,omitempty"` @@ -2311,6 +2406,9 @@ func (o *Credentials) MarshalJSON() (buffer []byte, err error) { m[k] = v } } + if o.Redacted != nil { + m["REDACTED"] = o.Redacted + } if o.Apikey != nil { m["apikey"] = o.Apikey } @@ -2333,6 +2431,12 @@ func (o *Credentials) MarshalJSON() (buffer []byte, err error) { // UnmarshalCredentials unmarshals an instance of Credentials from the specified map of raw messages. func UnmarshalCredentials(m map[string]json.RawMessage, result interface{}) (err error) { obj := new(Credentials) + err = core.UnmarshalPrimitive(m, "REDACTED", &obj.Redacted) + if err != nil { + return + } + delete(m, "REDACTED") + err = core.UnmarshalPrimitive(m, "apikey", &obj.Apikey) if err != nil { return @@ -2995,9 +3099,9 @@ type ListResourceInstancesOptions struct { // Constants associated with the ListResourceInstancesOptions.State property. // The state of the instance. If not specified, instances in state `active` and `provisioning` are returned. const ( - ListResourceInstancesOptionsStateActiveConst = "active" + ListResourceInstancesOptionsStateActiveConst = "active" ListResourceInstancesOptionsStateProvisioningConst = "provisioning" - ListResourceInstancesOptionsStateRemovedConst = "removed" + ListResourceInstancesOptionsStateRemovedConst = "removed" ) // NewListResourceInstancesOptions : Instantiate ListResourceInstancesOptions @@ -4170,6 +4274,175 @@ func UnmarshalResourceInstance(m map[string]json.RawMessage, result interface{}) return } +// ResourceInstanceLastOperation : The status of the last operation requested on the instance. +type ResourceInstanceLastOperation struct { + // The last operation type of the resource instance. + Type *string `json:"type" validate:"required"` + + // The last operation state of the resoure instance. This indicates if the resource's last operation is in progress, + // succeeded or failed. + State *string `json:"state" validate:"required"` + + // The last operation sub type of the resoure instance. + SubType *string `json:"sub_type,omitempty"` + + // A boolean that indicates if the resource is provisioned asynchronously or not. + Async *bool `json:"async" validate:"required"` + + // The description of the status of last operation. + Description *string `json:"description" validate:"required"` + + // Optional string that states the reason code for the last operation state change. + ReasonCode *string `json:"reason_code,omitempty"` + + // A field which indicates the time after which the instance's last operation is to be polled. + PollAfter *float64 `json:"poll_after,omitempty"` + + // A boolean that indicates if the resource's last operation is cancelable or not. + Cancelable *bool `json:"cancelable" validate:"required"` + + // A boolean that indicates if the resource broker's last operation can be polled or not. + Poll *bool `json:"poll" validate:"required"` + + // Allows users to set arbitrary properties + additionalProperties map[string]interface{} +} + +// Constants associated with the ResourceInstanceLastOperation.State property. +// The last operation state of the resoure instance. This indicates if the resource's last operation is in progress, +// succeeded or failed. +const ( + ResourceInstanceLastOperationStateFailedConst = "failed" + ResourceInstanceLastOperationStateInProgressConst = "in progress" + ResourceInstanceLastOperationStateSucceededConst = "succeeded" +) + +// SetProperty allows the user to set an arbitrary property on an instance of ResourceInstanceLastOperation +func (o *ResourceInstanceLastOperation) SetProperty(key string, value interface{}) { + if o.additionalProperties == nil { + o.additionalProperties = make(map[string]interface{}) + } + o.additionalProperties[key] = value +} + +// SetProperties allows the user to set a map of arbitrary properties on an instance of ResourceInstanceLastOperation +func (o *ResourceInstanceLastOperation) SetProperties(m map[string]interface{}) { + o.additionalProperties = make(map[string]interface{}) + for k, v := range m { + o.additionalProperties[k] = v + } +} + +// GetProperty allows the user to retrieve an arbitrary property from an instance of ResourceInstanceLastOperation +func (o *ResourceInstanceLastOperation) GetProperty(key string) interface{} { + return o.additionalProperties[key] +} + +// GetProperties allows the user to retrieve the map of arbitrary properties from an instance of ResourceInstanceLastOperation +func (o *ResourceInstanceLastOperation) GetProperties() map[string]interface{} { + return o.additionalProperties +} + +// MarshalJSON performs custom serialization for instances of ResourceInstanceLastOperation +func (o *ResourceInstanceLastOperation) MarshalJSON() (buffer []byte, err error) { + m := make(map[string]interface{}) + if len(o.additionalProperties) > 0 { + for k, v := range o.additionalProperties { + m[k] = v + } + } + if o.Type != nil { + m["type"] = o.Type + } + if o.State != nil { + m["state"] = o.State + } + if o.SubType != nil { + m["sub_type"] = o.SubType + } + if o.Async != nil { + m["async"] = o.Async + } + if o.Description != nil { + m["description"] = o.Description + } + if o.ReasonCode != nil { + m["reason_code"] = o.ReasonCode + } + if o.PollAfter != nil { + m["poll_after"] = o.PollAfter + } + if o.Cancelable != nil { + m["cancelable"] = o.Cancelable + } + if o.Poll != nil { + m["poll"] = o.Poll + } + buffer, err = json.Marshal(m) + return +} + +// UnmarshalResourceInstanceLastOperation unmarshals an instance of ResourceInstanceLastOperation from the specified map of raw messages. +func UnmarshalResourceInstanceLastOperation(m map[string]json.RawMessage, result interface{}) (err error) { + obj := new(ResourceInstanceLastOperation) + err = core.UnmarshalPrimitive(m, "type", &obj.Type) + if err != nil { + return + } + delete(m, "type") + err = core.UnmarshalPrimitive(m, "state", &obj.State) + if err != nil { + return + } + delete(m, "state") + err = core.UnmarshalPrimitive(m, "sub_type", &obj.SubType) + if err != nil { + return + } + delete(m, "sub_type") + err = core.UnmarshalPrimitive(m, "async", &obj.Async) + if err != nil { + return + } + delete(m, "async") + err = core.UnmarshalPrimitive(m, "description", &obj.Description) + if err != nil { + return + } + delete(m, "description") + err = core.UnmarshalPrimitive(m, "reason_code", &obj.ReasonCode) + if err != nil { + return + } + delete(m, "reason_code") + err = core.UnmarshalPrimitive(m, "poll_after", &obj.PollAfter) + if err != nil { + return + } + delete(m, "poll_after") + err = core.UnmarshalPrimitive(m, "cancelable", &obj.Cancelable) + if err != nil { + return + } + delete(m, "cancelable") + err = core.UnmarshalPrimitive(m, "poll", &obj.Poll) + if err != nil { + return + } + delete(m, "poll") + for k := range m { + var v interface{} + e := core.UnmarshalPrimitive(m, k, &v) + if e != nil { + err = e + return + } + obj.SetProperty(k, v) + } + reflect.ValueOf(result).Elem().Set(reflect.ValueOf(obj)) + return +} + // ResourceInstancesList : A list of resource instances. type ResourceInstancesList struct { // The number of resource instances in `resources`. @@ -4477,7 +4750,7 @@ type RunReclamationActionOptions struct { // NewRunReclamationActionOptions : Instantiate RunReclamationActionOptions func (*ResourceControllerV2) NewRunReclamationActionOptions(id string, actionName string) *RunReclamationActionOptions { return &RunReclamationActionOptions{ - ID: core.StringPtr(id), + ID: core.StringPtr(id), ActionName: core.StringPtr(actionName), } } @@ -4556,7 +4829,7 @@ type UpdateResourceAliasOptions struct { // NewUpdateResourceAliasOptions : Instantiate UpdateResourceAliasOptions func (*ResourceControllerV2) NewUpdateResourceAliasOptions(id string, name string) *UpdateResourceAliasOptions { return &UpdateResourceAliasOptions{ - ID: core.StringPtr(id), + ID: core.StringPtr(id), Name: core.StringPtr(name), } } @@ -4595,7 +4868,7 @@ type UpdateResourceBindingOptions struct { // NewUpdateResourceBindingOptions : Instantiate UpdateResourceBindingOptions func (*ResourceControllerV2) NewUpdateResourceBindingOptions(id string, name string) *UpdateResourceBindingOptions { return &UpdateResourceBindingOptions{ - ID: core.StringPtr(id), + ID: core.StringPtr(id), Name: core.StringPtr(name), } } @@ -4700,7 +4973,7 @@ type UpdateResourceKeyOptions struct { // NewUpdateResourceKeyOptions : Instantiate UpdateResourceKeyOptions func (*ResourceControllerV2) NewUpdateResourceKeyOptions(id string, name string) *UpdateResourceKeyOptions { return &UpdateResourceKeyOptions{ - ID: core.StringPtr(id), + ID: core.StringPtr(id), Name: core.StringPtr(name), } } diff --git a/resourcecontrollerv2/resource_controller_v2_examples_test.go b/resourcecontrollerv2/resource_controller_v2_examples_test.go index f29b443c..d7cb52aa 100644 --- a/resourcecontrollerv2/resource_controller_v2_examples_test.go +++ b/resourcecontrollerv2/resource_controller_v2_examples_test.go @@ -199,12 +199,28 @@ var _ = Describe(`ResourceControllerV2 Examples Tests`, func() { listResourceInstancesOptions := resourceControllerService.NewListResourceInstancesOptions() listResourceInstancesOptions = listResourceInstancesOptions.SetName(resourceInstanceName) + listResourceInstancesOptions = listResourceInstancesOptions.SetLimit(2) // Setting the limit to 2 as a caution to not fetch all paginated records + resources := make([]resourcecontrollerv2.ResourceInstance, 0) resourceInstancesList, response, err := resourceControllerService.ListResourceInstances(listResourceInstancesOptions) + loopCounter := 0 + for err == nil && resourceInstancesList.NextURL != nil && *resourceInstancesList.NextURL != "" && loopCounter < 3 { + resourceInstancesList, response, err = resourceControllerService.ListResourceInstances(listResourceInstancesOptions) + resources = append(resources, resourceInstancesList.Resources...) + startString, err2 := core.GetQueryParam(resourceInstancesList.NextURL, "start") + if err2 != nil || startString == nil { + fmt.Println("Error in fetching start value from next_url:", err2) + break + } + listResourceInstancesOptions.SetStart(*startString) + loopCounter = loopCounter + 1 // Adding the loopCounter as a caution to not fetch all paginated records + } if err != nil { panic(err) + } else { + resources = append(resources, resourceInstancesList.Resources...) } - b, _ := json.MarshalIndent(resourceInstancesList, "", " ") + b, _ := json.MarshalIndent(resources, "", " ") fmt.Println(string(b)) // end-list_resource_instances @@ -390,6 +406,10 @@ var _ = Describe(`ResourceControllerV2 Examples Tests`, func() { b, _ := json.MarshalIndent(resourceBinding, "", " ") fmt.Println(string(b)) + if resourceBinding.Credentials.Redacted != nil && (*resourceBinding.Credentials.Redacted == "REDACTED" || *resourceBinding.Credentials.Redacted == "REDACTED_EXPLICIT") { + fmt.Println("Credentials are redacted with code:", *resourceBinding.Credentials.Redacted, ".The User doesn't have the correct access to view the credentials. Refer to the API documentation for additional details.") + } + // end-get_resource_binding Expect(err).To(BeNil()) @@ -501,6 +521,9 @@ var _ = Describe(`ResourceControllerV2 Examples Tests`, func() { } b, _ := json.MarshalIndent(resourceKey, "", " ") fmt.Println(string(b)) + if resourceKey.Credentials.Redacted != nil && (*resourceKey.Credentials.Redacted == "REDACTED" || *resourceKey.Credentials.Redacted == "REDACTED_EXPLICIT") { + fmt.Println("Credentials are redacted with code:", *resourceKey.Credentials.Redacted, ".The User doesn't have the correct access to view the credentials. Refer to the API documentation for additional details.") + } // end-get_resource_key @@ -739,5 +762,32 @@ var _ = Describe(`ResourceControllerV2 Examples Tests`, func() { // Wait for reclamation object to be created. time.Sleep(20 * time.Second) }) + It(`CancelLastopResourceInstance request example`, func() { + fmt.Println("\nCancelLastopResourceInstance() result:") + // begin-cancel_lastop_resource_instance + + cancelLastopResourceInstanceOptions := resourceControllerService.NewCancelLastopResourceInstanceOptions( + instanceGUID, + ) + + resourceInstance, response, err := resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptions) + if err != nil { + fmt.Println("The instance is not cancelable.") + } else { + b, _ := json.MarshalIndent(resourceInstance, "", " ") + fmt.Println(string(b)) + } + + // end-cancel_lastop_resource_instance + if err != nil { + Expect(err.Error()).To(Equal("The instance is not cancelable.")) + Expect(response.StatusCode).To(Equal(422)) + Expect(resourceInstance).To(BeNil()) + } else { + Expect(err).To(BeNil()) + Expect(resourceInstance).ToNot(BeNil()) + } + + }) }) }) diff --git a/resourcecontrollerv2/resource_controller_v2_integration_test.go b/resourcecontrollerv2/resource_controller_v2_integration_test.go index a965339c..f1eba5be 100644 --- a/resourcecontrollerv2/resource_controller_v2_integration_test.go +++ b/resourcecontrollerv2/resource_controller_v2_integration_test.go @@ -586,11 +586,11 @@ var _ = Describe("Resource Controller - Integration Tests", func() { It("12 - Create Resource Binding", func() { shouldSkipTest() - Expect(testAliasGUID).ToNot(BeEmpty()) + Expect(testAliasCRN).ToNot(BeEmpty()) target := "crn:v1:staging:public:bluemix:us-south:s/" + testSpaceGUID + "::cf-application:" + testAppGUID bindTargetCRN = "crn:v1:staging:public:cf:us-south:s/" + testSpaceGUID + "::cf-application:" + testAppGUID - options := service.NewCreateResourceBindingOptions(testAliasGUID, target) + options := service.NewCreateResourceBindingOptions(testAliasCRN, target) options.SetName(bindingNames["name"]) parameters := &resourcecontrollerv2.ResourceBindingPostParameters{} @@ -774,10 +774,10 @@ var _ = Describe("Resource Controller - Integration Tests", func() { It(`17a - List Resource Bindings For Alias`, func() { shouldSkipTest() - Expect(testAliasGUID).ToNot(BeEmpty()) + Expect(testAliasCRN).ToNot(BeEmpty()) listResourceBindingsForAliasOptions := &resourcecontrollerv2.ListResourceBindingsForAliasOptions{ - ID: &testAliasGUID, + ID: &testAliasCRN, Limit: core.Int64Ptr(resultsPerPage), } @@ -1023,7 +1023,7 @@ var _ = Describe("Resource Controller - Integration Tests", func() { It("24 - Create Resource Key For Alias", func() { shouldSkipTest() - options := service.NewCreateResourceKeyOptions(keyNames["name2"], testAliasGUID) + options := service.NewCreateResourceKeyOptions(keyNames["name2"], testAliasCRN) headers := map[string]string{ "Transaction-ID": "rc-sdk-go-test24-" + transactionID, } @@ -1179,7 +1179,7 @@ var _ = Describe("Resource Controller - Integration Tests", func() { It("30 - Delete A Resource Alias With Dependencies - Fail", func() { shouldSkipTest() - options := service.NewDeleteResourceAliasOptions(testAliasGUID) + options := service.NewDeleteResourceAliasOptions(testAliasCRN) headers := map[string]string{ "Transaction-ID": "rc-sdk-go-test30-" + transactionID, } @@ -1299,9 +1299,9 @@ var _ = Describe("Resource Controller - Integration Tests", func() { It("36 - Delete A Resource Alias", func() { shouldSkipTest() - Expect(testAliasGUID).ToNot(BeEmpty()) + Expect(testAliasCRN).ToNot(BeEmpty()) - options := service.NewDeleteResourceAliasOptions(testAliasGUID) + options := service.NewDeleteResourceAliasOptions(testAliasCRN) headers := map[string]string{ "Transaction-ID": "rc-sdk-go-test36-" + transactionID, } @@ -1315,9 +1315,9 @@ var _ = Describe("Resource Controller - Integration Tests", func() { It("37 - Verify Resource Alias Was Deleted", func() { shouldSkipTest() - Expect(testAliasGUID).ToNot(BeEmpty()) + Expect(testAliasCRN).ToNot(BeEmpty()) - options := service.NewGetResourceAliasOptions(testAliasGUID) + options := service.NewGetResourceAliasOptions(testAliasCRN) headers := map[string]string{ "Transaction-ID": "rc-sdk-go-test37-" + transactionID, } @@ -1375,7 +1375,7 @@ var _ = Describe("Resource Controller - Integration Tests", func() { _, resp, err := service.UpdateResourceInstance(options) Expect(err).NotTo(BeNil()) - Expect(resp.StatusCode).To(Equal(400)) + Expect(resp.StatusCode).To(Equal(422)) }) It("40 - Delete A Locked Resource Instance - Fail", func() { @@ -1391,7 +1391,7 @@ var _ = Describe("Resource Controller - Integration Tests", func() { resp, err := service.DeleteResourceInstance(options) Expect(err).NotTo(BeNil()) - Expect(resp.StatusCode).To(Equal(400)) + Expect(resp.StatusCode).To(Equal(422)) }) It("41 - Unlock A Resource Instance", func() { @@ -1709,6 +1709,26 @@ var _ = Describe("Resource Controller - Integration Tests", func() { time.Sleep(20 * time.Second) }) + Describe(`CancelLastopResourceInstance - Cancel the in progress last operation of the resource instance`, func() { + BeforeEach(func() { + shouldSkipTest() + }) + It(`53 - CancelLastopResourceInstance(cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions)`, func() { + Expect(testInstanceGUID).ToNot(BeEmpty()) + cancelLastopResourceInstanceOptions := &resourcecontrollerv2.CancelLastopResourceInstanceOptions{ + ID: &testInstanceGUID, + } + + resourceInstance, response, err := service.CancelLastopResourceInstance(cancelLastopResourceInstanceOptions) + // Expect(err).To(BeNil()) + // Expect(response.StatusCode).To(Equal(200)) + // Expect(resourceInstance).ToNot(BeNil()) + Expect(err.Error()).To(Equal("The instance is not cancelable.")) + Expect(response.StatusCode).To(Equal(422)) + Expect(resourceInstance).To(BeNil()) + }) + }) + // Commented because redis timeouts cause intermittent failure // It("53 - Verify The Resource Instance Is Reclaimed", func() { diff --git a/resourcecontrollerv2/resource_controller_v2_test.go b/resourcecontrollerv2/resource_controller_v2_test.go index 34727620..f0eb462d 100644 --- a/resourcecontrollerv2/resource_controller_v2_test.go +++ b/resourcecontrollerv2/resource_controller_v2_test.go @@ -67,14 +67,13 @@ var _ = Describe(`ResourceControllerV2`, func() { Context(`Using external config, construct service client instances`, func() { // Map containing environment variables used in testing. var testEnvironment = map[string]string{ - "RESOURCE_CONTROLLER_URL": "https://resourcecontrollerv2/api", + "RESOURCE_CONTROLLER_URL": "https://resourcecontrollerv2/api", "RESOURCE_CONTROLLER_AUTH_TYPE": "noauth", } It(`Create service client using external config successfully`, func() { SetTestEnvironment(testEnvironment) - resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2UsingExternalConfig(&resourcecontrollerv2.ResourceControllerV2Options{ - }) + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2UsingExternalConfig(&resourcecontrollerv2.ResourceControllerV2Options{}) Expect(resourceControllerService).ToNot(BeNil()) Expect(serviceErr).To(BeNil()) ClearTestEnvironment(testEnvironment) @@ -103,8 +102,7 @@ var _ = Describe(`ResourceControllerV2`, func() { }) It(`Create service client using external config and set url programatically successfully`, func() { SetTestEnvironment(testEnvironment) - resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2UsingExternalConfig(&resourcecontrollerv2.ResourceControllerV2Options{ - }) + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2UsingExternalConfig(&resourcecontrollerv2.ResourceControllerV2Options{}) err := resourceControllerService.SetServiceURL("https://testService/api") Expect(err).To(BeNil()) Expect(resourceControllerService).ToNot(BeNil()) @@ -122,13 +120,12 @@ var _ = Describe(`ResourceControllerV2`, func() { Context(`Using external config, construct service client instances with error: Invalid Auth`, func() { // Map containing environment variables used in testing. var testEnvironment = map[string]string{ - "RESOURCE_CONTROLLER_URL": "https://resourcecontrollerv2/api", + "RESOURCE_CONTROLLER_URL": "https://resource-controller.test.cloud.ibm.com", "RESOURCE_CONTROLLER_AUTH_TYPE": "someOtherAuth", } SetTestEnvironment(testEnvironment) - resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2UsingExternalConfig(&resourcecontrollerv2.ResourceControllerV2Options{ - }) + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2UsingExternalConfig(&resourcecontrollerv2.ResourceControllerV2Options{}) It(`Instantiate service client with error`, func() { Expect(resourceControllerService).To(BeNil()) @@ -139,7 +136,7 @@ var _ = Describe(`ResourceControllerV2`, func() { Context(`Using external config, construct service client instances with error: Invalid URL`, func() { // Map containing environment variables used in testing. var testEnvironment = map[string]string{ - "RESOURCE_CONTROLLER_AUTH_TYPE": "NOAuth", + "RESOURCE_CONTROLLER_AUTH_TYPE": "NOAuth", } SetTestEnvironment(testEnvironment) @@ -2172,6 +2169,218 @@ var _ = Describe(`ResourceControllerV2`, func() { }) }) }) + Describe(`CancelLastopResourceInstance(cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions) - Operation response error`, func() { + cancelLastopResourceInstancePath := "/v2/resource_instances/testString/last_operation" + Context(`Using mock server endpoint with invalid JSON response`, func() { + BeforeEach(func() { + testServer = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + defer GinkgoRecover() + + // Verify the contents of the request + Expect(req.URL.EscapedPath()).To(Equal(cancelLastopResourceInstancePath)) + Expect(req.Method).To(Equal("DELETE")) + res.Header().Set("Content-type", "application/json") + res.WriteHeader(200) + fmt.Fprint(res, `} this is not valid json {`) + })) + }) + It(`Invoke CancelLastopResourceInstance with error: Operation response processing error`, func() { + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2(&resourcecontrollerv2.ResourceControllerV2Options{ + URL: testServer.URL, + Authenticator: &core.NoAuthAuthenticator{}, + }) + Expect(serviceErr).To(BeNil()) + Expect(resourceControllerService).ToNot(BeNil()) + + // Construct an instance of the CancelLastopResourceInstanceOptions model + cancelLastopResourceInstanceOptionsModel := new(resourcecontrollerv2.CancelLastopResourceInstanceOptions) + cancelLastopResourceInstanceOptionsModel.ID = core.StringPtr("testString") + cancelLastopResourceInstanceOptionsModel.Headers = map[string]string{"x-custom-header": "x-custom-value"} + // Expect response parsing to fail since we are receiving a text/plain response + result, response, operationErr := resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).ToNot(BeNil()) + Expect(response).ToNot(BeNil()) + Expect(result).To(BeNil()) + + // Enable retries and test again + resourceControllerService.EnableRetries(0, 0) + result, response, operationErr = resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).ToNot(BeNil()) + Expect(response).ToNot(BeNil()) + Expect(result).To(BeNil()) + }) + AfterEach(func() { + testServer.Close() + }) + }) + }) + Describe(`CancelLastopResourceInstance(cancelLastopResourceInstanceOptions *CancelLastopResourceInstanceOptions)`, func() { + cancelLastopResourceInstancePath := "/v2/resource_instances/testString/last_operation" + Context(`Using mock server endpoint with timeout`, func() { + BeforeEach(func() { + testServer = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + defer GinkgoRecover() + + // Verify the contents of the request + Expect(req.URL.EscapedPath()).To(Equal(cancelLastopResourceInstancePath)) + Expect(req.Method).To(Equal("DELETE")) + + // Sleep a short time to support a timeout test + time.Sleep(100 * time.Millisecond) + + // Set mock response + res.Header().Set("Content-type", "application/json") + res.WriteHeader(200) + fmt.Fprintf(res, "%s", `{"id": "ID", "guid": "GUID", "url": "URL", "created_at": "2019-01-01T12:00:00.000Z", "updated_at": "2019-01-01T12:00:00.000Z", "deleted_at": "2019-01-01T12:00:00.000Z", "created_by": "CreatedBy", "updated_by": "UpdatedBy", "deleted_by": "DeletedBy", "scheduled_reclaim_at": "2019-01-01T12:00:00.000Z", "restored_at": "2019-01-01T12:00:00.000Z", "restored_by": "RestoredBy", "scheduled_reclaim_by": "ScheduledReclaimBy", "name": "Name", "region_id": "RegionID", "account_id": "AccountID", "reseller_channel_id": "ResellerChannelID", "resource_plan_id": "ResourcePlanID", "resource_group_id": "ResourceGroupID", "resource_group_crn": "ResourceGroupCRN", "target_crn": "TargetCRN", "parameters": {"mapKey": "anyValue"}, "allow_cleanup": true, "crn": "CRN", "state": "active", "type": "Type", "sub_type": "SubType", "resource_id": "ResourceID", "dashboard_url": "DashboardURL", "last_operation": {"type": "Type", "state": "in progress", "sub_type": "SubType", "async": false, "description": "Description", "reason_code": "ReasonCode", "poll_after": 9, "cancelable": true, "poll": true}, "resource_aliases_url": "ResourceAliasesURL", "resource_bindings_url": "ResourceBindingsURL", "resource_keys_url": "ResourceKeysURL", "plan_history": [{"resource_plan_id": "ResourcePlanID", "start_date": "2019-01-01T12:00:00.000Z", "requestor_id": "RequestorID"}], "migrated": true, "extensions": {"mapKey": "anyValue"}, "controlled_by": "ControlledBy", "locked": true}`) + })) + }) + It(`Invoke CancelLastopResourceInstance successfully with retries`, func() { + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2(&resourcecontrollerv2.ResourceControllerV2Options{ + URL: testServer.URL, + Authenticator: &core.NoAuthAuthenticator{}, + }) + Expect(serviceErr).To(BeNil()) + Expect(resourceControllerService).ToNot(BeNil()) + resourceControllerService.EnableRetries(0, 0) + + // Construct an instance of the CancelLastopResourceInstanceOptions model + cancelLastopResourceInstanceOptionsModel := new(resourcecontrollerv2.CancelLastopResourceInstanceOptions) + cancelLastopResourceInstanceOptionsModel.ID = core.StringPtr("testString") + cancelLastopResourceInstanceOptionsModel.Headers = map[string]string{"x-custom-header": "x-custom-value"} + + // Invoke operation with a Context to test a timeout error + ctx, cancelFunc := context.WithTimeout(context.Background(), 80*time.Millisecond) + defer cancelFunc() + _, _, operationErr := resourceControllerService.CancelLastopResourceInstanceWithContext(ctx, cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).ToNot(BeNil()) + Expect(operationErr.Error()).To(ContainSubstring("deadline exceeded")) + + // Disable retries and test again + resourceControllerService.DisableRetries() + result, response, operationErr := resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).To(BeNil()) + Expect(response).ToNot(BeNil()) + Expect(result).ToNot(BeNil()) + + // Re-test the timeout error with retries disabled + ctx, cancelFunc2 := context.WithTimeout(context.Background(), 80*time.Millisecond) + defer cancelFunc2() + _, _, operationErr = resourceControllerService.CancelLastopResourceInstanceWithContext(ctx, cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).ToNot(BeNil()) + Expect(operationErr.Error()).To(ContainSubstring("deadline exceeded")) + }) + AfterEach(func() { + testServer.Close() + }) + }) + Context(`Using mock server endpoint`, func() { + BeforeEach(func() { + testServer = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + defer GinkgoRecover() + + // Verify the contents of the request + Expect(req.URL.EscapedPath()).To(Equal(cancelLastopResourceInstancePath)) + Expect(req.Method).To(Equal("DELETE")) + + // Set mock response + res.Header().Set("Content-type", "application/json") + res.WriteHeader(200) + fmt.Fprintf(res, "%s", `{"id": "ID", "guid": "GUID", "url": "URL", "created_at": "2019-01-01T12:00:00.000Z", "updated_at": "2019-01-01T12:00:00.000Z", "deleted_at": "2019-01-01T12:00:00.000Z", "created_by": "CreatedBy", "updated_by": "UpdatedBy", "deleted_by": "DeletedBy", "scheduled_reclaim_at": "2019-01-01T12:00:00.000Z", "restored_at": "2019-01-01T12:00:00.000Z", "restored_by": "RestoredBy", "scheduled_reclaim_by": "ScheduledReclaimBy", "name": "Name", "region_id": "RegionID", "account_id": "AccountID", "reseller_channel_id": "ResellerChannelID", "resource_plan_id": "ResourcePlanID", "resource_group_id": "ResourceGroupID", "resource_group_crn": "ResourceGroupCRN", "target_crn": "TargetCRN", "parameters": {"mapKey": "anyValue"}, "allow_cleanup": true, "crn": "CRN", "state": "active", "type": "Type", "sub_type": "SubType", "resource_id": "ResourceID", "dashboard_url": "DashboardURL", "last_operation": {"type": "Type", "state": "in progress", "sub_type": "SubType", "async": false, "description": "Description", "reason_code": "ReasonCode", "poll_after": 9, "cancelable": true, "poll": true}, "resource_aliases_url": "ResourceAliasesURL", "resource_bindings_url": "ResourceBindingsURL", "resource_keys_url": "ResourceKeysURL", "plan_history": [{"resource_plan_id": "ResourcePlanID", "start_date": "2019-01-01T12:00:00.000Z", "requestor_id": "RequestorID"}], "migrated": true, "extensions": {"mapKey": "anyValue"}, "controlled_by": "ControlledBy", "locked": true}`) + })) + }) + It(`Invoke CancelLastopResourceInstance successfully`, func() { + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2(&resourcecontrollerv2.ResourceControllerV2Options{ + URL: testServer.URL, + Authenticator: &core.NoAuthAuthenticator{}, + }) + Expect(serviceErr).To(BeNil()) + Expect(resourceControllerService).ToNot(BeNil()) + + // Invoke operation with nil options model (negative test) + result, response, operationErr := resourceControllerService.CancelLastopResourceInstance(nil) + Expect(operationErr).NotTo(BeNil()) + Expect(response).To(BeNil()) + Expect(result).To(BeNil()) + + // Construct an instance of the CancelLastopResourceInstanceOptions model + cancelLastopResourceInstanceOptionsModel := new(resourcecontrollerv2.CancelLastopResourceInstanceOptions) + cancelLastopResourceInstanceOptionsModel.ID = core.StringPtr("testString") + cancelLastopResourceInstanceOptionsModel.Headers = map[string]string{"x-custom-header": "x-custom-value"} + + // Invoke operation with valid options model (positive test) + result, response, operationErr = resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).To(BeNil()) + Expect(response).ToNot(BeNil()) + Expect(result).ToNot(BeNil()) + + }) + It(`Invoke CancelLastopResourceInstance with error: Operation validation and request error`, func() { + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2(&resourcecontrollerv2.ResourceControllerV2Options{ + URL: testServer.URL, + Authenticator: &core.NoAuthAuthenticator{}, + }) + Expect(serviceErr).To(BeNil()) + Expect(resourceControllerService).ToNot(BeNil()) + + // Construct an instance of the CancelLastopResourceInstanceOptions model + cancelLastopResourceInstanceOptionsModel := new(resourcecontrollerv2.CancelLastopResourceInstanceOptions) + cancelLastopResourceInstanceOptionsModel.ID = core.StringPtr("testString") + cancelLastopResourceInstanceOptionsModel.Headers = map[string]string{"x-custom-header": "x-custom-value"} + // Invoke operation with empty URL (negative test) + err := resourceControllerService.SetServiceURL("") + Expect(err).To(BeNil()) + result, response, operationErr := resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).ToNot(BeNil()) + Expect(operationErr.Error()).To(ContainSubstring(core.ERRORMSG_SERVICE_URL_MISSING)) + Expect(response).To(BeNil()) + Expect(result).To(BeNil()) + // Construct a second instance of the CancelLastopResourceInstanceOptions model with no property values + cancelLastopResourceInstanceOptionsModelNew := new(resourcecontrollerv2.CancelLastopResourceInstanceOptions) + // Invoke operation with invalid model (negative test) + result, response, operationErr = resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModelNew) + Expect(operationErr).ToNot(BeNil()) + Expect(response).To(BeNil()) + Expect(result).To(BeNil()) + }) + AfterEach(func() { + testServer.Close() + }) + }) + Context(`Using mock server endpoint with missing response body`, func() { + BeforeEach(func() { + testServer = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + defer GinkgoRecover() + + // Set success status code with no respoonse body + res.WriteHeader(200) + })) + }) + It(`Invoke CancelLastopResourceInstance successfully`, func() { + resourceControllerService, serviceErr := resourcecontrollerv2.NewResourceControllerV2(&resourcecontrollerv2.ResourceControllerV2Options{ + URL: testServer.URL, + Authenticator: &core.NoAuthAuthenticator{}, + }) + Expect(serviceErr).To(BeNil()) + Expect(resourceControllerService).ToNot(BeNil()) + + // Construct an instance of the CancelLastopResourceInstanceOptions model + cancelLastopResourceInstanceOptionsModel := new(resourcecontrollerv2.CancelLastopResourceInstanceOptions) + cancelLastopResourceInstanceOptionsModel.ID = core.StringPtr("testString") + cancelLastopResourceInstanceOptionsModel.Headers = map[string]string{"x-custom-header": "x-custom-value"} + + // Invoke operation + result, response, operationErr := resourceControllerService.CancelLastopResourceInstance(cancelLastopResourceInstanceOptionsModel) + Expect(operationErr).To(BeNil()) + Expect(response).ToNot(BeNil()) + + // Verify a nil result + Expect(result).To(BeNil()) + }) + AfterEach(func() { + testServer.Close() + }) + }) + }) Describe(`ListResourceKeys(listResourceKeysOptions *ListResourceKeysOptions) - Operation response error`, func() { listResourceKeysPath := "/v2/resource_keys" Context(`Using mock server endpoint with invalid JSON response`, func() {