From 4506c5afd11ab8e2e827679f74520e251d984871 Mon Sep 17 00:00:00 2001 From: Harkanwal Gill Date: Sun, 16 Apr 2023 23:58:17 -0400 Subject: [PATCH] Update for creating and filtering workspace scoped agent pools --- CHANGELOG.md | 10 +++++ agent_pool.go | 9 +++++ agent_pool_integration_test.go | 72 ++++++++++++++++++++++++++++++++++ helper_test.go | 26 ++++++++++++ 4 files changed, 117 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4b96511b..2a9dcecba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# Unreleased + +## Features + +## Enhancements +* Adds `OrganizationScoped` and `AllowedWorkspaces` fields for creating workspace scoped agent pools and adds `AllowedWorkspacesName` for filtering agents pools associated with a given workspace by hs26gill [#682](https://github.com/hashicorp/go-tfe/pull/682/files) + +## Bug Fixes + + # v1.21.0 ## Features diff --git a/agent_pool.go b/agent_pool.go index 425cd9d71..7adb1adec 100644 --- a/agent_pool.go +++ b/agent_pool.go @@ -79,6 +79,9 @@ type AgentPoolListOptions struct { // Optional: A search query string used to filter agent pool. Agent pools are searchable by name Query string `url:"q,omitempty"` + + // Optional: String (workspace name) used to filter the results. + AllowedWorkspacesName string `url:"filter[allowed_workspaces][name],omitempty"` } // AgentPoolCreateOptions represents the options for creating an agent pool. @@ -91,6 +94,12 @@ type AgentPoolCreateOptions struct { // Required: A name to identify the agent pool. Name *string `jsonapi:"attr,name"` + + // True if the agent pool is organization scoped, false otherwise. + OrganizationScoped *bool `jsonapi:"attr,organization-scoped,omitempty"` + + // List of workspaces that are associated with an agent pool. + AllowedWorkspaces []*Workspace `jsonapi:"relation,allowed-workspaces"` } // List all the agent pools of the given organization. diff --git a/agent_pool_integration_test.go b/agent_pool_integration_test.go index 2c2b2f1a3..52b732f9b 100644 --- a/agent_pool_integration_test.go +++ b/agent_pool_integration_test.go @@ -84,6 +84,47 @@ func TestAgentPoolsList(t *testing.T) { require.NoError(t, err) assert.Empty(t, pools.Items) }) + + t.Run("with allowed workspace name filter", func(t *testing.T) { + ws1, ws1TestCleanup := createWorkspace(t, client, orgTest) + defer ws1TestCleanup() + + ws2, ws2TestCleanup := createWorkspace(t, client, orgTest) + defer ws2TestCleanup() + + organizationScoped := false + ap, apCleanup := createAgentPoolWithOptions(t, client, orgTest, AgentPoolCreateOptions{ + Name: String("a-pool"), + OrganizationScoped: &organizationScoped, + AllowedWorkspaces: []*Workspace{ ws1 }, + }) + defer apCleanup() + + ap2, ap2Cleanup := createAgentPoolWithOptions(t, client, orgTest, AgentPoolCreateOptions{ + Name: String("b-pool"), + OrganizationScoped: &organizationScoped, + AllowedWorkspaces: []*Workspace{ ws2 }, + }) + defer ap2Cleanup() + + pools, err := client.AgentPools.List(ctx, orgTest.Name, &AgentPoolListOptions{ + AllowedWorkspacesName: ws1.Name, + }) + require.NoError(t, err) + assert.NotEmpty(t, pools.Items) + assert.Contains(t, pools.Items, ap) + assert.Contains(t, pools.Items, agentPool) + assert.Equal(t, 2, pools.TotalCount) + + pools, err = client.AgentPools.List(ctx, orgTest.Name, &AgentPoolListOptions{ + AllowedWorkspacesName: ws2.Name, + }) + require.NoError(t, err) + assert.NotEmpty(t, pools.Items) + assert.Contains(t, pools.Items, agentPool) + assert.Contains(t, pools.Items, ap2) + assert.Equal(t, 2, pools.TotalCount) + }) } func TestAgentPoolsCreate(t *testing.T) { @@ -128,6 +169,37 @@ func TestAgentPoolsCreate(t *testing.T) { assert.Nil(t, pool) assert.EqualError(t, err, ErrInvalidOrg.Error()) }) + + t.Run("with allowed-workspaces options", func(t *testing.T) { + workspaceTest, workspaceTestCleanup := createWorkspace(t, client, orgTest) + defer workspaceTestCleanup() + + organizationScoped := false + options := AgentPoolCreateOptions{ + Name: String("a-pool"), + OrganizationScoped: &organizationScoped, + AllowedWorkspaces: []*Workspace{ + workspaceTest, + }, + } + + pool, err := client.AgentPools.Create(ctx, orgTest.Name, options) + require.NoError(t, err) + + assert.Equal(t, 1, len(pool.AllowedWorkspaces)) + assert.Equal(t, workspaceTest.ID, pool.AllowedWorkspaces[0].ID) + + // Get a refreshed view from the API. + refreshed, err := client.AgentPools.Read(ctx, pool.ID) + require.NoError(t, err) + + for _, item := range []*AgentPool{ + pool, + refreshed, + } { + assert.NotEmpty(t, item.ID) + } + }) } func TestAgentPoolsRead(t *testing.T) { diff --git a/helper_test.go b/helper_test.go index 2cc3bffa5..0aff03fd8 100644 --- a/helper_test.go +++ b/helper_test.go @@ -339,6 +339,32 @@ func createAgentPool(t *testing.T, client *Client, org *Organization) (*AgentPoo } } +func createAgentPoolWithOptions(t *testing.T, client *Client, org *Organization, opts AgentPoolCreateOptions) (*AgentPool, func()) { + var orgCleanup func() + + if org == nil { + org, orgCleanup = createOrganization(t, client) + } + + ctx := context.Background() + pool, err := client.AgentPools.Create(ctx, org.Name, opts) + if err != nil { + t.Fatal(err) + } + + return pool, func() { + if err := client.AgentPools.Delete(ctx, pool.ID); err != nil { + t.Logf("Error destroying agent pool! WARNING: Dangling resources "+ + "may exist! The full error is shown below.\n\n"+ + "Agent pool ID: %s\nError: %s", pool.ID, err) + } + + if orgCleanup != nil { + orgCleanup() + } + } +} + func createAgentToken(t *testing.T, client *Client, ap *AgentPool) (*AgentToken, func()) { var apCleanup func()