diff --git a/README.md b/README.md index cd3bc2f8..67ecabdc 100644 --- a/README.md +++ b/README.md @@ -293,4 +293,7 @@ On MacOS or Windows systems, we recommend either using a VM or the provided `.de | `SSL_CERT_BASE64` | | The content of an SSL cert file. This is useful for self-signed certificates. | | `EXPORT_ENV_FILE` | | Optional file path to a .env file where envbuilder will dump environment variables from devcontainer.json and the built container image. | | `POST_START_SCRIPT_PATH` | | The path to a script that will be created by envbuilder based on the postStartCommand in devcontainer.json, if any is specified (otherwise the script is not created). If this is set, the specified InitCommand should check for the presence of this script and execute it after successful startup. | +| `CODER_AGENT_URL` | | URL of the Coder deployment. If CODER_AGENT_TOKEN is also set, logs from envbuilder will be forwarded here and will be visible in the workspace build logs. | +| `CODER_AGENT_TOKEN` | | Authentication token for a Coder agent. If this is set, then CODER_AGENT_URL must also be set. | +| `CODER_AGENT_SUBSYSTEM` | | Coder agent subsystems to report when forwarding logs. The envbuilder subsystem is always included. | diff --git a/cmd/envbuilder/main.go b/cmd/envbuilder/main.go index 1f6741c8..59323ae1 100644 --- a/cmd/envbuilder/main.go +++ b/cmd/envbuilder/main.go @@ -6,8 +6,9 @@ import ( "errors" "fmt" "net/http" - "net/url" "os" + "slices" + "strings" "time" "cdr.dev/slog" @@ -29,18 +30,12 @@ func main() { Options: options.CLI(), Handler: func(inv *serpent.Invocation) error { var sendLogs func(ctx context.Context, log ...agentsdk.Log) error - agentURL := os.Getenv("CODER_AGENT_URL") - agentToken := os.Getenv("CODER_AGENT_TOKEN") - if agentToken != "" { - if agentURL == "" { + if options.CoderAgentToken != "" { + if options.CoderAgentURL == nil { return errors.New("CODER_AGENT_URL must be set if CODER_AGENT_TOKEN is set") } - parsed, err := url.Parse(agentURL) - if err != nil { - return err - } - client := agentsdk.New(parsed) - client.SetSessionToken(agentToken) + client := agentsdk.New(options.CoderAgentURL) + client.SetSessionToken(options.CoderAgentToken) client.SDK.HTTPClient = &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ @@ -56,12 +51,10 @@ func main() { // If telemetry is enabled in a Coder deployment, // this will be reported and help us understand // envbuilder usage. - subsystems := os.Getenv("CODER_AGENT_SUBSYSTEM") - if subsystems != "" { - subsystems += "," + if !slices.Contains(options.CoderAgentSubsystem, string(codersdk.AgentSubsystemEnvbuilder)) { + options.CoderAgentSubsystem = append(options.CoderAgentSubsystem, string(codersdk.AgentSubsystemEnvbuilder)) + os.Setenv("CODER_AGENT_SUBSYSTEM", strings.Join(options.CoderAgentSubsystem, ",")) } - subsystems += string(codersdk.AgentSubsystemEnvbuilder) - os.Setenv("CODER_AGENT_SUBSYSTEM", subsystems) } options.Logger = func(level codersdk.LogLevel, format string, args ...interface{}) { diff --git a/options.go b/options.go index 134fdca5..3a101913 100644 --- a/options.go +++ b/options.go @@ -1,6 +1,8 @@ package envbuilder import ( + "net/url" + "github.com/coder/coder/v2/codersdk" "github.com/coder/serpent" "github.com/go-git/go-billy/v5" @@ -44,6 +46,11 @@ type Options struct { // Filesystem is the filesystem to use for all operations. // Defaults to the host filesystem. Filesystem billy.Filesystem + // These options are specifically used when envbuilder + // is invoked as part of a Coder workspace. + CoderAgentURL *url.URL + CoderAgentToken string + CoderAgentSubsystem []string } // Generate CLI options for the envbuilder command. @@ -272,6 +279,28 @@ func (o *Options) CLI() serpent.OptionSet { "is set, the specified InitCommand should check for the presence of " + "this script and execute it after successful startup.", }, + { + Flag: "coder-agent-url", + Env: "CODER_AGENT_URL", + Value: serpent.URLOf(o.CoderAgentURL), + Description: "URL of the Coder deployment. If CODER_AGENT_TOKEN is also " + + "set, logs from envbuilder will be forwarded here and will be " + + "visible in the workspace build logs.", + }, + { + Flag: "coder-agent-token", + Env: "CODER_AGENT_TOKEN", + Value: serpent.StringOf(&o.CoderAgentToken), + Description: "Authentication token for a Coder agent. If this is set, " + + "then CODER_AGENT_URL must also be set.", + }, + { + Flag: "coder-agent-subsystem", + Env: "CODER_AGENT_SUBSYSTEM", + Value: serpent.StringArrayOf(&o.CoderAgentSubsystem), + Description: "Coder agent subsystems to report when forwarding logs. " + + "The envbuilder subsystem is always included.", + }, } } diff --git a/testdata/options.golden b/testdata/options.golden index 5f561eba..ac814cf0 100644 --- a/testdata/options.golden +++ b/testdata/options.golden @@ -20,6 +20,19 @@ OPTIONS: The number of days to use cached layers before expiring them. Defaults to 7 days. + --coder-agent-subsystem string-array, $CODER_AGENT_SUBSYSTEM + Coder agent subsystems to report when forwarding logs. The envbuilder + subsystem is always included. + + --coder-agent-token string, $CODER_AGENT_TOKEN + Authentication token for a Coder agent. If this is set, then + CODER_AGENT_URL must also be set. + + --coder-agent-url url, $CODER_AGENT_URL + URL of the Coder deployment. If CODER_AGENT_TOKEN is also set, logs + from envbuilder will be forwarded here and will be visible in the + workspace build logs. + --devcontainer-dir string, $DEVCONTAINER_DIR The path to the folder containing the devcontainer.json file that will be used to build the workspace and can either be an absolute path or a