Skip to content

Commit d388f7e

Browse files
authored
Merge pull request #996 from hashicorp/TF-21917-go-tfe-support-for-effective-tag-bindings
Adds ListEffectiveTagBindings to Workspaces/Projects
2 parents 1318444 + 169df9b commit d388f7e

File tree

8 files changed

+144
-1
lines changed

8 files changed

+144
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Unreleased
22

3+
## Enhancements
4+
5+
* Add support for listing effective tag bindings for a workspace or project by @brandonc
6+
37
# v1.69.0
48

59
## Enhancements

mocks/project_mocks.go

Lines changed: 15 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: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

project.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ type Projects interface {
3535
// ListTagBindings lists all tag bindings associated with the project.
3636
ListTagBindings(ctx context.Context, projectID string) ([]*TagBinding, error)
3737

38+
// ListEffectiveTagBindings lists all tag bindings associated with the project. In practice,
39+
// this should be the same as ListTagBindings since projects do not currently inherit
40+
// tag bindings.
41+
ListEffectiveTagBindings(ctx context.Context, workspaceID string) ([]*EffectiveTagBinding, error)
42+
3843
// AddTagBindings adds or modifies the value of existing tag binding keys for a project.
3944
AddTagBindings(ctx context.Context, projectID string, options ProjectAddTagBindingsOptions) ([]*TagBinding, error)
4045
}
@@ -218,6 +223,30 @@ func (s *projects) ListTagBindings(ctx context.Context, projectID string) ([]*Ta
218223
return list.Items, nil
219224
}
220225

