Skip to content

Commit

Permalink
Merge pull request #870 from hashicorp/hs26gill/TF-3175-add-scoping-a…
Browse files Browse the repository at this point in the history
…gent-pools-to-workspaces

Update Agent Pools scope to Workspaces
  • Loading branch information
Karl Kirch authored Jun 26, 2023
2 parents b2c77a1 + d1ef6a5 commit f757261
Show file tree
Hide file tree
Showing 12 changed files with 620 additions and 48 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
## Unreleased

FEATURES:
* **New Resource**: `r/tfe_agent_pool_allowed_workspaces` restricts the use of an agent pool to particular workspaces, by @hs26gill [870](https://github.com/hashicorp/terraform-provider-tfe/pull/870)

BUG FIXES:
* `r/tfe_workspace_run`: Ensure `wait_for_run` correctly results in a fire-and-forget Run when set to `false` by @lucymhdavies ([#910](https://github.com/hashicorp/terraform-provider-tfe/pull/910))
* `r/tfe_notification_configuration`: Add support for missing "Check failed" Health Event notifications by @lucymhdavies ([#927](https://github.com/hashicorp/terraform-provider-tfe/pull/927))


ENHANCEMENTS:
* `r/tfe_agent_pool`: Add attribute `organization_scoped` to set the scope of an agent pool by @hs26gill [870](https://github.com/hashicorp/terraform-provider-tfe/pull/870)
* `d/tfe_agent_pool`: Add attribute `organization_scoped` and `allowed_workspace_ids` to retrieve agent pool scope and associated allowed workspace ids by @hs26gill [870](https://github.com/hashicorp/terraform-provider-tfe/pull/870)

## v0.45.0 (May 25, 2023)

Expand All @@ -16,7 +21,6 @@ FEATURES:
* `r/tfe_team_token`: Add optional `expired_at` field to team tokens by, @juliannatetreault ([#844](https://github.com/hashicorp/terraform-provider-tfe/pull/844))

ENHANCEMENTS:

* `r/tfe_workspace`: Retry workspace safe delete if resources are still being processed to determine safety. ([#881](https://github.com/hashicorp/terraform-provider-tfe/pull/881))

BUG FIXES:
Expand Down
8 changes: 4 additions & 4 deletions tfe/agent_pool_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
tfe "github.com/hashicorp/go-tfe"
)

func fetchAgentPoolID(orgName string, poolName string, client *tfe.Client) (string, error) {
func fetchAgentPool(orgName string, poolName string, client *tfe.Client) (*tfe.AgentPool, error) {
// to reduce the number of pages returned, search based on the name. TFE instances which
// do not support agent pool search will just ignore the query parameter
options := tfe.AgentPoolListOptions{
Expand All @@ -19,12 +19,12 @@ func fetchAgentPoolID(orgName string, poolName string, client *tfe.Client) (stri
for {
l, err := client.AgentPools.List(ctx, orgName, &options)
if err != nil {
return "", fmt.Errorf("Error retrieving agent pools: %w", err)
return nil, fmt.Errorf("Error retrieving agent pools: %w", err)
}

for _, k := range l.Items {
if k.Name == poolName {
return k.ID, nil
return k, nil
}
}

Expand All @@ -37,5 +37,5 @@ func fetchAgentPoolID(orgName string, poolName string, client *tfe.Client) (stri
options.PageNumber = l.NextPage
}

return "", tfe.ErrResourceNotFound
return nil, tfe.ErrResourceNotFound
}
24 changes: 22 additions & 2 deletions tfe/data_source_agent_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ func dataSourceTFEAgentPool() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},

"organization_scoped": {
Type: schema.TypeBool,
Computed: true,
},

"allowed_workspace_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}
Expand All @@ -35,10 +46,19 @@ func dataSourceTFEAgentPoolRead(d *schema.ResourceData, meta interface{}) error
return err
}

id, err := fetchAgentPoolID(organization, name, config.Client)
pool, err := fetchAgentPool(organization, name, config.Client)
if err != nil {
return err
}
d.SetId(id)

d.SetId(pool.ID)
d.Set("organization_scoped", pool.OrganizationScoped)

var allowedWorkspaceIDs []string
for _, allowedWorkspaceID := range pool.AllowedWorkspaces {
allowedWorkspaceIDs = append(allowedWorkspaceIDs, allowedWorkspaceID.ID)
}
d.Set("allowed_workspace_ids", allowedWorkspaceIDs)

return nil
}
65 changes: 65 additions & 0 deletions tfe/data_source_agent_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"testing"
"time"

"github.com/hashicorp/go-tfe"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

Expand Down Expand Up @@ -37,6 +39,50 @@ func TestAccTFEAgentPoolDataSource_basic(t *testing.T) {
"data.tfe_agent_pool.foobar", "name", fmt.Sprintf("agent-pool-test-%d", rInt)),
resource.TestCheckResourceAttr(
"data.tfe_agent_pool.foobar", "organization", org.Name),
resource.TestCheckResourceAttr(
"data.tfe_agent_pool.foobar", "organization_scoped", "true"),
),
},
},
})
}

func TestAccTFEAgentPoolDataSource_allowed_workspaces(t *testing.T) {
skipIfEnterprise(t)

tfeClient, err := getClientUsingEnv()
if err != nil {
t.Fatal(err)
}

org, orgCleanup := createBusinessOrganization(t, tfeClient)
t.Cleanup(orgCleanup)

rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()

ws, err := tfeClient.Workspaces.Create(ctx, org.Name, tfe.WorkspaceCreateOptions{
Name: tfe.String(fmt.Sprintf("tst-workspace-test-%d", rInt)),
})
if err != nil {
t.Fatal(err)
}

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccTFEAgentPoolDataSourceAllowedWorkspacesConfig(org.Name, rInt, ws.ID),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.tfe_agent_pool.foobar", "id"),
resource.TestCheckResourceAttr(
"data.tfe_agent_pool.foobar", "name", fmt.Sprintf("agent-pool-test-%d", rInt)),
resource.TestCheckResourceAttr(
"data.tfe_agent_pool.foobar", "organization", org.Name),
resource.TestCheckResourceAttr(
"data.tfe_agent_pool.foobar", "organization_scoped", "false"),
resource.TestCheckResourceAttr(
"data.tfe_agent_pool.foobar", "allowed_workspace_ids.0", ws.ID),
),
},
},
Expand All @@ -55,3 +101,22 @@ data "tfe_agent_pool" "foobar" {
organization = "%s"
}`, rInt, organization, organization)
}

func testAccTFEAgentPoolDataSourceAllowedWorkspacesConfig(organization string, rInt int, workspaceID string) string {
return fmt.Sprintf(`
resource "tfe_agent_pool" "foobar" {
name = "agent-pool-test-%d"
organization = "%s"
organization_scoped = false
}
resource "tfe_agent_pool_allowed_workspaces" "foobar" {
agent_pool_id = tfe_agent_pool.foobar.id
allowed_workspace_ids = ["%s"]
}
data "tfe_agent_pool" "foobar" {
name = tfe_agent_pool.foobar.name
organization = "%s"
}`, rInt, organization, workspaceID, organization)
}
71 changes: 36 additions & 35 deletions tfe/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,41 +134,42 @@ func Provider() *schema.Provider {
},

ResourcesMap: map[string]*schema.Resource{
"tfe_admin_organization_settings": resourceTFEAdminOrganizationSettings(),
"tfe_agent_pool": resourceTFEAgentPool(),
"tfe_agent_token": resourceTFEAgentToken(),
"tfe_notification_configuration": resourceTFENotificationConfiguration(),
"tfe_oauth_client": resourceTFEOAuthClient(),
"tfe_organization": resourceTFEOrganization(),
"tfe_organization_membership": resourceTFEOrganizationMembership(),
"tfe_organization_module_sharing": resourceTFEOrganizationModuleSharing(),
"tfe_organization_run_task": resourceTFEOrganizationRunTask(),
"tfe_organization_token": resourceTFEOrganizationToken(),
"tfe_policy": resourceTFEPolicy(),
"tfe_policy_set": resourceTFEPolicySet(),
"tfe_policy_set_parameter": resourceTFEPolicySetParameter(),
"tfe_project": resourceTFEProject(),
"tfe_project_variable_set": resourceTFEProjectVariableSet(),
"tfe_registry_module": resourceTFERegistryModule(),
"tfe_no_code_module": resourceTFENoCodeModule(),
"tfe_run_trigger": resourceTFERunTrigger(),
"tfe_sentinel_policy": resourceTFESentinelPolicy(),
"tfe_ssh_key": resourceTFESSHKey(),
"tfe_team": resourceTFETeam(),
"tfe_team_access": resourceTFETeamAccess(),
"tfe_team_organization_member": resourceTFETeamOrganizationMember(),
"tfe_team_organization_members": resourceTFETeamOrganizationMembers(),
"tfe_team_project_access": resourceTFETeamProjectAccess(),
"tfe_team_member": resourceTFETeamMember(),
"tfe_team_members": resourceTFETeamMembers(),
"tfe_team_token": resourceTFETeamToken(),
"tfe_terraform_version": resourceTFETerraformVersion(),
"tfe_workspace": resourceTFEWorkspace(),
"tfe_workspace_run_task": resourceTFEWorkspaceRunTask(),
"tfe_variable_set": resourceTFEVariableSet(),
"tfe_workspace_variable_set": resourceTFEWorkspaceVariableSet(),
"tfe_workspace_policy_set": resourceTFEWorkspacePolicySet(),
"tfe_workspace_run": resourceTFEWorkspaceRun(),
"tfe_admin_organization_settings": resourceTFEAdminOrganizationSettings(),
"tfe_agent_pool": resourceTFEAgentPool(),
"tfe_agent_pool_allowed_workspaces": resourceTFEAgentPoolAllowedWorkspaces(),
"tfe_agent_token": resourceTFEAgentToken(),
"tfe_notification_configuration": resourceTFENotificationConfiguration(),
"tfe_oauth_client": resourceTFEOAuthClient(),
"tfe_organization": resourceTFEOrganization(),
"tfe_organization_membership": resourceTFEOrganizationMembership(),
"tfe_organization_module_sharing": resourceTFEOrganizationModuleSharing(),
"tfe_organization_run_task": resourceTFEOrganizationRunTask(),
"tfe_organization_token": resourceTFEOrganizationToken(),
"tfe_policy": resourceTFEPolicy(),
"tfe_policy_set": resourceTFEPolicySet(),
"tfe_policy_set_parameter": resourceTFEPolicySetParameter(),
"tfe_project": resourceTFEProject(),
"tfe_project_variable_set": resourceTFEProjectVariableSet(),
"tfe_registry_module": resourceTFERegistryModule(),
"tfe_no_code_module": resourceTFENoCodeModule(),
"tfe_run_trigger": resourceTFERunTrigger(),
"tfe_sentinel_policy": resourceTFESentinelPolicy(),
"tfe_ssh_key": resourceTFESSHKey(),
"tfe_team": resourceTFETeam(),
"tfe_team_access": resourceTFETeamAccess(),
"tfe_team_organization_member": resourceTFETeamOrganizationMember(),
"tfe_team_organization_members": resourceTFETeamOrganizationMembers(),
"tfe_team_project_access": resourceTFETeamProjectAccess(),
"tfe_team_member": resourceTFETeamMember(),
"tfe_team_members": resourceTFETeamMembers(),
"tfe_team_token": resourceTFETeamToken(),
"tfe_terraform_version": resourceTFETerraformVersion(),
"tfe_workspace": resourceTFEWorkspace(),
"tfe_workspace_run_task": resourceTFEWorkspaceRunTask(),
"tfe_variable_set": resourceTFEVariableSet(),
"tfe_workspace_variable_set": resourceTFEWorkspaceVariableSet(),
"tfe_workspace_policy_set": resourceTFEWorkspacePolicySet(),
"tfe_workspace_run": resourceTFEWorkspaceRun(),
},
ConfigureContextFunc: configure(),
}
Expand Down
17 changes: 13 additions & 4 deletions tfe/resource_tfe_agent_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ func resourceTFEAgentPool() *schema.Resource {
Computed: true,
ForceNew: true,
},

"organization_scoped": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
},
}
}
Expand All @@ -51,7 +57,8 @@ func resourceTFEAgentPoolCreate(d *schema.ResourceData, meta interface{}) error

// Create a new options struct.
options := tfe.AgentPoolCreateOptions{
Name: tfe.String(name),
Name: tfe.String(name),
OrganizationScoped: tfe.Bool(d.Get("organization_scoped").(bool)),
}

log.Printf("[DEBUG] Create new agent pool for organization: %s", organization)
Expand Down Expand Up @@ -83,6 +90,7 @@ func resourceTFEAgentPoolRead(d *schema.ResourceData, meta interface{}) error {
// Update the config.
d.Set("name", agentPool.Name)
d.Set("organization", agentPool.Organization.Name)
d.Set("organization_scoped", agentPool.OrganizationScoped)

return nil
}
Expand All @@ -92,7 +100,8 @@ func resourceTFEAgentPoolUpdate(d *schema.ResourceData, meta interface{}) error

// Create a new options struct.
options := tfe.AgentPoolUpdateOptions{
Name: tfe.String(d.Get("name").(string)),
Name: tfe.String(d.Get("name").(string)),
OrganizationScoped: tfe.Bool(d.Get("organization_scoped").(bool)),
}

log.Printf("[DEBUG] Update agent pool: %s", d.Id())
Expand Down Expand Up @@ -131,13 +140,13 @@ func resourceTFEAgentPoolImporter(ctx context.Context, d *schema.ResourceData, m
} else if len(s) == 2 {
org := s[0]
poolName := s[1]
poolID, err := fetchAgentPoolID(org, poolName, config.Client)
pool, err := fetchAgentPool(org, poolName, config.Client)
if err != nil {
return nil, fmt.Errorf(
"error retrieving agent pool with name %s from organization %s %w", poolName, org, err)
}

d.SetId(poolID)
d.SetId(pool.ID)
}

return []*schema.ResourceData{d}, nil
Expand Down
Loading

0 comments on commit f757261

Please sign in to comment.