diff --git a/client/api_client.go b/client/api_client.go index e3d55773..51badd82 100644 --- a/client/api_client.go +++ b/client/api_client.go @@ -66,7 +66,7 @@ type ApiClientInterface interface { Environment(id string) (Environment, error) EnvironmentCreate(payload EnvironmentCreate) (Environment, error) EnvironmentCreateWithoutTemplate(payload EnvironmentCreateWithoutTemplate) (Environment, error) - EnvironmentDestroy(id string) (Environment, error) + EnvironmentDestroy(id string) (*EnvironmentDestroyResponse, error) EnvironmentMarkAsArchived(id string) error EnvironmentUpdate(id string, payload EnvironmentUpdate) (Environment, error) EnvironmentDeploy(id string, payload DeployRequest) (EnvironmentDeployResponse, error) @@ -75,6 +75,7 @@ type ApiClientInterface interface { EnvironmentScheduling(environmentId string) (EnvironmentScheduling, error) EnvironmentSchedulingUpdate(environmentId string, payload EnvironmentScheduling) (EnvironmentScheduling, error) EnvironmentSchedulingDelete(environmentId string) error + EnvironmentDeployment(id string) (*DeploymentLog, error) WorkflowTrigger(environmentId string) ([]WorkflowTrigger, error) WorkflowTriggerUpsert(environmentId string, request WorkflowTriggerUpsertPayload) ([]WorkflowTrigger, error) EnvironmentDriftDetection(environmentId string) (EnvironmentSchedulingExpression, error) diff --git a/client/api_client_mock.go b/client/api_client_mock.go index 8f275e10..798303b1 100644 --- a/client/api_client_mock.go +++ b/client/api_client_mock.go @@ -852,11 +852,26 @@ func (mr *MockApiClientInterfaceMockRecorder) EnvironmentDeploy(arg0, arg1 any) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnvironmentDeploy", reflect.TypeOf((*MockApiClientInterface)(nil).EnvironmentDeploy), arg0, arg1) } +// EnvironmentDeployment mocks base method. +func (m *MockApiClientInterface) EnvironmentDeployment(arg0 string) (*DeploymentLog, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnvironmentDeployment", arg0) + ret0, _ := ret[0].(*DeploymentLog) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EnvironmentDeployment indicates an expected call of EnvironmentDeployment. +func (mr *MockApiClientInterfaceMockRecorder) EnvironmentDeployment(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnvironmentDeployment", reflect.TypeOf((*MockApiClientInterface)(nil).EnvironmentDeployment), arg0) +} + // EnvironmentDestroy mocks base method. -func (m *MockApiClientInterface) EnvironmentDestroy(arg0 string) (Environment, error) { +func (m *MockApiClientInterface) EnvironmentDestroy(arg0 string) (*EnvironmentDestroyResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnvironmentDestroy", arg0) - ret0, _ := ret[0].(Environment) + ret0, _ := ret[0].(*EnvironmentDestroyResponse) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/client/environment.go b/client/environment.go index 77d0addd..005c3699 100644 --- a/client/environment.go +++ b/client/environment.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +const ENVIRONMENT = "environment" + type ConfigurationVariableType int func (c *ConfigurationVariableType) ReadResourceData(fieldName string, d *schema.ResourceData) error { @@ -27,7 +29,7 @@ func (c *ConfigurationVariableType) WriteResourceData(fieldName string, d *schem switch val := *c; val { case 0: - valStr = "environment" + valStr = ENVIRONMENT case 1: valStr = TERRAFORM default: @@ -91,6 +93,7 @@ type DeploymentLog struct { Output json.RawMessage `json:"output,omitempty"` Error json.RawMessage `json:"error,omitempty"` Type string `json:"type"` + Status string `json:"status"` WorkflowFile *WorkflowFile `json:"workflowFile,omitempty" tfschema:"-"` } @@ -163,6 +166,10 @@ type EnvironmentMoveRequest struct { ProjectId string `json:"projectId"` } +type EnvironmentDestroyResponse struct { + Id string `json:"id"` +} + func GetConfigurationVariableType(variableType string) (ConfigurationVariableType, error) { switch variableType { case "terraform": @@ -256,6 +263,15 @@ func (client *ApiClient) Environment(id string) (Environment, error) { return result, nil } +func (client *ApiClient) EnvironmentDeployment(id string) (*DeploymentLog, error) { + var result DeploymentLog + err := client.http.Get("/environments/deployments/"+id, nil, &result) + if err != nil { + return nil, err + } + return &result, nil +} + func (client *ApiClient) EnvironmentCreate(payload EnvironmentCreate) (Environment, error) { var result Environment @@ -283,13 +299,13 @@ func (client *ApiClient) EnvironmentCreateWithoutTemplate(payload EnvironmentCre return result, nil } -func (client *ApiClient) EnvironmentDestroy(id string) (Environment, error) { - var result Environment +func (client *ApiClient) EnvironmentDestroy(id string) (*EnvironmentDestroyResponse, error) { + var result EnvironmentDestroyResponse err := client.http.Post("/environments/"+id+"/destroy", nil, &result) if err != nil { - return Environment{}, err + return nil, err } - return result, nil + return &result, nil } func (client *ApiClient) EnvironmentUpdate(id string, payload EnvironmentUpdate) (Environment, error) { diff --git a/client/environment_test.go b/client/environment_test.go index 76747cd0..3b0efaf7 100644 --- a/client/environment_test.go +++ b/client/environment_test.go @@ -5,6 +5,7 @@ import ( "errors" "testing" + "github.com/env0/terraform-provider-env0/client" . "github.com/env0/terraform-provider-env0/client" "github.com/jinzhu/copier" . "github.com/onsi/ginkgo" @@ -280,15 +281,27 @@ var _ = Describe("Environment Client", func() { Describe("EnvironmentDelete", func() { var err error + var res *client.EnvironmentDestroyResponse + + mockedRes := client.EnvironmentDestroyResponse{ + Id: "id123", + } BeforeEach(func() { - httpCall = mockHttpClient.EXPECT().Post("/environments/"+mockEnvironment.Id+"/destroy", nil, gomock.Any()).Times(1) - _, err = apiClient.EnvironmentDestroy(mockEnvironment.Id) + httpCall = mockHttpClient.EXPECT().Post("/environments/"+mockEnvironment.Id+"/destroy", nil, gomock.Any()).Times(1). + Do((func(path string, request interface{}, response *EnvironmentDestroyResponse) { + *response = mockedRes + })) + res, err = apiClient.EnvironmentDestroy(mockEnvironment.Id) }) It("Should not return error", func() { Expect(err).To(BeNil()) }) + + It("Should return the expected response", func() { + Expect(*res).To(Equal(mockedRes)) + }) }) Describe("EnvironmentMarkAsArchived", func() { @@ -438,6 +451,34 @@ var _ = Describe("Environment Client", func() { Expect(err).To(BeNil()) }) }) + + Describe("EnvironmentDeployment", func() { + var deployment *DeploymentLog + var err error + + mockDeployment := DeploymentLog{ + Id: "id12345", + Status: "IN_PROGRESS", + } + + BeforeEach(func() { + httpCall = mockHttpClient.EXPECT(). + Get("/environments/deployments/"+mockDeployment.Id, nil, gomock.Any()). + Do(func(path string, request interface{}, response *DeploymentLog) { + *response = mockDeployment + }).Times(1) + + deployment, err = apiClient.EnvironmentDeployment(mockDeployment.Id) + }) + + It("Should return deployment", func() { + Expect(*deployment).To(Equal(mockDeployment)) + }) + + It("Should not return an error", func() { + Expect(err).To(BeNil()) + }) + }) }) func TestMarshalEnvironmentCreateWithoutTemplate(t *testing.T) { diff --git a/env0/data_configuration_variable.go b/env0/data_configuration_variable.go index f4acb41a..0ed97154 100644 --- a/env0/data_configuration_variable.go +++ b/env0/data_configuration_variable.go @@ -198,37 +198,47 @@ func getConfigurationVariable(params ConfigurationVariableParams, meta interface name, nameOk := params.Name, params.Name != "" typeString, ok := params.ConfigurationType, params.ConfigurationType != "" type_ := -1 + if ok { if !nameOk { return client.ConfigurationVariable{}, diag.Errorf("Specify 'type' only when searching configuration variables by 'name' (not by 'id')") } + switch typeString { - case "environment": + case client.ENVIRONMENT: type_ = int(client.ConfigurationVariableTypeEnvironment) - case "terraform": + case client.TERRAFORM: type_ = int(client.ConfigurationVariableTypeTerraform) default: return client.ConfigurationVariable{}, diag.Errorf("Invalid value for 'type': %s. can be either 'environment' or 'terraform'", typeString) } } + var variable client.ConfigurationVariable + for _, candidate := range variables { if idOk && candidate.Id == id { variable = candidate + break } + if nameOk && candidate.Name == name { if type_ != -1 { if int(*candidate.Type) != type_ { continue } } + variable = candidate + break } } + if variable.Id == "" { return client.ConfigurationVariable{}, diag.Errorf("Could not find variable") } + return variable, nil } diff --git a/env0/data_git_token.go b/env0/data_git_token.go index 62eb5da3..58dde20a 100644 --- a/env0/data_git_token.go +++ b/env0/data_git_token.go @@ -31,6 +31,7 @@ func dataGitToken() *schema.Resource { func dataGitTokenRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var gitToken *client.GitToken + var err error id, ok := d.GetOk("id") diff --git a/env0/errors.go b/env0/errors.go index 2f7c28b2..66e164e4 100644 --- a/env0/errors.go +++ b/env0/errors.go @@ -28,6 +28,7 @@ func ResourceGetFailure(ctx context.Context, resourceName string, d *schema.Reso if driftDetected(err) { tflog.Warn(ctx, "Drift Detected: Terraform will remove id from state", map[string]interface{}{"id": d.Id()}) d.SetId("") + return nil } diff --git a/env0/provider.go b/env0/provider.go index 1c2d29a4..b564c65f 100644 --- a/env0/provider.go +++ b/env0/provider.go @@ -193,10 +193,12 @@ func configureProvider(version string, p *schema.Provider) schema.ConfigureConte if r != nil { tflog.SubsystemInfo(subCtx, "env0_api_client", "Sending request", map[string]interface{}{"method": r.Method, "url": r.URL}) } + return nil }). OnAfterResponse(func(c *resty.Client, r *resty.Response) error { tflog.SubsystemInfo(subCtx, "env0_api_client", "Received response", map[string]interface{}{"method": r.Request.Method, "url": r.Request.URL, "status": r.Status()}) + return nil }). AddRetryAfterErrorCondition(). @@ -204,6 +206,7 @@ func configureProvider(version string, p *schema.Provider) schema.ConfigureConte if r == nil { // No response. Possibly a networking issue (E.g. DNS lookup failure). tflog.SubsystemWarn(subCtx, "env0_api_client", "No response, retrying request") + return true } @@ -211,11 +214,13 @@ func configureProvider(version string, p *schema.Provider) schema.ConfigureConte // Retry when there's a 5xx error. Otherwise do not retry. if r.StatusCode() >= 500 || (isIntegrationTest && r.StatusCode() == 404) { tflog.SubsystemWarn(subCtx, "env0_api_client", "Received a failed or not found response, retrying request", map[string]interface{}{"method": r.Request.Method, "url": r.Request.URL, "status code": r.StatusCode()}) + return true } if r.StatusCode() == 200 && isIntegrationTest && r.String() == "[]" { tflog.SubsystemWarn(subCtx, "env0_api_client", "Received an empty list , retrying request", map[string]interface{}{"method": r.Request.Method, "url": r.Request.URL}) + return true } @@ -249,6 +254,7 @@ func configureProvider(version string, p *schema.Provider) schema.ConfigureConte if _, err := apiClient.OrganizationId(); err != nil { return nil, diag.Diagnostics{diag.Diagnostic{Severity: diag.Error, Summary: err.Error()}} } + return apiClient, nil } } diff --git a/env0/resource_environment.go b/env0/resource_environment.go index 381f8f83..09ea77a2 100644 --- a/env0/resource_environment.go +++ b/env0/resource_environment.go @@ -6,6 +6,8 @@ import ( "fmt" "os" "regexp" + "slices" + "strings" "time" "github.com/env0/terraform-provider-env0/client" @@ -82,11 +84,11 @@ func resourceEnvironment() *schema.Resource { "type": { Type: schema.TypeString, Description: "variable type (allowed values are: terraform, environment)", - Default: "environment", + Default: client.ENVIRONMENT, Optional: true, ValidateFunc: func(val interface{}, key string) (warns []string, errs []error) { value := val.(string) - if value != "environment" && value != "terraform" { + if value != client.ENVIRONMENT && value != client.TERRAFORM { errs = append(errs, fmt.Errorf("%q can be either \"environment\" or \"terraform\", got: %q", key, value)) } return @@ -493,9 +495,9 @@ func createVariable(configurationVariable *client.ConfigurationVariable) interfa variable["value"] = configurationVariable.Value if configurationVariable.Type == nil || *configurationVariable.Type == 0 { - variable["type"] = "environment" + variable["type"] = client.ENVIRONMENT } else { - variable["type"] = "terraform" + variable["type"] = client.TERRAFORM } if configurationVariable.Description != "" { @@ -664,14 +666,14 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, meta } func getEnvironmentVariableSetIdsFromApi(d *schema.ResourceData, apiClient client.ApiClientInterface) ([]string, error) { - environmentVariableSets, err := apiClient.ConfigurationSetsAssignments("ENVIRONMENT", d.Id()) + environmentVariableSets, err := apiClient.ConfigurationSetsAssignments(strings.ToUpper(client.ENVIRONMENT), d.Id()) if err != nil { return nil, err } var environmentVariableSetIds []string for _, variableSet := range environmentVariableSets { - if variableSet.AssignmentScope == "environment" { + if variableSet.AssignmentScope == client.ENVIRONMENT { environmentVariableSetIds = append(environmentVariableSetIds, variableSet.Id) } } @@ -937,7 +939,7 @@ func resourceEnvironmentDelete(ctx context.Context, d *schema.ResourceData, meta return diag.Errorf(`must enable "force_destroy" safeguard in order to destroy`) } - environment, err := apiClient.EnvironmentDestroy(d.Id()) + res, err := apiClient.EnvironmentDestroy(d.Id()) if err != nil { if frerr, ok := err.(*http.FailedResponseError); ok && frerr.BadRequest() { tflog.Warn(ctx, "Could not delete environment. Already deleted?", map[string]interface{}{"id": d.Id(), "error": frerr.Error()}) @@ -946,8 +948,8 @@ func resourceEnvironmentDelete(ctx context.Context, d *schema.ResourceData, meta return diag.Errorf("could not delete environment: %v", err) } - if environment.Status != "INACTIVE" && d.Get("wait_for_destroy").(bool) { - if err := waitForEnvironmentDestroy(apiClient, &environment); err != nil { + if d.Get("wait_for_destroy").(bool) { + if err := waitForEnvironmentDestroy(apiClient, res.Id); err != nil { return diag.FromErr(err) } } @@ -955,44 +957,43 @@ func resourceEnvironmentDelete(ctx context.Context, d *schema.ResourceData, meta return nil } -func waitForEnvironmentDestroy(apiClient client.ApiClientInterface, environment *client.Environment) error { +func waitForEnvironmentDestroy(apiClient client.ApiClientInterface, deploymentId string) error { waitInteval := time.Second * 10 timeout := time.Minute * 30 - if os.Getenv("TF_ACC") == "1" { // For acceptance tests. + + if os.Getenv("TF_ACC") == "1" { // For acceptance tests reducing interval to 1 second and timeout to 10 seconds. waitInteval = time.Second timeout = time.Second * 10 } - ticker := time.NewTicker(waitInteval) // When invoked - check if environment is inactive. - timer := time.NewTimer(timeout) // When invoked - time out + ticker := time.NewTicker(waitInteval) // When invoked - check the status. + timer := time.NewTimer(timeout) // When invoked - timeout. results := make(chan error) go func() { for { - select { - case <-timer.C: - results <- fmt.Errorf("timed out! last environment status was '%s'", environment.Status) + deployment, err := apiClient.EnvironmentDeployment(deploymentId) + if err != nil { + results <- fmt.Errorf("failed to get environment deployment '%s': %w", deploymentId, err) return - case <-ticker.C: - latestEnvironment, err := apiClient.Environment(environment.Id) - if err != nil { - results <- fmt.Errorf("failed to get environment status: %w", err) - return - } - - environment = &latestEnvironment + } - if environment.Status == "INACTIVE" { - results <- nil - return - } + if slices.Contains([]string{"WAITING_FOR_USER", "TIMEOUT", "FAILURE", "CANCELLED", "INTERNAL_FAILURE", "ABORTING", "ABORTED", "SKIPPED", "NEVER_DEPLOYED"}, deployment.Status) { + results <- fmt.Errorf("failed to wait for environment destroy to complete, deployment status is: %s", deployment.Status) + return + } - if environment.Status == "DESTROY_IN_PROGRESS" { - continue - } + if deployment.Status == "SUCCESS" { + results <- nil + return + } - results <- fmt.Errorf("environment destroy failed with status '%s'", environment.Status) + select { + case <-timer.C: + results <- fmt.Errorf("timeout! last destroy deployment status was '%s'", deployment.Status) return + case <-ticker.C: + continue } } }() @@ -1468,7 +1469,7 @@ func resourceEnvironmentImport(ctx context.Context, d *schema.ResourceData, meta environmentConfigurationVariables, err := apiClient.ConfigurationVariablesByScope(scope, environment.Id) if err != nil { - return nil, fmt.Errorf("could not get environment configuration variables: %v", err) + return nil, fmt.Errorf("could not get environment configuration variables: %w", err) } environmentVariableSetIds, err := getEnvironmentVariableSetIdsFromApi(d, apiClient) diff --git a/env0/resource_environment_test.go b/env0/resource_environment_test.go index cc2ffa4f..3f4960b6 100644 --- a/env0/resource_environment_test.go +++ b/env0/resource_environment_test.go @@ -825,10 +825,18 @@ func TestUnitEnvironmentResource(t *testing.T) { }, } - environmentWithStatus := func(status string) client.Environment { - newEnvironment := environment - newEnvironment.Status = status - return newEnvironment + deploymentLog := client.DeploymentLog{ + Id: "id12345_deployment", + } + + destroyResponse := &client.EnvironmentDestroyResponse{ + Id: deploymentLog.Id, + } + + deploymentWithStatus := func(status string) *client.DeploymentLog { + newDeployment := deploymentLog + newDeployment.Status = status + return &newDeployment } config := resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ @@ -863,9 +871,10 @@ func TestUnitEnvironmentResource(t *testing.T) { mock.EXPECT().Environment(environment.Id).Times(1).Return(environment, nil), mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil), mock.EXPECT().ConfigurationSetsAssignments("ENVIRONMENT", environment.Id).Times(1).Return(nil, nil), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).Times(1).Return(environmentWithStatus("INACTIVE"), nil), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("QUEUED"), nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("IN_PROGRESS"), nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("SUCCESS"), nil), ) }) }) @@ -880,7 +889,7 @@ func TestUnitEnvironmentResource(t *testing.T) { { Config: config, Destroy: true, - ExpectError: regexp.MustCompile("environment destroy failed with status 'FAILED'"), + ExpectError: regexp.MustCompile("failed to wait for environment destroy to complete, deployment status is: WAITING_FOR_USER"), }, }, } @@ -895,15 +904,15 @@ func TestUnitEnvironmentResource(t *testing.T) { mock.EXPECT().Environment(environment.Id).Times(1).Return(environment, nil), mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil), mock.EXPECT().ConfigurationSetsAssignments("ENVIRONMENT", environment.Id).Times(1).Return(nil, nil), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).Times(1).Return(environmentWithStatus("FAILED"), nil), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("INACTIVE"), nil), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("WAITING_FOR_USER"), nil), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("SUCCESS"), nil), ) }) }) - t.Run("get environment failed", func(t *testing.T) { + t.Run("get deployment failed", func(t *testing.T) { testCase := resource.TestCase{ Steps: []resource.TestStep{ { @@ -913,7 +922,7 @@ func TestUnitEnvironmentResource(t *testing.T) { { Config: config, Destroy: true, - ExpectError: regexp.MustCompile("failed to get environment status: error"), + ExpectError: regexp.MustCompile(fmt.Sprintf("failed to get environment deployment '%s': error", deploymentLog.Id)), }, }, } @@ -928,10 +937,10 @@ func TestUnitEnvironmentResource(t *testing.T) { mock.EXPECT().Environment(environment.Id).Times(1).Return(environment, nil), mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil), mock.EXPECT().ConfigurationSetsAssignments("ENVIRONMENT", environment.Id).Times(1).Return(nil, nil), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).Times(1).Return(client.Environment{}, errors.New("error")), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("INACTIVE"), nil), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(nil, errors.New("error")), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("SUCCESS"), nil), ) }) }) @@ -946,7 +955,7 @@ func TestUnitEnvironmentResource(t *testing.T) { { Config: config, Destroy: true, - ExpectError: regexp.MustCompile("timed out! last environment status was 'DESTROY_IN_PROGRESS'"), + ExpectError: regexp.MustCompile("timeout! last destroy deployment status was 'IN_PROGRESS'"), }, }, } @@ -961,9 +970,11 @@ func TestUnitEnvironmentResource(t *testing.T) { mock.EXPECT().Environment(environment.Id).Times(1).Return(environment, nil), mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil), mock.EXPECT().ConfigurationSetsAssignments("ENVIRONMENT", environment.Id).Times(1).Return(nil, nil), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().Environment(environment.Id).AnyTimes().Return(environmentWithStatus("DESTROY_IN_PROGRESS"), nil), - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environmentWithStatus("INACTIVE"), nil), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("QUEUED"), nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).AnyTimes().Return(deploymentWithStatus("IN_PROGRESS"), nil), + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(destroyResponse, nil), + mock.EXPECT().EnvironmentDeployment(deploymentLog.Id).Times(1).Return(deploymentWithStatus("SUCCESS"), nil), ) }) }) @@ -2540,7 +2551,7 @@ func TestUnitEnvironmentResource(t *testing.T) { mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil) mock.EXPECT().ConfigurationSetsAssignments("ENVIRONMENT", environment.Id).Times(1).Return(nil, nil) mock.EXPECT().Environment(gomock.Any()).Times(2).Return(environment, nil) - mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(environment, http.NewMockFailedResponseError(400)) + mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1).Return(nil, http.NewMockFailedResponseError(400)) }) }) diff --git a/tests/integration/012_environment/main.tf b/tests/integration/012_environment/main.tf index a1dc4426..fdb86874 100644 --- a/tests/integration/012_environment/main.tf +++ b/tests/integration/012_environment/main.tf @@ -49,6 +49,7 @@ resource "env0_environment" "auto_glob_envrironment" { approve_plan_automatically = true deploy_on_push = true force_destroy = true + wait_for_destroy = true } resource "env0_environment" "example" {