From 7451b6658aa88b7e226f6e7aff54f562ce4b1226 Mon Sep 17 00:00:00 2001 From: Manuel Wudka-Robles Date: Wed, 13 Dec 2023 16:55:05 -0800 Subject: [PATCH 1/4] Upgrade to go-tfe v1.41.0 This version adds support for managing data retention policies. --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 0e53f61e2..1b470428b 100644 --- a/go.mod +++ b/go.mod @@ -11,8 +11,8 @@ require ( github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.5 // indirect - github.com/hashicorp/go-slug v0.13.2 - github.com/hashicorp/go-tfe v1.40.0 + github.com/hashicorp/go-slug v0.13.3 + github.com/hashicorp/go-tfe v1.41.0 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/hcl/v2 v2.19.1 // indirect @@ -30,7 +30,7 @@ require ( golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.4.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index 2fa7b2b75..3f92ea341 100644 --- a/go.sum +++ b/go.sum @@ -70,10 +70,10 @@ github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDm github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= -github.com/hashicorp/go-slug v0.13.2 h1:ArlarJ8w1Rinx4P1N6Sr00t+GmjJWtYZuSEDYPQBErA= -github.com/hashicorp/go-slug v0.13.2/go.mod h1:RA4C+ezyC2nDsiPM5+1djqagveBBJdSN/fM2QCUziYQ= -github.com/hashicorp/go-tfe v1.40.0 h1:xgR/ijk5XAAo4jQHIOrKnIJrc4iM0jjYPskKgf4eDTU= -github.com/hashicorp/go-tfe v1.40.0/go.mod h1:pc7+wHCH26BaoFP5txiKkM7Coi5PmB9VwNfnnT2XpKE= +github.com/hashicorp/go-slug v0.13.3 h1:JiYNpOkD0HmMWw/lNYiBAUD6+WIBIV7UftKiqIbpNqM= +github.com/hashicorp/go-slug v0.13.3/go.mod h1:RA4C+ezyC2nDsiPM5+1djqagveBBJdSN/fM2QCUziYQ= +github.com/hashicorp/go-tfe v1.41.0 h1:ieQrbFwH4KITMxqyBni7v5jTBkcvQqCbnPNsV2eh4TY= +github.com/hashicorp/go-tfe v1.41.0/go.mod h1:i29eWGEtI/glZaixaMTVUipNWxQFN6gw7hy3swKOC/A= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -239,8 +239,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= -golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= From 0170dfb206d432fa2e9aa855b00d54602551d763 Mon Sep 17 00:00:00 2001 From: Manuel Wudka-Robles Date: Wed, 13 Dec 2023 16:59:29 -0800 Subject: [PATCH 2/4] Add data retention policy block to organization resource --- .../provider/resource_tfe_organization.go | 63 +++++++++++++++ .../resource_tfe_organization_test.go | 80 +++++++++++++++++++ website/docs/r/organization.html.markdown | 6 ++ 3 files changed, 149 insertions(+) diff --git a/internal/provider/resource_tfe_organization.go b/internal/provider/resource_tfe_organization.go index 491581930..a1e1d7625 100644 --- a/internal/provider/resource_tfe_organization.go +++ b/internal/provider/resource_tfe_organization.go @@ -91,6 +91,21 @@ func resourceTFEOrganization() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "data_retention_policy": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "delete_older_than_n_days": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, }, } } @@ -115,6 +130,19 @@ func resourceTFEOrganizationCreate(d *schema.ResourceData, meta interface{}) err d.SetId(org.Name) + if v, ok := d.GetOk("data_retention_policy"); ok { + drp := v.([]interface{})[0].(map[string]interface{}) + + _, err = config.Client.Organizations.SetDataRetentionPolicy(ctx, org.Name, tfe.DataRetentionPolicySetOptions{ + DeleteOlderThanNDays: drp["delete_older_than_n_days"].(int), + }) + + if err != nil { + d.Partial(true) + return fmt.Errorf("Error setting data retention policy on organization %s: %w", org.Name, err) + } + } + return resourceTFEOrganizationUpdate(d, meta) } @@ -150,6 +178,22 @@ func resourceTFEOrganizationRead(d *schema.ResourceData, meta interface{}) error d.Set("default_project_id", org.DefaultProject.ID) } + var dataRetentionPolicy []interface{} + if org.DataRetentionPolicy != nil { + policy, err := config.Client.Organizations.ReadDataRetentionPolicy(ctx, org.Name) + + if err != nil { + return fmt.Errorf( + "Error getting data retention policy for organization %s: %w", org.Name, err) + } + + drp := map[string]interface{}{ + "delete_older_than_n_days": policy.DeleteOlderThanNDays, + } + dataRetentionPolicy = append(dataRetentionPolicy, drp) + } + d.Set("data_retention_policy", dataRetentionPolicy) + return nil } @@ -210,6 +254,25 @@ func resourceTFEOrganizationUpdate(d *schema.ResourceData, meta interface{}) err d.SetId(org.Name) + // nolint: nestif + if d.HasChange("data_retention_policy") { + v, ok := d.GetOk("data_retention_policy") + if ok { + drp := v.([]interface{})[0].(map[string]interface{}) + _, err := config.Client.Organizations.SetDataRetentionPolicy(ctx, org.Name, tfe.DataRetentionPolicySetOptions{DeleteOlderThanNDays: drp["delete_older_than_n_days"].(int)}) + if err != nil { + d.Partial(true) + return fmt.Errorf("Error setting data retention policy on organization %s: %w", org.Name, err) + } + } else { + err := config.Client.Organizations.DeleteDataRetentionPolicy(ctx, org.Name) + if err != nil { + d.Partial(true) + return fmt.Errorf("Error deleting data retention policy from organization %s: %w", org.Name, err) + } + } + } + return resourceTFEOrganizationRead(d, meta) } diff --git a/internal/provider/resource_tfe_organization_test.go b/internal/provider/resource_tfe_organization_test.go index cae3b88b6..00d3f2dd4 100644 --- a/internal/provider/resource_tfe_organization_test.go +++ b/internal/provider/resource_tfe_organization_test.go @@ -251,6 +251,75 @@ func TestAccTFEOrganization_import(t *testing.T) { }) } +func TestAccTFEOrganization_updateDataRetentionPolicy(t *testing.T) { + skipIfCloud(t) + + org := &tfe.Organization{} + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckTFEOrganizationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFEOrganization_basic(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFEOrganizationExists( + "tfe_organization.foobar", org), + resource.TestCheckNoResourceAttr("tfe_organization.foobar", "data_retention_policy.0.delete_older_than_n_days"), + ), + }, + { + Config: testAccTFEOrganization_dataRetentionPolicy(rInt, 8), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "tfe_organization.foobar", "data_retention_policy.0.delete_older_than_n_days", "8"), + ), + }, + { + Config: testAccTFEOrganization_dataRetentionPolicy(rInt, 20), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "tfe_organization.foobar", "data_retention_policy.0.delete_older_than_n_days", "20"), + ), + }, + { + Config: testAccTFEOrganization_basic(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFEOrganizationExists( + "tfe_organization.foobar", org), + resource.TestCheckNoResourceAttr("tfe_organization.foobar", "data_retention_policy.0.delete_older_than_n_days"), + ), + }, + }, + }) +} + +func TestAccTFEOrganization_importDataRetentionPolicy(t *testing.T) { + skipIfCloud(t) + + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckTFEWorkspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFEOrganization_dataRetentionPolicy(rInt, 10), + }, + { + ResourceName: "tfe_organization.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckTFEOrganizationExists( n string, org *tfe.Organization) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -434,3 +503,14 @@ resource "tfe_organization" "foobar" { allow_force_delete_workspaces = %t }`, orgName, orgEmail, costEstimationEnabled, assessmentsEnforced, allowForceDeleteWorkspaces) } + +func testAccTFEOrganization_dataRetentionPolicy(rInt int, deleteOlderThanNDays int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" + data_retention_policy { + delete_older_than_n_days = %d + } +}`, rInt, deleteOlderThanNDays) +} diff --git a/website/docs/r/organization.html.markdown b/website/docs/r/organization.html.markdown index ac2351a1b..234961a61 100644 --- a/website/docs/r/organization.html.markdown +++ b/website/docs/r/organization.html.markdown @@ -24,6 +24,7 @@ resource "tfe_organization" "test" { The following arguments are supported: +* `data_retention_policy` - (Optional) The organization's [data retention policy](https://developer.hashicorp.com/terraform/enterprise/workspaces/settings/deletion#data-retention-policies). * `name` - (Required) Name of the organization. * `email` - (Required) Admin email address. * `session_timeout_minutes` - (Optional) Session timeout after inactivity. @@ -38,6 +39,11 @@ The following arguments are supported: * `assessments_enforced` - (Optional) (Available only in Terraform Cloud) Whether to force health assessments (drift detection) on all eligible workspaces or allow workspaces to set their own preferences. * `allow_force_delete_workspaces` - (Optional) Whether workspace administrators are permitted to delete workspaces with resources under management. If false, only organization owners may delete these workspaces. Defaults to false. +The `data_retention_policy` block supports: + +* `delete_older_than_n_days` - (Required) Automatically delete backing data for state versions and configuration versions older than N days. + + ## Attributes Reference * `id` - The name of the organization. From e617d180cdf3bc4d5ca9468c27663d081916f4f1 Mon Sep 17 00:00:00 2001 From: Manuel Wudka-Robles Date: Wed, 13 Dec 2023 16:59:41 -0800 Subject: [PATCH 3/4] Add data retention policy block to workspace resource --- internal/provider/client_mock_workspaces.go | 12 +++ internal/provider/resource_tfe_workspace.go | 62 ++++++++++++ .../provider/resource_tfe_workspace_test.go | 94 +++++++++++++++++++ website/docs/r/workspace.html.markdown | 5 + 4 files changed, 173 insertions(+) diff --git a/internal/provider/client_mock_workspaces.go b/internal/provider/client_mock_workspaces.go index 5e5df377c..71374b2c4 100644 --- a/internal/provider/client_mock_workspaces.go +++ b/internal/provider/client_mock_workspaces.go @@ -172,3 +172,15 @@ func (m *mockWorkspaces) SafeDelete(ctx context.Context, organization string, wo func (m *mockWorkspaces) SafeDeleteByID(ctx context.Context, workspaceID string) error { panic("not implemented") } + +func (m *mockWorkspaces) ReadDataRetentionPolicy(ctx context.Context, workspaceID string) (*tfe.DataRetentionPolicy, error) { + panic("not implemented") +} + +func (m *mockWorkspaces) SetDataRetentionPolicy(ctx context.Context, workspaceID string, options tfe.DataRetentionPolicySetOptions) (*tfe.DataRetentionPolicy, error) { + panic("not implemented") +} + +func (m *mockWorkspaces) DeleteDataRetentionPolicy(ctx context.Context, workspaceID string) error { + panic("not implemented") +} diff --git a/internal/provider/resource_tfe_workspace.go b/internal/provider/resource_tfe_workspace.go index 435d15ed4..6c1159e84 100644 --- a/internal/provider/resource_tfe_workspace.go +++ b/internal/provider/resource_tfe_workspace.go @@ -230,6 +230,21 @@ func resourceTFEWorkspace() *schema.Resource { Default: "", }, + "data_retention_policy": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "delete_older_than_n_days": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + "vcs_repo": { Type: schema.TypeList, Optional: true, @@ -428,6 +443,18 @@ func resourceTFEWorkspaceCreate(d *schema.ResourceData, meta interface{}) error d.SetId(workspace.ID) + if v, ok := d.GetOk("data_retention_policy"); ok { + drp := v.([]interface{})[0].(map[string]interface{}) + + _, err = config.Client.Workspaces.SetDataRetentionPolicy(ctx, workspace.ID, tfe.DataRetentionPolicySetOptions{ + DeleteOlderThanNDays: drp["delete_older_than_n_days"].(int), + }) + + if err != nil { + return fmt.Errorf("Error setting data retention policy on workspace %s: %w", name, err) + } + } + if sshKeyID, ok := d.GetOk("ssh_key_id"); ok { _, err = config.Client.Workspaces.AssignSSHKey(ctx, workspace.ID, tfe.WorkspaceAssignSSHKeyOptions{ SSHKeyID: tfe.String(sshKeyID.(string)), @@ -542,6 +569,22 @@ func resourceTFEWorkspaceRead(d *schema.ResourceData, meta interface{}) error { d.Set("vcs_repo", vcsRepo) + var dataRetentionPolicy []interface{} + if workspace.DataRetentionPolicy != nil { + policy, err := config.Client.Workspaces.ReadDataRetentionPolicy(ctx, id) + + if err != nil { + return fmt.Errorf( + "Error data retention policy for workspace %s: %w", id, err) + } + + drp := map[string]interface{}{ + "delete_older_than_n_days": policy.DeleteOlderThanNDays, + } + dataRetentionPolicy = append(dataRetentionPolicy, drp) + } + d.Set("data_retention_policy", dataRetentionPolicy) + if workspace.GlobalRemoteState { d.Set("global_remote_state", true) } else { @@ -734,6 +777,25 @@ func resourceTFEWorkspaceUpdate(d *schema.ResourceData, meta interface{}) error } } + // nolint: nestif + if d.HasChange("data_retention_policy") { + v, ok := d.GetOk("data_retention_policy") + if ok { + drp := v.([]interface{})[0].(map[string]interface{}) + _, err := config.Client.Workspaces.SetDataRetentionPolicy(ctx, id, tfe.DataRetentionPolicySetOptions{DeleteOlderThanNDays: drp["delete_older_than_n_days"].(int)}) + if err != nil { + d.Partial(true) + return fmt.Errorf("Error setting data retention policy on workspace %s: %w", d.Id(), err) + } + } else { + err := config.Client.Workspaces.DeleteDataRetentionPolicy(ctx, id) + if err != nil { + d.Partial(true) + return fmt.Errorf("Error deleting data retention policy from workspace %s: %w", d.Id(), err) + } + } + } + if d.HasChange("tag_names") { oldTagNameValues, newTagNameValues := d.GetChange("tag_names") newTagNamesSet := newTagNameValues.(*schema.Set) diff --git a/internal/provider/resource_tfe_workspace_test.go b/internal/provider/resource_tfe_workspace_test.go index 81cfef2d1..35a365452 100644 --- a/internal/provider/resource_tfe_workspace_test.go +++ b/internal/provider/resource_tfe_workspace_test.go @@ -1484,6 +1484,83 @@ func TestAccTFEWorkspace_updateVCSRepo(t *testing.T) { }) } +func TestAccTFEWorkspace_updateDataRetentionPolicy(t *testing.T) { + skipIfCloud(t) + + workspace := &tfe.Workspace{} + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckTFEWorkspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFEWorkspace_basicForceDeleteEnabled(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFEWorkspaceExists( + "tfe_workspace.foobar", workspace, testAccProvider), + resource.TestCheckNoResourceAttr("tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days"), + ), + }, + { + Config: testAccTFEWorkspace_dataRetentionPolicy(rInt, 8), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days", "8"), + ), + }, + { + Config: testAccTFEWorkspace_dataRetentionPolicy(rInt, 20), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days", "20"), + ), + }, + { + Config: testAccTFEWorkspace_basicForceDeleteEnabled(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFEWorkspaceExists( + "tfe_workspace.foobar", workspace, testAccProvider), + resource.TestCheckNoResourceAttr("tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days"), + ), + }, + }, + }) +} + +func TestAccTFEWorkspace_importDataRetentionPolicy(t *testing.T) { + skipIfCloud(t) + + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckTFEWorkspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFEWorkspace_dataRetentionPolicy(rInt, 10), + }, + { + ResourceName: "tfe_workspace.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_delete"}, + }, + { + ResourceName: "tfe_workspace.foobar", + ImportState: true, + ImportStateId: fmt.Sprintf("tst-terraform-%d/workspace-test", rInt), + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_delete"}, + }, + }, + }) +} + func TestAccTFEWorkspace_updateGitHubAppRepo(t *testing.T) { workspace := &tfe.Workspace{} rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() @@ -3655,3 +3732,20 @@ func testAccTFEWorkspace_mismatchOrganization() string { description = "My favorite workspace!" }` } + +func testAccTFEWorkspace_dataRetentionPolicy(rInt int, deleteOlderThanNDays int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_workspace" "foobar" { + name = "workspace-test" + organization = tfe_organization.foobar.id + data_retention_policy { + delete_older_than_n_days = %d + } +} +`, rInt, deleteOlderThanNDays) +} diff --git a/website/docs/r/workspace.html.markdown b/website/docs/r/workspace.html.markdown index e314fe4ce..008b620d3 100644 --- a/website/docs/r/workspace.html.markdown +++ b/website/docs/r/workspace.html.markdown @@ -68,6 +68,7 @@ The following arguments are supported: * `assessments_enabled` - (Optional) Whether to regularly run health assessments such as drift detection on the workspace. Defaults to `false`. * `auto_apply` - (Optional) Whether to automatically apply changes when a Terraform plan is successful. Defaults to `false`. * `auto_apply_run_trigger` - (Optional) Whether to automatically apply changes for runs that were created by run triggers from another workspace. Defaults to `false`. +* `data_retention_policy` - (Optional) The workspace's [data retention policy](https://developer.hashicorp.com/terraform/enterprise/workspaces/settings/deletion#data-retention-policies). * `description` - (Optional) A description for the workspace. * `execution_mode` - (Optional) **Deprecated** Which [execution mode](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/settings#execution-mode) to use. Use [tfe_workspace_settings](workspace_settings) instead. * `file_triggers_enabled` - (Optional) Whether to filter runs based on the changed files @@ -127,6 +128,10 @@ The following arguments are supported: workflows, where runs are not driven by webhooks on your VCS provider. * `working_directory` - (Optional) A relative path that Terraform will execute within. Defaults to the root of your repository. +The `data_retention_policy` block supports: + +* `delete_older_than_n_days` - (Required) Automatically delete backing data for state versions and configuration versions older than N days. + The `vcs_repo` block supports: * `identifier` - (Required) A reference to your VCS repository in the format From f2b1c8e6b1b165c9afdfba1c22ac671144218449 Mon Sep 17 00:00:00 2001 From: Manuel Wudka-Robles Date: Wed, 13 Dec 2023 17:10:00 -0800 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 506c74233..089d8f299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ FEATURES: * **New Resource**: `r/tfe_registry_gpg_key` is a new resource for managing private registry GPG keys, by @tmatilai [1160](https://github.com/hashicorp/terraform-provider-tfe/pull/1160) * **New Data Source**: `d/tfe_registry_gpg_key` is a new data source to retrieve a private registry GPG key, by @tmatilai [1160](https://github.com/hashicorp/terraform-provider-tfe/pull/1160) * **New Data Source**: `d/tfe_registry_gpg_keys` is a new data source to retrieve all private registry GPG keys of an organization, by @tmatilai [1160](https://github.com/hashicorp/terraform-provider-tfe/pull/1160) +* `r/tfe_workspace`: Add `data_retention_policy` attribute to allow configuration of a workspace's data retention policy, by @mwudka [1170](https://github.com/hashicorp/terraform-provider-tfe/pull/1170) +* `r/tfe_organization`: Add `data_retention_policy` attribute to allow configuration of an organization's data retention policy, by @mwudka [1170](https://github.com/hashicorp/terraform-provider-tfe/pull/1170) ENHANCEMENTS: * `d/tfe_organization`: Make `name` argument optional if configured for the provider, by @tmatilai [1133](https://github.com/hashicorp/terraform-provider-tfe/pull/1133)