From 1c3ddd93aa06a6f1f8970dac094e275bd0a8a1a2 Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Thu, 23 Jan 2025 16:12:57 -0500 Subject: [PATCH 1/2] Add effective tag binding include relation --- project.go | 12 +++++++++++- projects_integration_test.go | 27 +++++++++++++++++++++++++++ workspace.go | 26 ++++++++++++++------------ workspace_integration_test.go | 27 +++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 13 deletions(-) diff --git a/project.go b/project.go index 433549f3d..8bcc73518 100644 --- a/project.go +++ b/project.go @@ -71,9 +71,16 @@ type Project struct { AutoDestroyActivityDuration jsonapi.NullableAttr[string] `jsonapi:"attr,auto-destroy-activity-duration,omitempty"` // Relations - Organization *Organization `jsonapi:"relation,organization"` + Organization *Organization `jsonapi:"relation,organization"` + EffectiveTagBindings []*EffectiveTagBinding `jsonapi:"relation,effective-tag-bindings"` } +type ProjectIncludeOpt string + +const ( + ProjectEffectiveTagBindings ProjectIncludeOpt = "effective_tag_bindings" +) + // ProjectListOptions represents the options for listing projects type ProjectListOptions struct { ListOptions @@ -89,6 +96,9 @@ type ProjectListOptions struct { // Optional: A filter string to list projects filtered by key/value tags. // These are not annotated and therefore not encoded by go-querystring TagBindings []*TagBinding + + // Optional: A list of relations to include + Include []ProjectIncludeOpt `url:"include,omitempty"` } // ProjectCreateOptions represents the options for creating a project diff --git a/projects_integration_test.go b/projects_integration_test.go index b84a9e869..2bb0cdaa7 100644 --- a/projects_integration_test.go +++ b/projects_integration_test.go @@ -113,6 +113,33 @@ func TestProjectsList(t *testing.T) { assert.Len(t, pl3.Items, 1) assert.Contains(t, pl3.Items, p2) }) + + t.Run("when including effective tags relationship", func(t *testing.T) { + skipUnlessBeta(t) + + orgTest2, orgTest2Cleanup := createOrganization(t, client) + t.Cleanup(orgTest2Cleanup) + + _, pTestCleanup1 := createProjectWithOptions(t, client, orgTest2, ProjectCreateOptions{ + Name: randomStringWithoutSpecialChar(t), + TagBindings: []*TagBinding{ + {Key: "key1", Value: "value1"}, + {Key: "key2", Value: "value2a"}, + }, + }) + t.Cleanup(pTestCleanup1) + + pl, err := client.Projects.List(ctx, orgTest2.Name, &ProjectListOptions{ + Include: []ProjectIncludeOpt{ProjectEffectiveTagBindings}, + }) + require.NoError(t, err) + require.Len(t, pl.Items, 2) + require.Len(t, pl.Items[0].EffectiveTagBindings, 2) + assert.NotEmpty(t, pl.Items[0].EffectiveTagBindings[0].Key) + assert.NotEmpty(t, pl.Items[0].EffectiveTagBindings[0].Value) + assert.NotEmpty(t, pl.Items[0].EffectiveTagBindings[1].Key) + assert.NotEmpty(t, pl.Items[0].EffectiveTagBindings[1].Value) + }) } func TestProjectsRead(t *testing.T) { diff --git a/workspace.go b/workspace.go index be1004686..384a79ce3 100644 --- a/workspace.go +++ b/workspace.go @@ -217,18 +217,19 @@ type Workspace struct { SettingOverwrites *WorkspaceSettingOverwrites `jsonapi:"attr,setting-overwrites"` // Relations - AgentPool *AgentPool `jsonapi:"relation,agent-pool"` - CurrentRun *Run `jsonapi:"relation,current-run"` - CurrentStateVersion *StateVersion `jsonapi:"relation,current-state-version"` - Organization *Organization `jsonapi:"relation,organization"` - SSHKey *SSHKey `jsonapi:"relation,ssh-key"` - Outputs []*WorkspaceOutputs `jsonapi:"relation,outputs"` - Project *Project `jsonapi:"relation,project"` - Tags []*Tag `jsonapi:"relation,tags"` - CurrentConfigurationVersion *ConfigurationVersion `jsonapi:"relation,current-configuration-version,omitempty"` - LockedBy *LockedByChoice `jsonapi:"polyrelation,locked-by"` - Variables []*Variable `jsonapi:"relation,vars"` - TagBindings []*TagBinding `jsonapi:"relation,tag-bindings"` + AgentPool *AgentPool `jsonapi:"relation,agent-pool"` + CurrentRun *Run `jsonapi:"relation,current-run"` + CurrentStateVersion *StateVersion `jsonapi:"relation,current-state-version"` + Organization *Organization `jsonapi:"relation,organization"` + SSHKey *SSHKey `jsonapi:"relation,ssh-key"` + Outputs []*WorkspaceOutputs `jsonapi:"relation,outputs"` + Project *Project `jsonapi:"relation,project"` + Tags []*Tag `jsonapi:"relation,tags"` + CurrentConfigurationVersion *ConfigurationVersion `jsonapi:"relation,current-configuration-version,omitempty"` + LockedBy *LockedByChoice `jsonapi:"polyrelation,locked-by"` + Variables []*Variable `jsonapi:"relation,vars"` + TagBindings []*TagBinding `jsonapi:"relation,tag-bindings"` + EffectiveTagBindings []*EffectiveTagBinding `jsonapi:"relation,effective-tag-bindings"` // Deprecated: Use DataRetentionPolicyChoice instead. DataRetentionPolicy *DataRetentionPolicy @@ -314,6 +315,7 @@ const ( WSCurrentRunPlan WSIncludeOpt = "current_run.plan" WSCurrentRunConfigVer WSIncludeOpt = "current_run.configuration_version" WSCurrentrunConfigVerIngress WSIncludeOpt = "current_run.configuration_version.ingress_attributes" + WSEffectiveTagBindings WSIncludeOpt = "effective_tag_bindings" WSLockedBy WSIncludeOpt = "locked_by" WSReadme WSIncludeOpt = "readme" WSOutputs WSIncludeOpt = "outputs" diff --git a/workspace_integration_test.go b/workspace_integration_test.go index 04b28c543..0f83067de 100644 --- a/workspace_integration_test.go +++ b/workspace_integration_test.go @@ -299,6 +299,33 @@ func TestWorkspacesList(t *testing.T) { assert.Contains(t, wl3.Items, w2) }) + t.Run("when including effective tag bindings", func(t *testing.T) { + skipUnlessBeta(t) + + orgTest2, orgTest2Cleanup := createOrganization(t, client) + t.Cleanup(orgTest2Cleanup) + + _, wTestCleanup1 := createWorkspaceWithOptions(t, client, orgTest2, WorkspaceCreateOptions{ + Name: String(randomString(t)), + TagBindings: []*TagBinding{ + {Key: "key1", Value: "value1"}, + {Key: "key2", Value: "value2a"}, + }, + }) + t.Cleanup(wTestCleanup1) + + wl, err := client.Workspaces.List(ctx, orgTest2.Name, &WorkspaceListOptions{ + Include: []WSIncludeOpt{WSEffectiveTagBindings}, + }) + require.NoError(t, err) + require.Len(t, wl.Items, 1) + require.Len(t, wl.Items[0].EffectiveTagBindings, 2) + assert.NotEmpty(t, wl.Items[0].EffectiveTagBindings[0].Key) + assert.NotEmpty(t, wl.Items[0].EffectiveTagBindings[0].Value) + assert.NotEmpty(t, wl.Items[0].EffectiveTagBindings[1].Key) + assert.NotEmpty(t, wl.Items[0].EffectiveTagBindings[1].Value) + }) + t.Run("when using project id filter and project contains workspaces", func(t *testing.T) { // create a project in the orgTest p, pTestCleanup := createProject(t, client, orgTest) From 71902986d655ecebe7f4163d620298f0c59d5a8f Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Thu, 23 Jan 2025 16:17:31 -0500 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39b7b80c6..3792754bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +## Enhancements + +* Adds `EffectiveTagBindings` relation to projects and workspaces, allowing the relation to be included when listing projects or workspaces by @sebasslash [#1043](https://github.com/hashicorp/go-tfe/pull/1043) + # v1.74.1 ## Enhancements