Skip to content

Use already-running instances when discovery finds nothing#409

Draft
gtsiolis wants to merge 2 commits into
mainfrom
attach-external-localstack-instances
Draft

Use already-running instances when discovery finds nothing#409
gtsiolis wants to merge 2 commits into
mainfrom
attach-external-localstack-instances

Conversation

@gtsiolis

@gtsiolis gtsiolis commented Jul 24, 2026

Copy link
Copy Markdown
Member

Motivation

lstk aws (and the other proxies) could not target a LocalStack running from source: discovery was Docker-only (container name, then image match), so a plain-process instance on 4566 was invisible and every command pushed the user to start a container — reported by Duncan for the internal dev loop, but equally affecting hand-started containers with unknown images and remote instances via LOCALSTACK_HOST. The same gate also broke lstk az start-interception against a debug/host-mode Azure emulator (reported by Paolo), since it shares the proxy discovery path.

What changed

When Docker discovery finds nothing — or Docker is unavailable — lstk now probes GET /_localstack/info on the resolved host and silently attaches if a LocalStack instance answers (200 + JSON + non-empty version). The probe only runs on paths that errored before, so container flows are byte-for-byte unchanged and success paths gain no latency. This generalizes the attach precedent that lstk start's port-conflict fallback already had; that path now shares the same probe.

  • Adopted by: aws, az (incl. start-interception), terraform/cdk/sam, reset, snapshot save/load (incl. S3 save/load).
  • Wrong-type guard: when Docker is healthy and a known LocalStack container of another type is running, the probe answer is attributed to that container, keeping the existing type-mismatch errors (lstk terraform with only Snowflake up).
  • snapshot load's Docker auto-start runs only when Docker is healthy and nothing is reachable; an external instance is used as-is.
  • Unchanged: stop, logs, restart, status, snapshot list s3:///remove stay Docker-gated (follow-up: external-aware status + truthful "running, but not started by lstk" errors for stop/logs).
  • New helpers: container.ProbeEmulatorInfo, container.ResolveEmulator, container.FirstReachableEmulator, cmd/emulator.go:resolveReachableEmulator.

Testing

  • Unit: probe fingerprinting (non-200 / non-JSON / empty version / unreachable) and resolution (managed-found skips probe, fallback, nil-runtime, wrong-type guard, Docker-down error parity).
  • Integration (new external_instance_test.go, no Docker needed): aws/terraform/az/reset/snapshot-save/snapshot-load against a mock /_localstack/info server with a dead DOCKER_HOST — the aws case fails on main with "Docker is not available".
  • lstk az start-interception against a host-run Azure emulator (Paolo's debug-mode report): the shared azPreflight now finds the external instance instead of reporting "not running". Pinned by TestAzStartInterceptionUsesExternalInstance, which asserts the command gets past Docker-only discovery and reaches the interception reachability check; verified red→green against the pre-fix binary (pre-fix: "Docker is not available"). The full interception (global ~/.azure mutation) needs the emulator's TLS gateway + wildcard DNS and stays covered by TestSetupAzureAndAzCommandSucceed.
  • Existing negative tests ("is not running"/"Docker is not available") are pinned to a dead LOCALSTACK_HOST so they stay deterministic on machines with a real LocalStack on 4566.
  • Full integration suite run locally: only pre-existing failures remain (token-gated tests without LOCALSTACK_AUTH_TOKEN, and environment-specific ones — verified identical against a pre-change binary).
  • Manual end-to-end: with the Docker daemon stopped and LocalStack running from source (uv run -m localstack.runtime.main), lstk aws s3 mb/ls, lstk reset --force, and lstk snapshot save all succeed; the pre-change binary fails the same setup with "Docker is not available". lstk stop still errors truthfully.

Review

New user-facing behavior on five proxy commands plus reset/snapshot — human review advisable. The riskiest spots are the Docker-down error-precedence changes in FirstReachableEmulator/resolveReachableEmulator and the silent-attach semantics.

Closes DEVX-1016

Co-Authored-By: Claude noreply@anthropic.com

…nothing

Co-Authored-By: Claude <noreply@anthropic.com>
@gtsiolis
gtsiolis requested a review from a team as a code owner July 24, 2026 10:55
@gtsiolis gtsiolis added semver: minor docs: needed Pull request requires documentation updates labels Jul 24, 2026
@gtsiolis
gtsiolis marked this pull request as draft July 24, 2026 11:09
@gtsiolis gtsiolis changed the title Use already-running LocalStack instances when Docker discovery finds nothing Use already-running instances when discovery finds nothing Jul 24, 2026
@gtsiolis

Copy link
Copy Markdown
Member Author

Possibly not worth adding, but wanted to see the PoC in action. Feedback welcome.

@gtsiolis gtsiolis self-assigned this Jul 24, 2026
Co-Authored-By: Claude <noreply@anthropic.com>
@skyrpex

skyrpex commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

The probe only runs on paths that errored before, so container flows are byte-for-byte unchanged and success paths gain no latency.

That sounds good. My first instinct was to run the HTTP check in parallel to the container check but I bet the implementation remains must simpler this way.

(follow-up: external-aware status + truthful "running, but not started by lstk" errors for stop/logs)

Yeah, feels like lstk status should optionally work without a running container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs: needed Pull request requires documentation updates semver: minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants