Skip to content

Commit

Permalink
Merge pull request #1023 from hashicorp/sebasslash/remove-tag-bindings
Browse files Browse the repository at this point in the history
Add support to remove tag bindings from projects/workspaces
  • Loading branch information
sebasslash authored Jan 6, 2025
2 parents 9e23f0e + e1ea9cb commit 4344019
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

* Add support for project level auto destroy settings @simonxmh [#1011](https://github.com/hashicorp/go-tfe/pull/1011)
* Add BETA support for Linux arm64 agents, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users @natalie-todd [#1022](https://github.com/hashicorp/go-tfe/pull/1022)

* Adds support to delete all tag bindings on either a project or workspace by @sebasslash [#1023](https://github.com/hashicorp/go-tfe/pull/1023)

# v1.71.0

## Enhancements
Expand Down
14 changes: 14 additions & 0 deletions mocks/project_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions mocks/workspace_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions project.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ type Projects interface {

// AddTagBindings adds or modifies the value of existing tag binding keys for a project.
AddTagBindings(ctx context.Context, projectID string, options ProjectAddTagBindingsOptions) ([]*TagBinding, error)

// DeleteAllTagBindings removes all existing tag bindings for a project.
DeleteAllTagBindings(ctx context.Context, projectID string) error
}

// projects implements Projects
Expand Down Expand Up @@ -326,6 +329,30 @@ func (s *projects) Delete(ctx context.Context, projectID string) error {
return req.Do(ctx, nil)
}

// Delete all tag bindings associated with a project.
func (s *projects) DeleteAllTagBindings(ctx context.Context, projectID string) error {
if !validStringID(&projectID) {
return ErrInvalidProjectID
}

type aliasOpts struct {
Type string `jsonapi:"primary,projects"`
TagBindings []*TagBinding `jsonapi:"relation,tag-bindings"`
}

opts := &aliasOpts{
TagBindings: []*TagBinding{},
}

u := fmt.Sprintf("projects/%s", url.PathEscape(projectID))
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return err
}

return req.Do(ctx, nil)
}

func (o ProjectCreateOptions) valid() error {
if !validString(&o.Name) {
return ErrRequiredName
Expand Down
27 changes: 27 additions & 0 deletions projects_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,33 @@ func TestProjectsAddTagBindings(t *testing.T) {
})
}

func TestProjects_DeleteAllTagBindings(t *testing.T) {
skipUnlessBeta(t)

client := testClient(t)
ctx := context.Background()

pTest, wCleanup := createProject(t, client, nil)
t.Cleanup(wCleanup)

tagBindings := []*TagBinding{
{Key: "foo", Value: "bar"},
{Key: "baz", Value: "qux"},
}

_, err := client.Projects.AddTagBindings(ctx, pTest.ID, ProjectAddTagBindingsOptions{
TagBindings: tagBindings,
})
require.NoError(t, err)

err = client.Projects.DeleteAllTagBindings(ctx, pTest.ID)
require.NoError(t, err)

bindings, err := client.Projects.ListTagBindings(ctx, pTest.ID)
require.NoError(t, err)
require.Empty(t, bindings)
}

func TestProjectsDelete(t *testing.T) {
client := testClient(t)
ctx := context.Background()
Expand Down
29 changes: 29 additions & 0 deletions workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ type Workspaces interface {

// AddTagBindings adds or modifies the value of existing tag binding keys for a workspace.
AddTagBindings(ctx context.Context, workspaceID string, options WorkspaceAddTagBindingsOptions) ([]*TagBinding, error)

// DeleteAllTagBindings removes all tag bindings for a workspace.
DeleteAllTagBindings(ctx context.Context, workspaceID string) error
}

// workspaces implements Workspaces.
Expand Down Expand Up @@ -829,6 +832,32 @@ func (s *workspaces) AddTagBindings(ctx context.Context, workspaceID string, opt
return response.Items, err
}

// DeleteAllTagBindings removes all tag bindings associated with a workspace.
// This method will not remove any inherited tag bindings, which must be
// explicitly removed from the parent project.
func (s *workspaces) DeleteAllTagBindings(ctx context.Context, workspaceID string) error {
if !validStringID(&workspaceID) {
return ErrInvalidWorkspaceID
}

type aliasOpts struct {
Type string `jsonapi:"primary,workspaces"`
TagBindings []*TagBinding `jsonapi:"relation,tag-bindings"`
}

opts := &aliasOpts{
TagBindings: []*TagBinding{},
}

u := fmt.Sprintf("workspaces/%s", url.PathEscape(workspaceID))
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return err
}

return req.Do(ctx, nil)
}

// Create is used to create a new workspace.
func (s *workspaces) Create(ctx context.Context, organization string, options WorkspaceCreateOptions) (*Workspace, error) {
if !validStringID(&organization) {
Expand Down
27 changes: 27 additions & 0 deletions workspace_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,33 @@ func TestWorkspacesAddTagBindings(t *testing.T) {
})
}

func TestWorkspaces_DeleteAllTagBindings(t *testing.T) {
skipUnlessBeta(t)

client := testClient(t)
ctx := context.Background()

wTest, wCleanup := createWorkspace(t, client, nil)
t.Cleanup(wCleanup)

tagBindings := []*TagBinding{
{Key: "foo", Value: "bar"},
{Key: "baz", Value: "qux"},
}

_, err := client.Workspaces.AddTagBindings(ctx, wTest.ID, WorkspaceAddTagBindingsOptions{
TagBindings: tagBindings,
})
require.NoError(t, err)

err = client.Workspaces.DeleteAllTagBindings(ctx, wTest.ID)
require.NoError(t, err)

bindings, err := client.Workspaces.ListTagBindings(ctx, wTest.ID)
require.NoError(t, err)
require.Empty(t, bindings)
}

func TestWorkspacesUpdate(t *testing.T) {
client := testClient(t)
ctx := context.Background()
Expand Down

0 comments on commit 4344019

Please sign in to comment.