Skip to content

Commit 0f5842a

Browse files
committed
fix: ensure the agent token is reused for prebuilds
1 parent e46f69a commit 0f5842a

File tree

2 files changed

+46
-40
lines changed

2 files changed

+46
-40
lines changed

provider/agent.go

+36-34
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,7 @@ func agentResource() *schema.Resource {
2929
agentID := uuid.NewString()
3030
resourceData.SetId(agentID)
3131

32-
// Most of the time, we will generate a new token for the agent.
33-
// In the case of a prebuilt workspace being claimed, we will override with
34-
// an existing token provided below.
35-
token := uuid.NewString()
36-
37-
// If isPrebuild is true, then this workspace was built by the prebuilds system.
38-
// This does not determine whether the workspace has been claimed by a user.
39-
// At this point, it may or may not have been claimed.
40-
isPrebuild := helpers.OptionalEnv(IsPrebuildEnvironmentVariable()) == "true"
41-
// existingToken should only have been set if isPrebuild is true, because we only
42-
// reuse the token when a prebuilt workspace is being claimed.
43-
existingToken := helpers.OptionalEnv(RunningAgentTokenEnvironmentVariable(agentID))
44-
logFields := map[string]interface{}{
45-
"agent_id": agentID,
46-
"is_prebuild": isPrebuild,
47-
"token_provided": existingToken != "",
48-
}
49-
if isPrebuild && existingToken != "" {
50-
// check if a token was already generated for this agent.
51-
// If so, this workspace is in the process of being claimed
52-
// and we should reuse the token. If not, we use a new token as usual.
53-
tflog.Info(ctx, "using provided agent token for prebuild", logFields)
54-
token = existingToken
55-
} else {
56-
tflog.Info(ctx, "using a new agent token", logFields)
57-
}
58-
32+
token := agentAuthToken(ctx, "")
5933
err := resourceData.Set("token", token)
6034
if err != nil {
6135
return diag.FromErr(err)
@@ -79,10 +53,12 @@ func agentResource() *schema.Resource {
7953
return updateInitScript(resourceData, i)
8054
},
8155
ReadWithoutTimeout: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
82-
err := resourceData.Set("token", uuid.NewString())
56+
token := agentAuthToken(ctx, "")
57+
err := resourceData.Set("token", token)
8358
if err != nil {
8459
return diag.FromErr(err)
8560
}
61+
8662
if _, ok := resourceData.GetOk("display_apps"); !ok {
8763
err = resourceData.Set("display_apps", []interface{}{
8864
map[string]bool{
@@ -501,15 +477,41 @@ func updateInitScript(resourceData *schema.ResourceData, i interface{}) diag.Dia
501477
return nil
502478
}
503479

504-
// RunningAgentTokenEnvironmentVariable returns the name of the environment variable
505-
// that contains the token for the running agent. This is used for prebuilds, where
506-
// we want to reuse the same token for the next iteration of a workspace agent before
507-
// and after the workspace was claimed by a user.
480+
func agentAuthToken(ctx context.Context, agentID string) string {
481+
// Most of the time, we will generate a new token for the agent.
482+
// In the case of a prebuilt workspace being claimed, we will override with
483+
// an existing token provided below.
484+
token := uuid.NewString()
485+
486+
existingToken := helpers.OptionalEnv(RunningAgentTokenEnvironmentVariable(agentID))
487+
logFields := map[string]interface{}{
488+
"agent_id": agentID,
489+
"token_provided": existingToken != "",
490+
}
491+
if existingToken != "" {
492+
// An existing token was provided for this agent. That means that this
493+
// is a prebuilt workspace in the process of being claimed.
494+
// We should reuse the token.
495+
tflog.Info(ctx, "using provided agent token for prebuild", logFields)
496+
token = existingToken
497+
} else {
498+
tflog.Info(ctx, "using a new agent token", logFields)
499+
}
500+
501+
return token
502+
}
503+
504+
// RunningAgentTokenEnvironmentVariable returns the name of an environment variable
505+
// that contains the token to use for the running agent. This is used for prebuilds,
506+
// where we want to reuse the same token for the next iteration of a workspace agent
507+
// before and after the workspace was claimed by a user.
508+
//
509+
// By reusing an existing token, we can avoid the need to change a value that may have been
510+
// used immutably. Thus, allowing us to avoid reprovisioning resources that may take a long time
511+
// to replace.
508512
//
509513
// agentID is unused for now, but will be used as soon as we support multiple agents.
510514
func RunningAgentTokenEnvironmentVariable(agentID string) string {
511-
agentID = "" // remove this once we need to support multiple agents per prebuilt workspace.
512-
513515
sum := sha256.Sum256([]byte(agentID))
514516
return "CODER_RUNNING_WORKSPACE_AGENT_TOKEN_" + hex.EncodeToString(sum[:])
515517
}

provider/workspace.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ func workspaceDataSource() *schema.Resource {
2727
}
2828
_ = rd.Set("start_count", count)
2929

30-
prebuild := helpers.OptionalEnv(IsPrebuildEnvironmentVariable())
30+
isPrebuild := isPrebuiltWorkspace(c)
3131
prebuildCount := 0
32-
if prebuild == "true" {
32+
if isPrebuild {
3333
prebuildCount = 1
3434
_ = rd.Set("is_prebuild", true)
3535
}
@@ -140,12 +140,16 @@ func workspaceDataSource() *schema.Resource {
140140
}
141141
}
142142

143+
func isPrebuiltWorkspace(ctx context.Context) bool {
144+
return helpers.OptionalEnv(IsPrebuildEnvironmentVariable()) == "true"
145+
}
146+
143147
// IsPrebuildEnvironmentVariable returns the name of the environment
144-
// variable that indicates whether the workspace was prebuilt. The value of
145-
// this environment variable should be set to "true" if the workspace is prebuilt.
148+
// variable that indicates whether the workspace is an unclaimed prebuilt workspace.
149+
// The value of this environment variable should be set to "true" if the workspace
150+
// is prebuilt and it has not yet been claimed by a user.
146151
// Any other values, including "false" and "" will be interpreted to mean that the
147-
// workspace is not prebuilt. If the workspace is prebuilt, it may or may not yet
148-
// have been claimed by a user.
152+
// workspace is not prebuilt, or was prebuilt but has since been claimed by a user.
149153
func IsPrebuildEnvironmentVariable() string {
150154
return "CODER_WORKSPACE_IS_PREBUILD"
151155
}

0 commit comments

Comments
 (0)