Skip to content

Commit

Permalink
Update Org and Run Tasks for Private Run Tasks
Browse files Browse the repository at this point in the history
This commit updates the Org. entitlements for the new Private Run Tasks feature.
This commit also updates the Run Task options struct for CRUD operations to
pass through the agent pool relationship
  • Loading branch information
glennsarti committed Aug 1, 2024
1 parent de2e5b8 commit 7bc320e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# UNRELEASED

## Enhancements

* Adds `AllowMemberTokenManagement` permission to `Team` by @juliannatetreault [#922](https://github.com/hashicorp/go-tfe/pull/922)
* Adds `PrivateRunTasks` field to Entitlements by @glennsarti [#944](https://github.com/hashicorp/go-tfe/pull/944)
* Adds `AgentPool` relationship to options when creating and updating Run Tasks by @glennsarti [#944](https://github.com/hashicorp/go-tfe/pull/944)

# v1.61.0

Expand Down
1 change: 1 addition & 0 deletions organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ type Entitlements struct {
GlobalRunTasks bool `jsonapi:"attr,global-run-tasks"`
Operations bool `jsonapi:"attr,operations"`
PrivateModuleRegistry bool `jsonapi:"attr,private-module-registry"`
PrivateRunTasks bool `jsonapi:"attr,private-run-tasks"`
RunTasks bool `jsonapi:"attr,run-tasks"`
SSO bool `jsonapi:"attr,sso"`
Sentinel bool `jsonapi:"attr,sentinel"`
Expand Down
9 changes: 9 additions & 0 deletions run_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type RunTask struct {
Enabled bool `jsonapi:"attr,enabled"`
Global *GlobalRunTask `jsonapi:"attr,global-configuration,omitempty"`

AgentPool *AgentPool `jsonapi:"relation,agent-pool"`
Organization *Organization `jsonapi:"relation,organization"`
WorkspaceRunTasks []*WorkspaceRunTask `jsonapi:"relation,workspace-tasks"`
}
Expand Down Expand Up @@ -130,6 +131,10 @@ type RunTaskCreateOptions struct {

// Optional: Whether the task contains global configuration
Global *GlobalRunTaskOptions `jsonapi:"attr,global-configuration,omitempty"`

// Optional: Whether the task will be executed using an Agent Pool
// Requires the PrivateRunTasks entitlement
AgentPool *AgentPool `jsonapi:"relation,agent-pool,omitempty"`
}

// RunTaskUpdateOptions represents the set of options for updating an organization's run task
Expand Down Expand Up @@ -160,6 +165,10 @@ type RunTaskUpdateOptions struct {

// Optional: Whether the task contains global configuration
Global *GlobalRunTaskOptions `jsonapi:"attr,global-configuration,omitempty"`

// Optional: Whether the task will be executed using an Agent Pool
// Requires the PrivateRunTasks entitlement
AgentPool *AgentPool `jsonapi:"relation,agent-pool,omitempty"`
}

// Create is used to create a new run task for an organization
Expand Down
79 changes: 73 additions & 6 deletions run_task_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,32 @@ import (
"github.com/stretchr/testify/require"
)

func hasGlobalRunTasks(client *Client, organizationName string) (bool, error) {
func getOrgEntitlements(client *Client, organizationName string) (*Entitlements, error) {
ctx := context.Background()
if orgEntitlements, err := client.Organizations.ReadEntitlements(ctx, organizationName); err != nil {
orgEntitlements, err := client.Organizations.ReadEntitlements(ctx, organizationName)
if err != nil {
return nil, err
}
if orgEntitlements == nil {
return nil, errors.New("The organization entitlements are empty.")
}
return orgEntitlements, nil
}

func hasGlobalRunTasks(client *Client, organizationName string) (bool, error) {
oe, err := getOrgEntitlements(client, organizationName)
if err != nil {
return false, err
} else if orgEntitlements == nil {
return false, errors.New("The organization entitlements are empty.")
} else {
return orgEntitlements.GlobalRunTasks, nil
}
return oe.GlobalRunTasks, nil
}

func hasPrivateRunTasks(client *Client, organizationName string) (bool, error) {
oe, err := getOrgEntitlements(client, organizationName)
if err != nil {
return false, err
}
return oe.PrivateRunTasks, nil
}

func TestRunTasksCreate(t *testing.T) {
Expand Down Expand Up @@ -54,6 +71,33 @@ func TestRunTasksCreate(t *testing.T) {
}
globalEnforce := Mandatory

t.Run("with an agent pool", func(t *testing.T) {
// We can only test if the org, supports private run tasks. For now this isn't
// a fatal error and we just skip the test.
if v, err := hasPrivateRunTasks(client, orgTest.Name); err != nil {
t.Fatalf("Could not retrieve the entitlements for the test organization.: %s", err)
} else if !v {
t.Skip("The test organization requires the private-run-tasks entitlement but is not entitled.")
return
}

// Unfortunately when we create a Run Task it automatically verifies that the URL by sending a test payload. But
// this means with an agent pool, we need an agent pool to exist, and an agent created with request forwarding enabled.
// This is too much to create for this one test suite. So instead, we really only need to assert that; when the options include an
// agent pool, then we expect HCP Terraform to process the agent pool. So, if we send it a nonsense agent pool ID, then we
// expect an error to be returned saying that the ID was nonsense.
_, err := client.RunTasks.Create(ctx, orgTest.Name, RunTaskCreateOptions{
Name: runTaskName,
URL: runTaskServerURL,
Description: &runTaskDescription,
Category: "task",
AgentPool: &AgentPool{
ID: "apool-this-pool-id-will-never-exist-so-we-expect-http-error-response",
},
})
require.ErrorContains(t, err, "The provided agent pool does not exist")
})

t.Run("add run task to organization", func(t *testing.T) {
r, err := client.RunTasks.Create(ctx, orgTest.Name, RunTaskCreateOptions{
Name: runTaskName,
Expand Down Expand Up @@ -262,6 +306,29 @@ func TestRunTasksUpdate(t *testing.T) {

assert.Equal(t, newDescription, r.Description)
})

t.Run("with an agent pool", func(t *testing.T) {
// We can only test if the org, supports private run tasks. For now this isn't
// a fatal error and we just skip the test.
if v, err := hasPrivateRunTasks(client, orgTest.Name); err != nil {
t.Fatalf("Could not retrieve the entitlements for the test organization.: %s", err)
} else if !v {
t.Skip("The test organization requires the private-run-tasks entitlement but is not entitled.")
return
}

// Unfortunately when we update a Run Task it automatically verifies that the URL by sending a test payload. But
// this means with an agent pool, we need an agent pool to exist, and an agent created with request forwarding enabled.
// This is too much to create for this one test suite. So instead, we really only need to assert that; when the options include an
// agent pool, then we expect HCP Terraform to process the agent pool. So, if we send it a nonsense agent pool ID, then we
// expect an error to be returned saying that the ID was nonsense.
_, err := client.RunTasks.Update(ctx, runTaskTest.ID, RunTaskUpdateOptions{
AgentPool: &AgentPool{
ID: "apool-this-pool-id-will-never-exist-so-we-expect-http-error-response",
},
})
require.ErrorContains(t, err, "The provided agent pool does not exist")
})
}

func TestRunTasksDelete(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions task_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type TaskResult struct {
TaskURL string `jsonapi:"attr,task-url"`
WorkspaceTaskID string `jsonapi:"attr,workspace-task-id"`
WorkspaceTaskEnforcementLevel TaskEnforcementLevel `jsonapi:"attr,workspace-task-enforcement-level"`
AgentPoolID *string `jsonapi:"attr,agent-pool-id,omitempty"`

// The task stage this result belongs to
TaskStage *TaskStage `jsonapi:"relation,task_stage"`
Expand Down

0 comments on commit 7bc320e

Please sign in to comment.