feat: add --type flag to start for non-interactive emulator selection#381
Conversation
fde3a84 to
a3ea678
Compare
|
Commenting for reach as this would be nice to merge before Thursday's release. |
6d2f109 to
e00dc3a
Compare
anisaoshafi
left a comment
There was a problem hiding this comment.
I run these two commands consecutively:
./bin/lstk -t azure
./bin/lstk -t snowflake.
Because azure emulator was already running, ./bin/lstk -t snowflake fails with an error Your config specifies the LocalStack Snowflake Emulator. Only one emulator can run on a port at a time., however it DOES change the configuration profile.
I think it shouldn't change the config file if it doesn't finish successfully, because some subsequent commands will fail as they won't detect the running emulator, e.g ./bin/lstk status:
e00dc3a to
de2b2e6
Compare
|
@anisaoshafi Nice catch, fixed in de2b2e6. The --type switch now checks whether a different emulator is already running on the port first, and refuses the switch (config untouched) if so. Added tests, including one reproducing your azure -> snowflake repro. Could you take another look? |
Add --type/-t (aws|snowflake|azure) to `lstk start` and the bare root command as the non-interactive answer to the first-run emulator picker. It records the selection in config: creating the file on first run (reusing the picker's EnsureCreated/SetEmulatorType path), no-op when the configured type already matches, and switching the type line in place when it differs (preserving comments/formatting, with a note naming the file). On switch, a custom `image` is a hard error (it pins a product that can't be reinterpreted under a new type), a non-latest `tag` and any volume mounts are kept with a warning, and `port`/`env`/`snapshot` are kept silently. The type may also be given as a positional (`lstk start azure`) and `start` now validates arg count. Also add a `-c` shorthand for `--config` (stripped for proxy commands too) and a README CI example. Generated with [Linear](https://linear.app/localstack/issue/DEVX-985/add-type-flag-to-start-for-non-interactive-emulator-selection#agent-session-09427df8) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
SetEmulatorType replaced every `type = "..."` match in the file, so an in-place `--type` switch could also rewrite commented-out example blocks, a second [[containers]] block, or an unrelated `content_type` key. Anchor the regex to the start of a line and splice only the first match's value, so quotes, spacing, trailing comments, and other keys are all preserved. Also reject a multi-block config before mutating it (the start path rejects it anyway, so a rewrite would leave a half-changed config that can't start), use the emulator's display name in the switch note for casing consistency, and add regression tests plus coverage for the bare-root `lstk --type` form. Co-authored-by: Claude <noreply@anthropic.com>
The positional form (`lstk start azure`) implied a mental model the bare root contradicts: `lstk aws`/`lstk az` are proxy subcommands that run the wrapped CLI, and `lstk azure`/`lstk snowflake` route to extension dispatch, so the positional could only ever work on `start`, never on the bare root. Keep one self-documenting spelling — `--type`/`-t`, which works identically on `start` and the bare root. A stray positional is now rejected with a hint pointing at --type instead of silently starting AWS.
The -c shorthand added for --config was stripped from proxy args in stripGlobalFlags, swallowing the -c flags that wrapped tools own (CDK's -c/--context, SAM's -c/--cached). For example lstk cdk synth -c env=prod failed with "failed to read config file: open env=prod". Drop the shorthand: --config stays long-form only, and -c passes through to the wrapped tool. --type/-t remains the emulator selector Maureen asked for.
Review follow-up. SetEmulatorType matched the first anchored type = "..." line anywhere in the file, so a type key in an earlier table (e.g. an [env.*] profile) would be rewritten instead of the container's — silently failing the switch and corrupting an unrelated key. Scope the search to the active [[containers]] block (from its header to the next table header), and error clearly when the file has no such block. Also guard the empty-config branch of ApplyEmulatorType (clear error instead of a panic-prone containers[0] access) and fall back to a generic phrase when the friendly config path is empty so the tag/volume/image messages still read as sentences.
Rewriting the config to the requested type before checking whether the start would actually succeed left status/stop/logs unable to find a still-running emulator of the previous type once the start failed on the port conflict.
de2b2e6 to
53431ca
Compare
Thanks for tackling that 💯 |
|
Thanks for merging, @anisaoshafi! 🏀 Generated by Claude Code |
Adds
--type/-t(aws|snowflake|azure) tolstk startand the bare root command as the non-interactive answer to the first-run emulator picker. Becausestop,status,logs,volume, and snapshot auto-load all resolve from the configured type, the flag records the selection in config rather than overriding it per-run — an ephemeral override would strand every follow-up command (none of them take--type), so persisting keeps config and reality in sync for CI scripts.Behaviour:
EnsureCreated/SetEmulatorTypepath.typeline in place via a surgical rewrite. The search is anchored to the active[[containers]]block (from its header to the next table header), so quotes, spacing, trailing comments, other keys, and anytypekey in another table (e.g. an[env.*]profile) are all left untouched. A note names the file.On a switch the other block fields are kept, with guards: a custom
imageis a hard error (it pins a specific product that can't be reinterpreted under a new type — use--configfor a separate profile); a non-latesttagand anyvolumes/volumeare kept with a warning;port/env/snapshotare kept silently. A config with more than one[[containers]]block is rejected before any write, since only one block can start.The domain logic lives in
container.ApplyEmulatorType(parallel tocontainer.SelectEmulator) and is applied at the top ofstartEmulatorbefore snapshot/start-options are resolved, so it runs before the TUI.Also in this PR:
lstk start azure) is rejected with a hint pointing at--type(previously it silently started AWS).Dropped along the way (with why):
Positional emulator selection (
lstk start azureas an accepted alias).lstk aws/lstk azare already proxy subcommands andlstk azure/lstk snowflakeroute to extension dispatch, so a positional could only work onstart, never symmetrically on the bare root — it would teach a mental model the root contradicts.startnow rejects a positional with a hint instead.-cshorthand for--config. It was stripped from proxy args, which swallowed the-cflags wrapped tools own (CDK-c/--context, SAM-c/--cached) — e.g.lstk cdk synth -c env=prodfailed withfailed to read config file: open env=prod.--configstays long-form only; proxy commands forward-cto the wrapped tool.Ephemeral per-run override (start Azure once without touching config). See the opening note: the follow-up commands are config-seeded, so a non-persistent flag would half-work. The flag persists instead.