Skip to content

Commit 0a50b31

Browse files
committed
feat: reuse agent tokens when a prebuilt agent reinitializes
1 parent c8c5101 commit 0a50b31

File tree

1 file changed

+53
-2
lines changed

1 file changed

+53
-2
lines changed

provider/agent.go

+53-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ package provider
33
import (
44
"context"
55
"fmt"
6+
"os"
67
"path/filepath"
78
"reflect"
89
"strings"
910

11+
"github.com/hashicorp/terraform-plugin-log/tflog"
12+
1013
"github.com/google/uuid"
1114
"github.com/hashicorp/go-cty/cty"
1215
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -22,10 +25,54 @@ func agentResource() *schema.Resource {
2225
SchemaVersion: 1,
2326

2427
Description: "Use this resource to associate an agent.",
25-
CreateContext: func(_ context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
28+
CreateContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
2629
// This should be a real authentication token!
2730
resourceData.SetId(uuid.NewString())
28-
err := resourceData.Set("token", uuid.NewString())
31+
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
42+
43+
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
60+
}
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+
}
69+
} else {
70+
if !isPrebuild {
71+
tflog.Info(ctx, "IS USING EXISTING AGENT TOKEN", allEnv)
72+
}
73+
}
74+
75+
err := resourceData.Set("token", token)
2976
if err != nil {
3077
return diag.FromErr(err)
3178
}
@@ -469,3 +516,7 @@ func updateInitScript(resourceData *schema.ResourceData, i interface{}) diag.Dia
469516
}
470517
return nil
471518
}
519+
520+
func RunningAgentTokenEnvironmentVariable() string {
521+
return "CODER_RUNNING_WORKSPACE_AGENT_TOKEN"
522+
}

0 commit comments

Comments
 (0)