Skip to content

Commit 570047a

Browse files
anisaoshaficlaude
andcommitted
Clean up snapshot save command and plain sink
Fix AWS-only guard, align container lookup with aws.go patterns, remove the unused NewPlainSinkSplit constructor and its dead errOut routing, and minor code clarity improvements. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c680041 commit 570047a

5 files changed

Lines changed: 17 additions & 60 deletions

File tree

cmd/snapshot.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cmd
33
import (
44
"fmt"
55
"os"
6-
"slices"
76
"time"
87

98
"github.com/localstack/lstk/internal/config"
@@ -57,29 +56,30 @@ Cloud destinations are not yet supported.`,
5756
return fmt.Errorf("failed to get config: %w", err)
5857
}
5958

60-
awsIdx := slices.IndexFunc(appConfig.Containers, func(c config.ContainerConfig) bool {
61-
return c.Type == config.EmulatorAWS
62-
})
63-
if awsIdx < 0 && len(appConfig.Containers) > 0 {
59+
awsContainer := config.ContainerConfig{Type: config.EmulatorAWS, Port: config.DefaultAWSPort}
60+
var found bool
61+
for _, c := range appConfig.Containers {
62+
if c.Type == config.EmulatorAWS {
63+
awsContainer = c
64+
found = true
65+
break
66+
}
67+
}
68+
if !found {
6469
return fmt.Errorf("snapshot is only supported for the AWS emulator")
6570
}
6671

6772
rt, err := runtime.NewDockerRuntime(cfg.DockerHost)
6873
if err != nil {
6974
return err
7075
}
71-
72-
awsContainer := config.ContainerConfig{Type: config.EmulatorAWS, Port: config.DefaultAWSPort}
73-
if awsIdx >= 0 {
74-
awsContainer = appConfig.Containers[awsIdx]
75-
}
7676
host, _ := endpoint.ResolveHost(cmd.Context(), awsContainer.Port, cfg.LocalStackHost)
7777
exporter := aws.NewClient()
7878

7979
if isInteractiveMode(cfg) {
8080
return ui.RunSnapshotSave(cmd.Context(), rt, []config.ContainerConfig{awsContainer}, exporter, host, dest)
8181
}
82-
return snapshot.Save(cmd.Context(), rt, []config.ContainerConfig{awsContainer}, exporter, host, dest, output.NewPlainSinkSplit(os.Stdout, os.Stderr))
82+
return snapshot.Save(cmd.Context(), rt, []config.ContainerConfig{awsContainer}, exporter, host, dest, output.NewPlainSink(os.Stdout))
8383
},
8484
}
8585
}

internal/output/plain_sink.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,15 @@ import (
77
)
88

99
type PlainSink struct {
10-
out io.Writer
11-
errOut io.Writer
12-
err error
10+
out io.Writer
11+
err error
1312
}
1413

1514
func NewPlainSink(out io.Writer) *PlainSink {
1615
if out == nil {
1716
out = os.Stdout
1817
}
19-
return &PlainSink{out: out, errOut: out}
20-
}
21-
22-
// NewPlainSinkSplit creates a PlainSink that routes ErrorEvents to errOut and all others to out.
23-
func NewPlainSinkSplit(out, errOut io.Writer) *PlainSink {
24-
if out == nil {
25-
out = os.Stdout
26-
}
27-
if errOut == nil {
28-
errOut = os.Stderr
29-
}
30-
return &PlainSink{out: out, errOut: errOut}
18+
return &PlainSink{out: out}
3119
}
3220

3321
// Err returns the first write error encountered, if any.
@@ -46,10 +34,6 @@ func (s *PlainSink) Emit(event Event) {
4634
if !ok {
4735
return
4836
}
49-
w := s.out
50-
if _, isErr := event.(ErrorEvent); isErr {
51-
w = s.errOut
52-
}
53-
_, err := fmt.Fprintln(w, line)
37+
_, err := fmt.Fprintln(s.out, line)
5438
s.setErr(err)
5539
}

internal/output/plain_sink_test.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -286,32 +286,6 @@ func TestPlainSink_TableWidth(t *testing.T) {
286286
})
287287
}
288288

289-
func TestPlainSinkSplit_RoutesErrorEventToErrOut(t *testing.T) {
290-
var out, errOut bytes.Buffer
291-
sink := NewPlainSinkSplit(&out, &errOut)
292-
293-
sink.Emit(ErrorEvent{Title: "Something failed"})
294-
295-
assert.Empty(t, out.String(), "ErrorEvent should not go to out")
296-
assert.Contains(t, errOut.String(), "Something failed")
297-
}
298-
299-
func TestPlainSinkSplit_RoutesOtherEventsToOut(t *testing.T) {
300-
var out, errOut bytes.Buffer
301-
sink := NewPlainSinkSplit(&out, &errOut)
302-
303-
sink.Emit(MessageEvent{Severity: SeverityInfo, Text: "hello"})
304-
305-
assert.Contains(t, out.String(), "hello")
306-
assert.Empty(t, errOut.String(), "MessageEvent should not go to errOut")
307-
}
308-
309-
func TestPlainSinkSplit_NilWritersFallback(t *testing.T) {
310-
// nil writers should not panic (fallback to os.Stdout/os.Stderr)
311-
sink := NewPlainSinkSplit(nil, nil)
312-
assert.NotNil(t, sink)
313-
}
314-
315289
func TestPlainSink_ErrReturnsNilOnSuccess(t *testing.T) {
316290
var out bytes.Buffer
317291
sink := NewPlainSink(&out)

internal/snapshot/destination.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ func ParseDestination(dest string, now time.Time) (string, error) {
3131
strings.HasPrefix(lower, "cloud:"):
3232
return "", ErrRemoteNotSupported
3333
case strings.Contains(lower, "://"):
34-
scheme := dest[:strings.Index(lower, "://")+3]
35-
return "", fmt.Errorf("%w: %q", ErrUnknownScheme, scheme)
34+
scheme, _, _ := strings.Cut(dest, "://")
35+
return "", fmt.Errorf("%w: %q", ErrUnknownScheme, scheme+"://")
3636
}
3737
}
3838

internal/snapshot/save.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"github.com/localstack/lstk/internal/runtime"
1313
)
1414

15-
// Save exports the emulator's state via exporter and writes it to dest.
1615
func Save(ctx context.Context, rt runtime.Runtime, containers []config.ContainerConfig, exporter StateExporter, host, dest string, sink output.Sink) (retErr error) {
1716
if err := rt.IsHealthy(ctx); err != nil {
1817
rt.EmitUnhealthyError(sink, err)

0 commit comments

Comments
 (0)