From 90c763c5664a3998108cb208cb205b1093164059 Mon Sep 17 00:00:00 2001 From: Teemu Matilainen Date: Wed, 12 Feb 2025 16:14:38 +0200 Subject: [PATCH] [tfe_workspace_run] Allow configuration without `apply` and `destroy` blocks Allow configuring the `tfe_workspace_run` resource without `apply` and `destroy` blocks. This makes it possible to remove the `destroy` block from a resource without an `apply` block, to avoid a destroy run to be scheduled like when removing the whole resource. --- CHANGELOG.md | 1 + .../provider/resource_tfe_workspace_run.go | 9 ++-- .../resource_tfe_workspace_run_test.go | 52 +++++++++++++++++-- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20571b938..a05761893 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ FEATURES: * `r/tfe_project`: Add `auto_destroy_activity_duration` field to the project resource, which automatically propagates auto-destroy settings to workspaces [1550](https://github.com/hashicorp/terraform-provider-tfe/pull/1550) * `d/tfe_project`: Add `auto_destroy_activity_duration` field to the project datasource [1550](https://github.com/hashicorp/terraform-provider-tfe/pull/1550) * `r/tfe_team_project_access`: Add `variable_sets` attribute to `project_access`, by @mkam [#1565](https://github.com/hashicorp/terraform-provider-tfe/pull/1565) +* `r/tfe_workspace_run`: Allow configuration without `apply` and `destroy` blocks, by @tmatilai [#1604](https://github.com/hashicorp/terraform-provider-tfe/pull/1604) BUG FIXES: * `r/tfe_stack`: Fix serialization issue when using github app installation within vcs_repo block, by @mjyocca [#1572](https://github.com/hashicorp/terraform-provider-tfe/pull/1572) diff --git a/internal/provider/resource_tfe_workspace_run.go b/internal/provider/resource_tfe_workspace_run.go index a0bd1c6af..ef294a183 100644 --- a/internal/provider/resource_tfe_workspace_run.go +++ b/internal/provider/resource_tfe_workspace_run.go @@ -82,11 +82,10 @@ func resourceTFEWorkspaceRun() *schema.Resource { ForceNew: true, }, "apply": { - Type: schema.TypeList, - Elem: resourceTFEWorkspaceRunSchema(), - Optional: true, - AtLeastOneOf: []string{"apply", "destroy"}, - MaxItems: 1, + Type: schema.TypeList, + Elem: resourceTFEWorkspaceRunSchema(), + Optional: true, + MaxItems: 1, }, "destroy": { Type: schema.TypeList, diff --git a/internal/provider/resource_tfe_workspace_run_test.go b/internal/provider/resource_tfe_workspace_run_test.go index 8f463160b..f458565d5 100644 --- a/internal/provider/resource_tfe_workspace_run_test.go +++ b/internal/provider/resource_tfe_workspace_run_test.go @@ -113,7 +113,7 @@ func TestAccTFEWorkspaceRun_withBothApplyAndDestroyBlocks(t *testing.T) { }) } -func TestAccTFEWorkspaceRun_invalidParams(t *testing.T) { +func TestAccTFEWorkspaceRun_withNoApplyOrDestroyBlock(t *testing.T) { rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() tfeClient, err := getClientUsingEnv() @@ -124,14 +124,32 @@ func TestAccTFEWorkspaceRun_invalidParams(t *testing.T) { organization, orgCleanup := createBusinessOrganization(t, tfeClient) t.Cleanup(orgCleanup) + parentWorkspace, _ := setupWorkspacesWithConfig(t, tfeClient, rInt, organization.Name, "test-fixtures/basic-config") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: resource.ComposeTestCheckFunc( + testAccCheckTFEWorkspaceRunDestroy(parentWorkspace.ID, 0), + ), + Steps: []resource.TestStep{ + { + Config: testAccTFEWorkspaceRun_noApplyOrDestroyBlockProvided(organization.Name, rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFEWorkspaceRunDoesNotExist("tfe_workspace_run.ws_run_parent"), + ), + }, + }, + }) +} + +func TestAccTFEWorkspaceRun_invalidParams(t *testing.T) { invalidCases := []struct { Config string ExpectError *regexp.Regexp }{ - { - Config: testAccTFEWorkspaceRun_noApplyOrDestroyBlockProvided(organization.Name, rInt), - ExpectError: regexp.MustCompile("\"apply\": one of `apply,destroy` must be specified"), - }, { Config: testAccTFEWorkspaceRun_noWorkspaceProvided(), ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found`), @@ -254,6 +272,30 @@ func testAccCheckTFEWorkspaceRunExistWithExpectedStatus(n string, run *tfe.Run, } } +func testAccCheckTFEWorkspaceRunDoesNotExist(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + config := testAccProvider.Meta().(ConfiguredClient) + + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No instance ID is set") + } + + // A workspace run resource without apply block has a random ID, + // and no run with that ID should exist. + _, err := config.Client.Runs.Read(ctx, rs.Primary.ID) + if err == nil { + return fmt.Errorf("Expected run to not exist") + } + + return nil + } +} + func testAccCheckTFEWorkspaceRunDestroy(workspaceID string, expectedDestroyCount int) resource.TestCheckFunc { return func(s *terraform.State) error { config := testAccProvider.Meta().(ConfiguredClient)