Skip to content

Commit 836fff1

Browse files
committed
Add data retention policy block to workspace resource
1 parent 739e009 commit 836fff1

File tree

4 files changed

+173
-0
lines changed

4 files changed

+173
-0
lines changed

internal/provider/client_mock_workspaces.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,15 @@ func (m *mockWorkspaces) SafeDelete(ctx context.Context, organization string, wo
172172
func (m *mockWorkspaces) SafeDeleteByID(ctx context.Context, workspaceID string) error {
173173
panic("not implemented")
174174
}
175+
176+
func (m *mockWorkspaces) ReadDataRetentionPolicy(ctx context.Context, workspaceID string) (*tfe.DataRetentionPolicy, error) {
177+
panic("not implemented")
178+
}
179+
180+
func (m *mockWorkspaces) SetDataRetentionPolicy(ctx context.Context, workspaceID string, options tfe.DataRetentionPolicySetOptions) (*tfe.DataRetentionPolicy, error) {
181+
panic("not implemented")
182+
}
183+
184+
func (m *mockWorkspaces) DeleteDataRetentionPolicy(ctx context.Context, workspaceID string) error {
185+
panic("not implemented")
186+
}

internal/provider/resource_tfe_workspace.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,21 @@ func resourceTFEWorkspace() *schema.Resource {
230230
Default: "",
231231
},
232232

233+
"data_retention_policy": {
234+
Type: schema.TypeList,
235+
Optional: true,
236+
MinItems: 1,
237+
MaxItems: 1,
238+
Elem: &schema.Resource{
239+
Schema: map[string]*schema.Schema{
240+
"delete_older_than_n_days": {
241+
Type: schema.TypeInt,
242+
Required: true,
243+
},
244+
},
245+
},
246+
},
247+
233248
"vcs_repo": {
234249
Type: schema.TypeList,
235250
Optional: true,
@@ -428,6 +443,18 @@ func resourceTFEWorkspaceCreate(d *schema.ResourceData, meta interface{}) error
428443

429444
d.SetId(workspace.ID)
430445

446+
if v, ok := d.GetOk("data_retention_policy"); ok {
447+
drp := v.([]interface{})[0].(map[string]interface{})
448+
449+
_, err = config.Client.Workspaces.SetDataRetentionPolicy(ctx, workspace.ID, tfe.DataRetentionPolicySetOptions{
450+
DeleteOlderThanNDays: drp["delete_older_than_n_days"].(int),
451+
})
452+
453+
if err != nil {
454+
return fmt.Errorf("Error setting data retention policy on workspace %s: %w", name, err)
455+
}
456+
}
457+
431458
if sshKeyID, ok := d.GetOk("ssh_key_id"); ok {
432459
_, err = config.Client.Workspaces.AssignSSHKey(ctx, workspace.ID, tfe.WorkspaceAssignSSHKeyOptions{
433460
SSHKeyID: tfe.String(sshKeyID.(string)),
@@ -542,6 +569,22 @@ func resourceTFEWorkspaceRead(d *schema.ResourceData, meta interface{}) error {
542569

543570
d.Set("vcs_repo", vcsRepo)
544571

572+
var dataRetentionPolicy []interface{}
573+
if workspace.DataRetentionPolicy != nil {
574+
policy, err := config.Client.Workspaces.ReadDataRetentionPolicy(ctx, id)
575+
576+
if err != nil {
577+
return fmt.Errorf(
578+
"Error data retention policy for workspace %s: %w", id, err)
579+
}
580+
581+
drp := map[string]interface{}{
582+
"delete_older_than_n_days": policy.DeleteOlderThanNDays,
583+
}
584+
dataRetentionPolicy = append(dataRetentionPolicy, drp)
585+
}
586+
d.Set("data_retention_policy", dataRetentionPolicy)
587+
545588
if workspace.GlobalRemoteState {
546589
d.Set("global_remote_state", true)
547590
} else {
@@ -734,6 +777,25 @@ func resourceTFEWorkspaceUpdate(d *schema.ResourceData, meta interface{}) error
734777
}
735778
}
736779

780+
// nolint: nestif
781+
if d.HasChange("data_retention_policy") {
782+
v, ok := d.GetOk("data_retention_policy")
783+
if ok {
784+
drp := v.([]interface{})[0].(map[string]interface{})
785+
_, err := config.Client.Workspaces.SetDataRetentionPolicy(ctx, id, tfe.DataRetentionPolicySetOptions{DeleteOlderThanNDays: drp["delete_older_than_n_days"].(int)})
786+
if err != nil {
787+
d.Partial(true)
788+
return fmt.Errorf("Error setting data retention policy on workspace %s: %w", d.Id(), err)
789+
}
790+
} else {
791+
err := config.Client.Workspaces.DeleteDataRetentionPolicy(ctx, id)
792+
if err != nil {
793+
d.Partial(true)
794+
return fmt.Errorf("Error deleting data retention policy from workspace %s: %w", d.Id(), err)
795+
}
796+
}
797+
}
798+
737799
if d.HasChange("tag_names") {
738800
oldTagNameValues, newTagNameValues := d.GetChange("tag_names")
739801
newTagNamesSet := newTagNameValues.(*schema.Set)

internal/provider/resource_tfe_workspace_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,83 @@ func TestAccTFEWorkspace_updateVCSRepo(t *testing.T) {
14841484
})
14851485
}
14861486

1487+
func TestAccTFEWorkspace_updateDataRetentionPolicy(t *testing.T) {
1488+
skipIfCloud(t)
1489+
1490+
workspace := &tfe.Workspace{}
1491+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
1492+
1493+
resource.Test(t, resource.TestCase{
1494+
PreCheck: func() {
1495+
testAccPreCheck(t)
1496+
},
1497+
Providers: testAccProviders,
1498+
CheckDestroy: testAccCheckTFEWorkspaceDestroy,
1499+
Steps: []resource.TestStep{
1500+
{
1501+
Config: testAccTFEWorkspace_basicForceDeleteEnabled(rInt),
1502+
Check: resource.ComposeTestCheckFunc(
1503+
testAccCheckTFEWorkspaceExists(
1504+
"tfe_workspace.foobar", workspace, testAccProvider),
1505+
resource.TestCheckNoResourceAttr("tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days"),
1506+
),
1507+
},
1508+
{
1509+
Config: testAccTFEWorkspace_dataRetentionPolicy(rInt, 8),
1510+
Check: resource.ComposeTestCheckFunc(
1511+
resource.TestCheckResourceAttr(
1512+
"tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days", "8"),
1513+
),
1514+
},
1515+
{
1516+
Config: testAccTFEWorkspace_dataRetentionPolicy(rInt, 20),
1517+
Check: resource.ComposeTestCheckFunc(
1518+
resource.TestCheckResourceAttr(
1519+
"tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days", "20"),
1520+
),
1521+
},
1522+
{
1523+
Config: testAccTFEWorkspace_basicForceDeleteEnabled(rInt),
1524+
Check: resource.ComposeTestCheckFunc(
1525+
testAccCheckTFEWorkspaceExists(
1526+
"tfe_workspace.foobar", workspace, testAccProvider),
1527+
resource.TestCheckNoResourceAttr("tfe_workspace.foobar", "data_retention_policy.0.delete_older_than_n_days"),
1528+
),
1529+
},
1530+
},
1531+
})
1532+
}
1533+
1534+
func TestAccTFEWorkspace_importDataRetentionPolicy(t *testing.T) {
1535+
skipIfCloud(t)
1536+
1537+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
1538+
1539+
resource.Test(t, resource.TestCase{
1540+
PreCheck: func() { testAccPreCheck(t) },
1541+
Providers: testAccProviders,
1542+
CheckDestroy: testAccCheckTFEWorkspaceDestroy,
1543+
Steps: []resource.TestStep{
1544+
{
1545+
Config: testAccTFEWorkspace_dataRetentionPolicy(rInt, 10),
1546+
},
1547+
{
1548+
ResourceName: "tfe_workspace.foobar",
1549+
ImportState: true,
1550+
ImportStateVerify: true,
1551+
ImportStateVerifyIgnore: []string{"force_delete"},
1552+
},
1553+
{
1554+
ResourceName: "tfe_workspace.foobar",
1555+
ImportState: true,
1556+
ImportStateId: fmt.Sprintf("tst-terraform-%d/workspace-test", rInt),
1557+
ImportStateVerify: true,
1558+
ImportStateVerifyIgnore: []string{"force_delete"},
1559+
},
1560+
},
1561+
})
1562+
}
1563+
14871564
func TestAccTFEWorkspace_updateGitHubAppRepo(t *testing.T) {
14881565
workspace := &tfe.Workspace{}
14891566
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
@@ -3655,3 +3732,20 @@ func testAccTFEWorkspace_mismatchOrganization() string {
36553732
description = "My favorite workspace!"
36563733
}`
36573734
}
3735+
3736+
func testAccTFEWorkspace_dataRetentionPolicy(rInt int, deleteOlderThanNDays int) string {
3737+
return fmt.Sprintf(`
3738+
resource "tfe_organization" "foobar" {
3739+
name = "tst-terraform-%d"
3740+
3741+
}
3742+
3743+
resource "tfe_workspace" "foobar" {
3744+
name = "workspace-test"
3745+
organization = tfe_organization.foobar.id
3746+
data_retention_policy {
3747+
delete_older_than_n_days = %d
3748+
}
3749+
}
3750+
`, rInt, deleteOlderThanNDays)
3751+
}

website/docs/r/workspace.html.markdown

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ The following arguments are supported:
6868
* `assessments_enabled` - (Optional) Whether to regularly run health assessments such as drift detection on the workspace. Defaults to `false`.
6969
* `auto_apply` - (Optional) Whether to automatically apply changes when a Terraform plan is successful. Defaults to `false`.
7070
* `auto_apply_run_trigger` - (Optional) Whether to automatically apply changes for runs that were created by run triggers from another workspace. Defaults to `false`.
71+
* `data_retention_policy` - (Optional) The workspace's [data retention policy](https://developer.hashicorp.com/terraform/enterprise/workspaces/settings/deletion#data-retention-policies).
7172
* `description` - (Optional) A description for the workspace.
7273
* `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.
7374
* `file_triggers_enabled` - (Optional) Whether to filter runs based on the changed files
@@ -127,6 +128,10 @@ The following arguments are supported:
127128
workflows, where runs are not driven by webhooks on your VCS provider.
128129
* `working_directory` - (Optional) A relative path that Terraform will execute within. Defaults to the root of your repository.
129130

131+
The `data_retention_policy` block supports:
132+
133+
* `delete_older_than_n_days` - (Required) Automatically delete backing data for state versions and configuration versions older than N days.
134+
130135
The `vcs_repo` block supports:
131136

132137
* `identifier` - (Required) A reference to your VCS repository in the format

0 commit comments

Comments
 (0)