226+
func (s *projects) ListEffectiveTagBindings(ctx context.Context, projectID string) ([]*EffectiveTagBinding, error) {
227+
if !validStringID(&projectID) {
228+
return nil, ErrInvalidProjectID
229+
}
230+
231+
u := fmt.Sprintf("projects/%s/effective-tag-bindings", url.PathEscape(projectID))
232+
req, err := s.client.NewRequest("GET", u, nil)
233+
if err != nil {
234+
return nil, err
235+
}
236+
237+
var list struct {
238+
*Pagination
239+
Items []*EffectiveTagBinding
240+
}
241+
242+
err = req.Do(ctx, &list)
243+
if err != nil {
244+
return nil, err
245+
}
246+
247+
return list.Items, nil
248+
}
249+
221250
// AddTagBindings adds or modifies the value of existing tag binding keys for a project
222251
func (s *projects) AddTagBindings(ctx context.Context, projectID string, options ProjectAddTagBindingsOptions) ([]*TagBinding, error) {
223252
if !validStringID(&projectID) {

projects_integration_test.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func TestProjectsUpdate(t *testing.T) {
204204

205205
t.Run("with valid options", func(t *testing.T) {
206206
kBefore, kTestCleanup := createProject(t, client, orgTest)
207-
defer kTestCleanup()
207+
t.Cleanup(kTestCleanup)
208208

209209
kAfter, err := client.Projects.Update(ctx, kBefore.ID, ProjectUpdateOptions{
210210
Name: String("new project name"),
@@ -226,6 +226,45 @@ func TestProjectsUpdate(t *testing.T) {
226226
assert.Len(t, bindings, 1)
227227
assert.Equal(t, "foo", bindings[0].Key)
228228
assert.Equal(t, "bar", bindings[0].Value)
229+
230+
effectiveBindings, err := client.Projects.ListEffectiveTagBindings(ctx, kAfter.ID)
231+
require.NoError(t, err)
232+
233+
assert.Len(t, effectiveBindings, 1)
234+
assert.Equal(t, "foo", effectiveBindings[0].Key)
235+
assert.Equal(t, "bar", effectiveBindings[0].Value)
236+
237+
ws, err := client.Workspaces.Create(ctx, orgTest.Name, WorkspaceCreateOptions{
238+
Name: String("new-workspace-inherits-tags"),
239+
Project: kAfter,
240+
TagBindings: []*TagBinding{
241+
{Key: "baz", Value: "qux"},
242+
},
243+
})
244+
require.NoError(t, err)
245+
246+
t.Cleanup(func() {
247+
err := client.Workspaces.DeleteByID(ctx, ws.ID)
248+
if err != nil {
249+
t.Errorf("Error destroying workspace! WARNING: Dangling resources\n"+
250+
"may exist! The full error is shown below.\n\n"+
251+
"Error: %s", err)
252+
}
253+
})
254+
255+
wsEffectiveBindings, err := client.Workspaces.ListEffectiveTagBindings(ctx, ws.ID)
256+
require.NoError(t, err)
257+
258+
assert.Len(t, wsEffectiveBindings, 2)
259+
for _, b := range wsEffectiveBindings {
260+
if b.Key == "foo" {
261+
assert.Equal(t, "bar", b.Value)
262+
} else if b.Key == "baz" {
263+
assert.Equal(t, "qux", b.Value)
264+
} else {
265+
assert.Fail(t, "unexpected tag binding %q", b.Key)
266+
}
267+
}
229268
}
230269
})
231270

tag.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ type TagBinding struct {
2222
Value string `jsonapi:"attr,value,omitempty"`
2323
}
2424

25+
type EffectiveTagBinding struct {
26+
ID string `jsonapi:"primary,effective-tag-bindings"`
27+
Key string `jsonapi:"attr,key"`
28+
Value string `jsonapi:"attr,value,omitempty"`
29+
}
30+
2531
func encodeTagFiltersAsParams(filters []*TagBinding) map[string][]string {
2632
if len(filters) == 0 {
2733
return nil

workspace.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ type Workspaces interface {
135135
// ListTagBindings lists all tag bindings associated with the workspace.
136136
ListTagBindings(ctx context.Context, workspaceID string) ([]*TagBinding, error)
137137

138+
// ListEffectiveTagBindings lists all tag bindings associated with the workspace which may be
139+
// either inherited from a project or binded to the workspace itself.
140+
ListEffectiveTagBindings(ctx context.Context, workspaceID string) ([]*EffectiveTagBinding, error)
141+
138142
// AddTagBindings adds or modifies the value of existing tag binding keys for a workspace.
139143
AddTagBindings(ctx context.Context, workspaceID string, options WorkspaceAddTagBindingsOptions) ([]*TagBinding, error)
140144
}
@@ -769,6 +773,30 @@ func (s *workspaces) ListTagBindings(ctx context.Context, workspaceID string) ([
769773
return list.Items, nil
770774
}
771775

776+
func (s *workspaces) ListEffectiveTagBindings(ctx context.Context, workspaceID string) ([]*EffectiveTagBinding, error) {
777+
if !validStringID(&workspaceID) {
778+
return nil, ErrInvalidWorkspaceID
779+
}
780+
781+
u := fmt.Sprintf("workspaces/%s/effective-tag-bindings", url.PathEscape(workspaceID))
782+
req, err := s.client.NewRequest("GET", u, nil)
783+
if err != nil {
784+
return nil, err
785+
}
786+
787+
var list struct {
788+
*Pagination
789+
Items []*EffectiveTagBinding
790+
}
791+
792+
err = req.Do(ctx, &list)
793+
if err != nil {
794+
return nil, err
795+
}
796+
797+
return list.Items, nil
798+
}
799+
772800
// AddTagBindings adds or modifies the value of existing tag binding keys for a workspace.
773801
func (s *workspaces) AddTagBindings(ctx context.Context, workspaceID string, options WorkspaceAddTagBindingsOptions) ([]*TagBinding, error) {
774802
if !validStringID(&workspaceID) {

workspace_integration_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,13 @@ func TestWorkspacesUpdate(t *testing.T) {
13731373
assert.Len(t, bindings, 1)
13741374
assert.Equal(t, "foo", bindings[0].Key)
13751375
assert.Equal(t, "bar", bindings[0].Value)
1376+
1377+
effectiveBindings, err := client.Workspaces.ListEffectiveTagBindings(ctx, wTest.ID)
1378+
require.NoError(t, err)
1379+
1380+
assert.Len(t, effectiveBindings, 1)
1381+
assert.Equal(t, "foo", effectiveBindings[0].Key)
1382+
assert.Equal(t, "bar", effectiveBindings[0].Value)
13761383
}
13771384
})
13781385

0 commit comments

Comments
 (0)