Skip to content

Commit ca6f7bc

Browse files
surface friendly license error for self-validating emulators (azure/snowflake)
1 parent 278e241 commit ca6f7bc

3 files changed

Lines changed: 49 additions & 3 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ When no config file exists, lstk creates one at `$HOME/.config/lstk/config.toml`
6363
Use `lstk config path` to print the resolved config file path currently in use.
6464
When adding a new command that depends on configuration, wire config initialization explicitly in that command (`PreRunE: initConfig`). Keep side-effect-free commands (e.g., `version`, `config path`) without config initialization.
6565

66-
Created automatically on first run with defaults. Supports emulator types: `aws` and `snowflake`.
66+
Created automatically on first run with defaults. Supports emulator types: `aws`, `snowflake`, and `azure`.
6767

6868
# Emulator Setup Commands
6969

internal/container/start.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,10 @@ func startContainers(ctx context.Context, rt runtime.Runtime, sink output.Sink,
385385
sink.Emit(output.SpinnerStop())
386386
errCode := telemetry.ErrCodeStartFailed
387387
var licErr *licenseNotCoveredError
388-
if errors.As(err, &licErr) && c.EmulatorType == config.EmulatorSnowflake {
388+
if errors.As(err, &licErr) && c.EmulatorType.SelfValidatesLicense() {
389389
errCode = telemetry.ErrCodeLicenseInvalid
390390
sink.Emit(output.ErrorEvent{
391-
Title: "Your license does not include the Snowflake emulator.",
391+
Title: fmt.Sprintf("Your license does not include the %s emulator.", c.EmulatorType.ShortName()),
392392
Actions: []output.ErrorAction{
393393
{Label: "Sign up for a free trial:", Value: "https://app.localstack.cloud/sign-up"},
394394
{Label: "Contact our team:", Value: "https://www.localstack.cloud/demo"},

internal/container/start_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,3 +357,49 @@ func TestStartContainers_SnowflakeLicenseError(t *testing.T) {
357357
t.Fatal("no telemetry event received")
358358
}
359359
}
360+
361+
func TestStartContainers_AzureLicenseError(t *testing.T) {
362+
ctrl := gomock.NewController(t)
363+
mockRT := runtime.NewMockRuntime(ctrl)
364+
365+
c := runtime.ContainerConfig{
366+
Image: "localstack/localstack-azure-alpha:latest",
367+
Name: "localstack-azure",
368+
EmulatorType: config.EmulatorAzure,
369+
Tag: "latest",
370+
Port: "4566",
371+
ContainerPort: "4566/tcp",
372+
HealthPath: "/_localstack/health",
373+
}
374+
const containerID = "abc123"
375+
licenseLog := "The Azure emulator is currently not covered by your license."
376+
mockRT.EXPECT().Start(gomock.Any(), c).Return(containerID, nil)
377+
mockRT.EXPECT().IsRunning(gomock.Any(), containerID).Return(false, nil)
378+
mockRT.EXPECT().Logs(gomock.Any(), containerID, 20).Return(licenseLog, nil)
379+
380+
tel, capturedEvents := newCapturingTelClient(t)
381+
382+
var out bytes.Buffer
383+
sink := output.NewPlainSink(&out)
384+
385+
err := startContainers(context.Background(), mockRT, sink, tel, []runtime.ContainerConfig{c}, map[string]bool{})
386+
tel.Close()
387+
388+
require.Error(t, err)
389+
assert.True(t, output.IsSilent(err), "error should be silent since ErrorEvent was already emitted")
390+
got := out.String()
391+
assert.Contains(t, got, "Your license does not include the Azure emulator.")
392+
assert.Contains(t, got, "https://app.localstack.cloud/sign-up")
393+
assert.Contains(t, got, "https://www.localstack.cloud/demo")
394+
395+
select {
396+
case ev := <-capturedEvents:
397+
payload, ok := ev["payload"].(map[string]any)
398+
require.True(t, ok, "telemetry event should have a payload map")
399+
assert.Equal(t, telemetry.LifecycleStartError, payload["event_type"])
400+
assert.Equal(t, telemetry.ErrCodeLicenseInvalid, payload["error_code"])
401+
assert.Equal(t, "azure", payload["emulator"])
402+
default:
403+
t.Fatal("no telemetry event received")
404+
}
405+
}

0 commit comments

Comments
 (0)