Skip to content

Commit 22862e9

Browse files
committed
Forward host environment variables to the emulator container
1 parent 5dcb7b3 commit 22862e9

3 files changed

Lines changed: 71 additions & 8 deletions

File tree

internal/container/start.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ func Start(ctx context.Context, rt runtime.Runtime, sink output.Sink, opts Start
9696

9797
tel := opts.Telemetry
9898

99+
var hostEnv []string
100+
for _, e := range os.Environ() {
101+
if strings.HasPrefix(e, "CI=") || (strings.HasPrefix(e, "LOCALSTACK_") && !strings.HasPrefix(e, "LOCALSTACK_AUTH_TOKEN=")) {
102+
hostEnv = append(hostEnv, e)
103+
}
104+
}
105+
99106
containers := make([]runtime.ContainerConfig, len(opts.Containers))
100107
for i, c := range opts.Containers {
101108
image, err := c.Image()
@@ -128,6 +135,8 @@ func Start(ctx context.Context, rt runtime.Runtime, sink output.Sink, opts Start
128135
"MAIN_CONTAINER_NAME="+containerName,
129136
)
130137

138+
env = append(env, hostEnv...)
139+
131140
var binds []runtime.BindMount
132141
if socketPath := rt.SocketPath(); socketPath != "" {
133142
binds = append(binds, runtime.BindMount{HostPath: socketPath, ContainerPath: "/var/run/docker.sock"})

internal/container/start_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"errors"
77
"io"
8+
"strings"
89
"testing"
910

1011
"github.com/localstack/lstk/internal/log"
@@ -64,3 +65,26 @@ func TestServicePortRange_ReturnsExpectedPorts(t *testing.T) {
6465
assert.Equal(t, "4559", ports[50].ContainerPort)
6566
assert.Equal(t, "4559", ports[50].HostPort)
6667
}
68+
69+
func TestFilterHostEnv(t *testing.T) {
70+
tests := []struct {
71+
name string
72+
env string
73+
expected bool
74+
}{
75+
{"CI is included", "CI=true", true},
76+
{"LOCALSTACK_DISABLE_EVENTS is included", "LOCALSTACK_DISABLE_EVENTS=1", true},
77+
{"LOCALSTACK_HOST is included", "LOCALSTACK_HOST=0.0.0.0", true},
78+
{"LOCALSTACK_AUTH_TOKEN is excluded", "LOCALSTACK_AUTH_TOKEN=secret", false},
79+
{"PATH is excluded", "PATH=/usr/bin", false},
80+
{"HOME is excluded", "HOME=/root", false},
81+
{"LOCALSTACK_BUILD_VERSION is included", "LOCALSTACK_BUILD_VERSION=3.0.0", true},
82+
}
83+
84+
for _, tt := range tests {
85+
t.Run(tt.name, func(t *testing.T) {
86+
got := strings.HasPrefix(tt.env, "CI=") || (strings.HasPrefix(tt.env, "LOCALSTACK_") && !strings.HasPrefix(tt.env, "LOCALSTACK_AUTH_TOKEN="))
87+
assert.Equal(t, tt.expected, got)
88+
})
89+
}
90+
}

test/integration/start_test.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,34 @@ func TestStartCommandSetsUpContainerCorrectly(t *testing.T) {
226226
})
227227
}
228228

229-
// containerEnvToMap converts a Docker container's []string env to a map.
230-
func containerEnvToMap(envList []string) map[string]string {
231-
m := make(map[string]string, len(envList))
232-
for _, e := range envList {
233-
k, v, _ := strings.Cut(e, "=")
234-
m[k] = v
235-
}
236-
return m
229+
func TestStartCommandPassesCIAndLocalStackEnvVars(t *testing.T) {
230+
requireDocker(t)
231+
_ = env.Require(t, env.AuthToken)
232+
233+
cleanup()
234+
t.Cleanup(cleanup)
235+
236+
t.Setenv("CI", "true")
237+
t.Setenv("LOCALSTACK_DISABLE_EVENTS", "1")
238+
t.Setenv("LOCALSTACK_AUTH_TOKEN", "host-token")
239+
240+
mockServer := createMockLicenseServer(true)
241+
defer mockServer.Close()
242+
243+
ctx := testContext(t)
244+
_, stderr, err := runLstk(t, ctx, "", env.With(env.APIEndpoint, mockServer.URL), "start")
245+
require.NoError(t, err, "lstk start failed: %s", stderr)
246+
requireExitCode(t, 0, err)
247+
248+
inspect, err := dockerClient.ContainerInspect(ctx, containerName)
249+
require.NoError(t, err, "failed to inspect container")
250+
require.True(t, inspect.State.Running)
251+
252+
envVars := containerEnvToMap(inspect.Config.Env)
253+
assert.Equal(t, "true", envVars["CI"])
254+
assert.Equal(t, "1", envVars["LOCALSTACK_DISABLE_EVENTS"])
255+
assert.NotEmpty(t, envVars["LOCALSTACK_AUTH_TOKEN"])
256+
assert.NotEqual(t, "host-token", envVars["LOCALSTACK_AUTH_TOKEN"], "host LOCALSTACK_AUTH_TOKEN should not be passed through")
237257
}
238258

239259
// hasBindTarget checks if any bind mount targets the given container path.
@@ -247,6 +267,16 @@ func hasBindTarget(binds []string, containerPath string) bool {
247267
return false
248268
}
249269

270+
// containerEnvToMap converts a Docker container's []string env to a map.
271+
func containerEnvToMap(envList []string) map[string]string {
272+
m := make(map[string]string, len(envList))
273+
for _, e := range envList {
274+
k, v, _ := strings.Cut(e, "=")
275+
m[k] = v
276+
}
277+
return m
278+
}
279+
250280
func cleanup() {
251281
ctx := context.Background()
252282
_ = dockerClient.ContainerStop(ctx, containerName, container.StopOptions{})

0 commit comments

Comments
 (0)