From 5426761891856b96f5461fef676c0125631f0f68 Mon Sep 17 00:00:00 2001 From: carole-lavillonniere Date: Fri, 30 Jan 2026 15:03:38 +0100 Subject: [PATCH 1/2] read auth token from env vars --- env.example | 1 + internal/container/start.go | 8 +++++++ internal/runtime/docker.go | 1 + internal/runtime/runtime.go | 1 + test/integration/start_test.go | 39 ++++++++++++++++++++++++++++++++-- 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 env.example diff --git a/env.example b/env.example new file mode 100644 index 0000000..fecb074 --- /dev/null +++ b/env.example @@ -0,0 +1 @@ +export LOCALSTACK_AUTH_TOKEN=ls-... diff --git a/internal/container/start.go b/internal/container/start.go index 41266bd..4bd1254 100644 --- a/internal/container/start.go +++ b/internal/container/start.go @@ -4,12 +4,19 @@ import ( "context" "fmt" "net/http" + "os" "time" "github.com/localstack/lstk/internal/runtime" ) func Start(ctx context.Context, rt runtime.Runtime, onProgress func(string)) error { + token := os.Getenv("LOCALSTACK_AUTH_TOKEN") + if token == "" { + return fmt.Errorf("LOCALSTACK_AUTH_TOKEN is not set") + } + env := []string{"LOCALSTACK_AUTH_TOKEN=" + token} + // TODO: hardcoded for now, later should be configurable containers := []runtime.ContainerConfig{ { @@ -17,6 +24,7 @@ func Start(ctx context.Context, rt runtime.Runtime, onProgress func(string)) err Name: "localstack-aws", Port: "4566", HealthPath: "/_localstack/health", + Env: env, }, } diff --git a/internal/runtime/docker.go b/internal/runtime/docker.go index d2f493a..ca7dab1 100644 --- a/internal/runtime/docker.go +++ b/internal/runtime/docker.go @@ -73,6 +73,7 @@ func (d *DockerRuntime) Start(ctx context.Context, config ContainerConfig) (stri &container.Config{ Image: config.Image, ExposedPorts: exposedPorts, + Env: config.Env, }, &container.HostConfig{ PortBindings: portBindings, diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index 224db62..7a95884 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -7,6 +7,7 @@ type ContainerConfig struct { Name string Port string HealthPath string + Env []string // e.g., ["KEY=value", "FOO=bar"] } type PullProgress struct { diff --git a/test/integration/start_test.go b/test/integration/start_test.go index 55a7208..ab9a96f 100644 --- a/test/integration/start_test.go +++ b/test/integration/start_test.go @@ -2,6 +2,7 @@ package integration_test import ( "context" + "os" "os/exec" "testing" "time" @@ -13,7 +14,40 @@ import ( const containerName = "localstack-aws" -func TestStartCommandFailsWithoutAuth(t *testing.T) { +func TestStartCommandSucceedsWithValidToken(t *testing.T) { + authToken := os.Getenv("LOCALSTACK_AUTH_TOKEN") + require.NotEmpty(t, authToken, "LOCALSTACK_AUTH_TOKEN must be set to run this test") + + cleanup() + t.Cleanup(cleanup) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + + cmd := exec.CommandContext(ctx, "../../bin/lstk", "start") + cmd.Env = append(os.Environ(), "LOCALSTACK_AUTH_TOKEN="+authToken) + output, err := cmd.CombinedOutput() + + require.NoError(t, err, "lstk start failed: %s", output) + + inspect, err := dockerClient.ContainerInspect(ctx, containerName) + require.NoError(t, err, "failed to inspect container") + assert.True(t, inspect.State.Running, "container should be running") +} + +func TestStartCommandFailsWithoutToken(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + + cmd := exec.CommandContext(ctx, "../../bin/lstk", "start") + cmd.Env = []string{} // Clear environment to ensure no token + output, err := cmd.CombinedOutput() + + require.Error(t, err, "expected lstk start to fail without token") + assert.Contains(t, string(output), "LOCALSTACK_AUTH_TOKEN is not set") +} + +func TestStartCommandFailsWithInvalidToken(t *testing.T) { cleanup() t.Cleanup(cleanup) @@ -21,9 +55,10 @@ func TestStartCommandFailsWithoutAuth(t *testing.T) { defer cancel() cmd := exec.CommandContext(ctx, "../../bin/lstk", "start") + cmd.Env = append(os.Environ(), "LOCALSTACK_AUTH_TOKEN=invalid-token") output, err := cmd.CombinedOutput() - require.Error(t, err, "expected lstk start to fail without auth") + require.Error(t, err, "expected lstk start to fail with invalid token") assert.Contains(t, string(output), "License activation failed") } From 0df30e7235a98b52bd0dbf91c74f904a2818bbe9 Mon Sep 17 00:00:00 2001 From: carole-lavillonniere Date: Mon, 2 Feb 2026 14:52:18 +0100 Subject: [PATCH 2/2] move env var check to auth.GetToken() --- internal/auth/auth.go | 16 ++++++++++++++++ internal/container/start.go | 8 ++++---- test/integration/start_test.go | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 internal/auth/auth.go diff --git a/internal/auth/auth.go b/internal/auth/auth.go new file mode 100644 index 0000000..f1cf6f3 --- /dev/null +++ b/internal/auth/auth.go @@ -0,0 +1,16 @@ +package auth + +import ( + "errors" + "os" +) + +// GetToken returns the auth token from keyring or environment variable. +func GetToken() (string, error) { + // TODO: try keyring first + + if token := os.Getenv("LOCALSTACK_AUTH_TOKEN"); token != "" { + return token, nil + } + return "", errors.New("auth token not found, please set LOCALSTACK_AUTH_TOKEN") +} diff --git a/internal/container/start.go b/internal/container/start.go index 4bd1254..dbaf700 100644 --- a/internal/container/start.go +++ b/internal/container/start.go @@ -4,16 +4,16 @@ import ( "context" "fmt" "net/http" - "os" "time" + "github.com/localstack/lstk/internal/auth" "github.com/localstack/lstk/internal/runtime" ) func Start(ctx context.Context, rt runtime.Runtime, onProgress func(string)) error { - token := os.Getenv("LOCALSTACK_AUTH_TOKEN") - if token == "" { - return fmt.Errorf("LOCALSTACK_AUTH_TOKEN is not set") + token, err := auth.GetToken() + if err != nil { + return err } env := []string{"LOCALSTACK_AUTH_TOKEN=" + token} diff --git a/test/integration/start_test.go b/test/integration/start_test.go index ab9a96f..c5e805f 100644 --- a/test/integration/start_test.go +++ b/test/integration/start_test.go @@ -44,7 +44,7 @@ func TestStartCommandFailsWithoutToken(t *testing.T) { output, err := cmd.CombinedOutput() require.Error(t, err, "expected lstk start to fail without token") - assert.Contains(t, string(output), "LOCALSTACK_AUTH_TOKEN is not set") + assert.Contains(t, string(output), "auth token not found") } func TestStartCommandFailsWithInvalidToken(t *testing.T) {