Skip to content

Commit 481bfa8

Browse files
author
Manuel Wudka-Robles
authored
Merge pull request #817 from hashicorp/mwudka/TF-8621-data-retention-policy-management-endpoints
Allow managing data retention policies
2 parents 375bcdc + 1f615d0 commit 481bfa8

8 files changed

+356
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# UNRELEASED
2+
* Allow managing workspace and organization data retention policies by @mwudka [#801](https://github.com/hashicorp/go-tfe/pull/817)
23

34
# v1.40.0
45

data_retention_policy.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package tfe
5+
6+
type DataRetentionPolicy struct {
7+
ID string `jsonapi:"primary,data-retention-policies"`
8+
DeleteOlderThanNDays int `jsonapi:"attr,delete-older-than-n-days"`
9+
}
10+
11+
type DataRetentionPolicySetOptions struct {
12+
// Type is a public field utilized by JSON:API to
13+
// set the resource type via the field tag.
14+
// It is not a user-defined value and does not need to be set.
15+
// https://jsonapi.org/format/#crud-creating
16+
Type string `jsonapi:"primary,data-retention-policies"`
17+
18+
DeleteOlderThanNDays int `jsonapi:"attr,delete-older-than-n-days"`
19+
}

mocks/organization_mocks.go

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mocks/workspace_mocks.go

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

organization.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ type Organizations interface {
4545

4646
// ReadRunQueue shows the current run queue of an organization.
4747
ReadRunQueue(ctx context.Context, organization string, options ReadRunQueueOptions) (*RunQueue, error)
48+
49+
// ReadDataRetentionPolicy reads an organization's data retention policy
50+
// **Note: This functionality is only available in Terraform Enterprise.**
51+
ReadDataRetentionPolicy(ctx context.Context, organization string) (*DataRetentionPolicy, error)
52+
53+
// SetDataRetentionPolicy sets an organization's data retention policy
54+
// **Note: This functionality is only available in Terraform Enterprise.**
55+
SetDataRetentionPolicy(ctx context.Context, organization string, options DataRetentionPolicySetOptions) (*DataRetentionPolicy, error)
56+
57+
// DeleteDataRetentionPolicy deletes an organization's data retention policy
58+
// **Note: This functionality is only available in Terraform Enterprise.**
59+
DeleteDataRetentionPolicy(ctx context.Context, organization string) error
4860
}
4961

5062
// organizations implements Organizations.
@@ -93,6 +105,9 @@ type Organization struct {
93105
// Relations
94106
DefaultProject *Project `jsonapi:"relation,default-project"`
95107
DefaultAgentPool *AgentPool `jsonapi:"relation,default-agent-pool"`
108+
109+
// **Note: This functionality is only available in Terraform Enterprise.**
110+
DataRetentionPolicy *DataRetentionPolicy `jsonapi:"relation,data-retention-policy"`
96111
}
97112

98113
// OrganizationIncludeOpt represents the available options for include query params.
@@ -416,6 +431,62 @@ func (s *organizations) ReadRunQueue(ctx context.Context, organization string, o
416431
return rq, nil
417432
}
418433

434+
func (s *organizations) ReadDataRetentionPolicy(ctx context.Context, organization string) (*DataRetentionPolicy, error) {
435+
if !validStringID(&organization) {
436+
return nil, ErrInvalidOrg
437+
}
438+
439+
u := fmt.Sprintf("organizations/%s/relationships/data-retention-policy", url.QueryEscape(organization))
440+
req, err := s.client.NewRequest("GET", u, nil)
441+
if err != nil {
442+
return nil, err
443+
}
444+
445+
dataRetentionPolicy := &DataRetentionPolicy{}
446+
err = req.Do(ctx, dataRetentionPolicy)
447+
448+
if err != nil {
449+
return nil, err
450+
}
451+
452+
return dataRetentionPolicy, nil
453+
}
454+
455+
func (s *organizations) SetDataRetentionPolicy(ctx context.Context, organization string, options DataRetentionPolicySetOptions) (*DataRetentionPolicy, error) {
456+
if !validStringID(&organization) {
457+
return nil, ErrInvalidOrg
458+
}
459+
460+
u := fmt.Sprintf("organizations/%s/relationships/data-retention-policy", url.QueryEscape(organization))
461+
req, err := s.client.NewRequest("PATCH", u, &options)
462+
if err != nil {
463+
return nil, err
464+
}
465+
466+
dataRetentionPolicy := &DataRetentionPolicy{}
467+
err = req.Do(ctx, dataRetentionPolicy)
468+
469+
if err != nil {
470+
return nil, err
471+
}
472+
473+
return dataRetentionPolicy, nil
474+
}
475+
476+
func (s *organizations) DeleteDataRetentionPolicy(ctx context.Context, organization string) error {
477+
if !validStringID(&organization) {
478+
return ErrInvalidOrg
479+
}
480+
481+
u := fmt.Sprintf("organizations/%s/relationships/data-retention-policy", url.QueryEscape(organization))
482+
req, err := s.client.NewRequest("DELETE", u, nil)
483+
if err != nil {
484+
return err
485+
}
486+
487+
return req.Do(ctx, nil)
488+
}
489+
419490
func (o OrganizationCreateOptions) valid() error {
420491
if !validString(o.Name) {
421492
return ErrRequiredName

organization_integration_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,59 @@ func TestOrganizationsAllowForceDeleteSetting(t *testing.T) {
654654
})
655655
}
656656

657+
func TestOrganization_DataRetentionPolicy(t *testing.T) {
658+
skipUnlessEnterprise(t)
659+
660+
client := testClient(t)
661+
ctx := context.Background()
662+
663+
orgTest, orgTestCleanup := createOrganization(t, client)
664+
t.Cleanup(orgTestCleanup)
665+
666+
dataRetentionPolicy, err := client.Organizations.ReadDataRetentionPolicy(ctx, orgTest.Name)
667+
assert.Equal(t, ErrResourceNotFound, err)
668+
require.Nil(t, dataRetentionPolicy)
669+
670+
organization, err := client.Organizations.Read(ctx, orgTest.Name)
671+
require.NoError(t, err)
672+
require.Nil(t, organization.DataRetentionPolicy)
673+
674+
t.Run("set data retention policy", func(t *testing.T) {
675+
createdDataRetentionPolicy, err := client.Organizations.SetDataRetentionPolicy(ctx, orgTest.Name, DataRetentionPolicySetOptions{DeleteOlderThanNDays: 33})
676+
require.NoError(t, err)
677+
require.Equal(t, 33, createdDataRetentionPolicy.DeleteOlderThanNDays)
678+
require.Contains(t, createdDataRetentionPolicy.ID, "drp-")
679+
680+
dataRetentionPolicy, err = client.Organizations.ReadDataRetentionPolicy(ctx, orgTest.Name)
681+
require.NoError(t, err)
682+
require.Equal(t, 33, dataRetentionPolicy.DeleteOlderThanNDays)
683+
require.Equal(t, createdDataRetentionPolicy.ID, dataRetentionPolicy.ID)
684+
require.Contains(t, dataRetentionPolicy.ID, "drp-")
685+
686+
organization, err := client.Organizations.Read(ctx, orgTest.Name)
687+
require.NoError(t, err)
688+
require.Equal(t, dataRetentionPolicy.ID, organization.DataRetentionPolicy.ID)
689+
})
690+
691+
t.Run("update data retention policy", func(t *testing.T) {
692+
_, err = client.Organizations.SetDataRetentionPolicy(ctx, orgTest.Name, DataRetentionPolicySetOptions{DeleteOlderThanNDays: 45})
693+
require.NoError(t, err)
694+
695+
dataRetentionPolicy, err = client.Organizations.ReadDataRetentionPolicy(ctx, orgTest.Name)
696+
require.NoError(t, err)
697+
require.Equal(t, 45, dataRetentionPolicy.DeleteOlderThanNDays)
698+
})
699+
700+
t.Run("delete data retention policy", func(t *testing.T) {
701+
err = client.Organizations.DeleteDataRetentionPolicy(ctx, orgTest.Name)
702+
require.NoError(t, err)
703+
704+
dataRetentionPolicy, err = client.Organizations.ReadDataRetentionPolicy(ctx, orgTest.Name)
705+
assert.Equal(t, ErrResourceNotFound, err)
706+
require.Nil(t, dataRetentionPolicy)
707+
})
708+
}
709+
657710
func orgItemsContainsName(items []*Organization, name string) bool {
658711
hasName := false
659712
for _, item := range items {

workspace.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,18 @@ type Workspaces interface {
101101

102102
// RemoveTags removes tags from a workspace
103103
RemoveTags(ctx context.Context, workspaceID string, options WorkspaceRemoveTagsOptions) error
104+
105+
// ReadDataRetentionPolicy reads a workspace's data retention policy
106+
// **Note: This functionality is only available in Terraform Enterprise.**
107+
ReadDataRetentionPolicy(ctx context.Context, workspaceID string) (*DataRetentionPolicy, error)
108+
109+
// SetDataRetentionPolicy sets a workspace's data retention policy
110+
// **Note: This functionality is only available in Terraform Enterprise.**
111+
SetDataRetentionPolicy(ctx context.Context, workspaceID string, options DataRetentionPolicySetOptions) (*DataRetentionPolicy, error)
112+
113+
// DeleteDataRetentionPolicy deletes a workspace's data retention policy
114+
// **Note: This functionality is only available in Terraform Enterprise.**
115+
DeleteDataRetentionPolicy(ctx context.Context, workspaceID string) error
104116
}
105117

106118
// workspaces implements Workspaces.
@@ -165,6 +177,9 @@ type Workspace struct {
165177
Tags []*Tag `jsonapi:"relation,tags"`
166178
CurrentConfigurationVersion *ConfigurationVersion `jsonapi:"relation,current-configuration-version,omitempty"`
167179

180+
// **Note: This functionality is only available in Terraform Enterprise.**
181+
DataRetentionPolicy *DataRetentionPolicy `jsonapi:"relation,data-retention-policy"`
182+
168183
// Links
169184
Links map[string]interface{} `jsonapi:"links,omitempty"`
170185
}
@@ -1182,6 +1197,62 @@ func (s *workspaces) RemoveTags(ctx context.Context, workspaceID string, options
11821197
return req.Do(ctx, nil)
11831198
}
11841199

1200+
func (s *workspaces) ReadDataRetentionPolicy(ctx context.Context, workspaceID string) (*DataRetentionPolicy, error) {
1201+
if !validStringID(&workspaceID) {
1202+
return nil, ErrInvalidWorkspaceID
1203+
}
1204+
1205+
u := fmt.Sprintf("workspaces/%s/relationships/data-retention-policy", url.QueryEscape(workspaceID))
1206+
req, err := s.client.NewRequest("GET", u, nil)
1207+
if err != nil {
1208+
return nil, err
1209+
}
1210+
1211+
dataRetentionPolicy := &DataRetentionPolicy{}
1212+
err = req.Do(ctx, dataRetentionPolicy)
1213+
1214+
if err != nil {
1215+
return nil, err
1216+
}
1217+
1218+
return dataRetentionPolicy, nil
1219+
}
1220+
1221+
func (s *workspaces) SetDataRetentionPolicy(ctx context.Context, workspaceID string, options DataRetentionPolicySetOptions) (*DataRetentionPolicy, error) {
1222+
if !validStringID(&workspaceID) {
1223+
return nil, ErrInvalidWorkspaceID
1224+
}
1225+
1226+
u := fmt.Sprintf("workspaces/%s/relationships/data-retention-policy", url.QueryEscape(workspaceID))
1227+
req, err := s.client.NewRequest("PATCH", u, &options)
1228+
if err != nil {
1229+
return nil, err
1230+
}
1231+
1232+
dataRetentionPolicy := &DataRetentionPolicy{}
1233+
err = req.Do(ctx, dataRetentionPolicy)
1234+
1235+
if err != nil {
1236+
return nil, err
1237+
}
1238+
1239+
return dataRetentionPolicy, nil
1240+
}
1241+
1242+
func (s *workspaces) DeleteDataRetentionPolicy(ctx context.Context, workspaceID string) error {
1243+
if !validStringID(&workspaceID) {
1244+
return ErrInvalidWorkspaceID
1245+
}
1246+
1247+
u := fmt.Sprintf("workspaces/%s/relationships/data-retention-policy", url.QueryEscape(workspaceID))
1248+
req, err := s.client.NewRequest("DELETE", u, nil)
1249+
if err != nil {
1250+
return err
1251+
}
1252+
1253+
return req.Do(ctx, nil)
1254+
}
1255+
11851256
func (o WorkspaceCreateOptions) valid() error {
11861257
if !validString(o.Name) {
11871258
return ErrRequiredName

0 commit comments

Comments
 (0)