-
Notifications
You must be signed in to change notification settings - Fork 22
feat: reuse agent tokens when a prebuilt agent reinitializes #374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5418ed7
af25037
56d1ab7
c8c5101
0a50b31
50bda99
e46f69a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,13 +2,16 @@ package provider | |||||||||
|
||||||||||
import ( | ||||||||||
"context" | ||||||||||
"crypto/sha256" | ||||||||||
"encoding/hex" | ||||||||||
"fmt" | ||||||||||
"path/filepath" | ||||||||||
"reflect" | ||||||||||
"strings" | ||||||||||
|
||||||||||
"github.com/google/uuid" | ||||||||||
"github.com/hashicorp/go-cty/cty" | ||||||||||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||||||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||||||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||||||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||||||||||
|
@@ -22,10 +25,38 @@ func agentResource() *schema.Resource { | |||||||||
SchemaVersion: 1, | ||||||||||
|
||||||||||
Description: "Use this resource to associate an agent.", | ||||||||||
CreateContext: func(_ context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { | ||||||||||
// This should be a real authentication token! | ||||||||||
resourceData.SetId(uuid.NewString()) | ||||||||||
err := resourceData.Set("token", uuid.NewString()) | ||||||||||
CreateContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { | ||||||||||
agentID := uuid.NewString() | ||||||||||
resourceData.SetId(agentID) | ||||||||||
|
||||||||||
// Most of the time, we will generate a new token for the agent. | ||||||||||
// In the case of a prebuilt workspace being claimed, we will override with | ||||||||||
// an existing token provided below. | ||||||||||
token := uuid.NewString() | ||||||||||
|
||||||||||
// If isPrebuild is true, then this workspace was built by the prebuilds system. | ||||||||||
// This does not determine whether the workspace has been claimed by a user. | ||||||||||
// At this point, it may or may not have been claimed. | ||||||||||
isPrebuild := helpers.OptionalEnv(IsPrebuildEnvironmentVariable()) == "true" | ||||||||||
// existingToken should only have been set if isPrebuild is true, because we only | ||||||||||
// reuse the token when a prebuilt workspace is being claimed. | ||||||||||
existingToken := helpers.OptionalEnv(RunningAgentTokenEnvironmentVariable(agentID)) | ||||||||||
logFields := map[string]interface{}{ | ||||||||||
"agent_id": agentID, | ||||||||||
"is_prebuild": isPrebuild, | ||||||||||
"token_provided": existingToken != "", | ||||||||||
} | ||||||||||
if isPrebuild && existingToken != "" { | ||||||||||
// check if a token was already generated for this agent. | ||||||||||
// If so, this workspace is in the process of being claimed | ||||||||||
// and we should reuse the token. If not, we use a new token as usual. | ||||||||||
tflog.Info(ctx, "using provided agent token for prebuild", logFields) | ||||||||||
token = existingToken | ||||||||||
} else { | ||||||||||
tflog.Info(ctx, "using a new agent token", logFields) | ||||||||||
} | ||||||||||
Comment on lines
+55
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's necessary to log this case.
Suggested change
|
||||||||||
|
||||||||||
err := resourceData.Set("token", token) | ||||||||||
if err != nil { | ||||||||||
return diag.FromErr(err) | ||||||||||
} | ||||||||||
|
@@ -469,3 +500,16 @@ func updateInitScript(resourceData *schema.ResourceData, i interface{}) diag.Dia | |||||||||
} | ||||||||||
return nil | ||||||||||
} | ||||||||||
|
||||||||||
// RunningAgentTokenEnvironmentVariable returns the name of the environment variable | ||||||||||
// that contains the token for the running agent. This is used for prebuilds, where | ||||||||||
// we want to reuse the same token for the next iteration of a workspace agent before | ||||||||||
// and after the workspace was claimed by a user. | ||||||||||
Comment on lines
+504
to
+507
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment could use some work; I think we should elaborate as to why this is being injected. |
||||||||||
// | ||||||||||
// agentID is unused for now, but will be used as soon as we support multiple agents. | ||||||||||
func RunningAgentTokenEnvironmentVariable(agentID string) string { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How will the ID be injected? How will we maintain a persistent identity across |
||||||||||
agentID = "" // remove this once we need to support multiple agents per prebuilt workspace. | ||||||||||
|
||||||||||
sum := sha256.Sum256([]byte(agentID)) | ||||||||||
return "CODER_RUNNING_WORKSPACE_AGENT_TOKEN_" + hex.EncodeToString(sum[:]) | ||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: consistency.