Skip to content

Commit e46f69a

Browse files
committed
WIP: get agent.go ready to be merged with support for prebuilds
1 parent 50bda99 commit e46f69a

File tree

2 files changed

+43
-44
lines changed

2 files changed

+43
-44
lines changed

provider/agent.go

+37-44
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ package provider
22

33
import (
44
"context"
5+
"crypto/sha256"
6+
"encoding/hex"
57
"fmt"
6-
"os"
78
"path/filepath"
89
"reflect"
910
"strings"
1011

11-
"github.com/hashicorp/terraform-plugin-log/tflog"
12-
1312
"github.com/google/uuid"
1413
"github.com/hashicorp/go-cty/cty"
14+
"github.com/hashicorp/terraform-plugin-log/tflog"
1515
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1616
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1717
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
@@ -26,50 +26,34 @@ func agentResource() *schema.Resource {
2626

2727
Description: "Use this resource to associate an agent.",
2828
CreateContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
29-
// This should be a real authentication token!
30-
resourceData.SetId(uuid.NewString())
29+
agentID := uuid.NewString()
30+
resourceData.SetId(agentID)
3131

32-
// CODER_RUNNING_WORKSPACE_AGENT_TOKEN is *only* used for prebuilds. We pass it down when we want to rebuild a prebuilt workspace
33-
// but not generate a new agent token. The provisionerdserver will retrieve this token and push it down to
34-
// here where it will be reused.
35-
// Context: the agent token is often used in immutable attributes of workspace resource (e.g. VM/container)
36-
// to initialize the agent, so if that value changes it will necessitate a replacement of that resource, thus
37-
// obviating the whole point of the prebuild.
38-
//
39-
// The default path is for a new token to be generated on each new resource creation.
40-
// TODO: add logging when the running token is actually used.
41-
var token string
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()
4236

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.
4340
isPrebuild := helpers.OptionalEnv(IsPrebuildEnvironmentVariable()) == "true"
44-
if !isPrebuild {
45-
token = os.Getenv(RunningAgentTokenEnvironmentVariable())
46-
}
47-
48-
allEnv := make(map[string]interface{})
49-
for _, v := range os.Environ() {
50-
split := strings.Split(v, "=")
51-
var key, val string
52-
if len(split) > 0 {
53-
key = split[0]
54-
}
55-
if len(split) > 1 {
56-
val = split[1]
57-
}
58-
59-
allEnv[key] = val
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 != "",
6048
}
61-
62-
allEnv["is_prebuild"] = fmt.Sprintf("%v", isPrebuild)
63-
64-
if token == "" {
65-
token = uuid.NewString()
66-
if !isPrebuild {
67-
tflog.Warn(ctx, "NOT USING EXISTING AGENT TOKEN", allEnv)
68-
}
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
6955
} else {
70-
if !isPrebuild {
71-
tflog.Info(ctx, "IS USING EXISTING AGENT TOKEN", allEnv)
72-
}
56+
tflog.Info(ctx, "using a new agent token", logFields)
7357
}
7458

7559
err := resourceData.Set("token", token)
@@ -517,6 +501,15 @@ func updateInitScript(resourceData *schema.ResourceData, i interface{}) diag.Dia
517501
return nil
518502
}
519503

520-
func RunningAgentTokenEnvironmentVariable() string {
521-
return "CODER_RUNNING_WORKSPACE_AGENT_TOKEN"
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.
508+
//
509+
// agentID is unused for now, but will be used as soon as we support multiple agents.
510+
func RunningAgentTokenEnvironmentVariable(agentID string) string {
511+
agentID = "" // remove this once we need to support multiple agents per prebuilt workspace.
512+
513+
sum := sha256.Sum256([]byte(agentID))
514+
return "CODER_RUNNING_WORKSPACE_AGENT_TOKEN_" + hex.EncodeToString(sum[:])
522515
}

provider/workspace.go

+6
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ func workspaceDataSource() *schema.Resource {
140140
}
141141
}
142142

143+
// 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.
146+
// 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.
143149
func IsPrebuildEnvironmentVariable() string {
144150
return "CODER_WORKSPACE_IS_PREBUILD"
145151
}

0 commit comments

Comments
 (0)