Skip to content

Commit 264c493

Browse files
authored
fix(cli): Close stdout when using --log-console (#2459)
when we use --log-console we dont want standard output. logs are by default written to stderr so we just close stdout which make any fmt.Print* silent. This makes it easy to use fmt.Print* in the CLI and not use any new abstractions and prop drilling. This also adds handling of ctrl+c, that should go together with this as well cloudquery/plugin-sdk#252
1 parent fb684c0 commit 264c493

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

cli/cmd/root.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"fmt"
45
"io"
56
"os"
67
"strings"
@@ -63,6 +64,9 @@ func NewCmdRoot() *cobra.Command {
6364
}
6465
}
6566
if logConsole {
67+
if err := os.Stdout.Close(); err != nil {
68+
return fmt.Errorf("failed to close stdout: %w", err)
69+
}
6670
if logFormat.String() == "text" {
6771
writers = append(writers, zerolog.ConsoleWriter{Out: os.Stderr, NoColor: noColor})
6872
} else {

cli/cmd/sync.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ func sync(cmd *cobra.Command, args []string) error {
4141
fmt.Printf("Loading spec(s) from %s\n", strings.Join(args, ", "))
4242
specReader, err := specs.NewSpecReader(args)
4343
if err != nil {
44-
log.Error().Strs("args", args).Err(err).Msg("Failed to load spec(s)")
4544
return fmt.Errorf("failed to load spec(s) from %s. Error: %w", strings.Join(args, ", "), err)
4645
}
4746

@@ -83,6 +82,7 @@ func syncConnection(ctx context.Context, sourceSpec specs.Source, destinationsSp
8382
}
8483
defer func() {
8584
if err := sourceClient.Terminate(); err != nil {
85+
log.Error().Err(err).Msg("Failed to terminate source client")
8686
fmt.Println("failed to terminate source client: ", err)
8787
}
8888
}()
@@ -96,6 +96,7 @@ func syncConnection(ctx context.Context, sourceSpec specs.Source, destinationsSp
9696
for _, destClient := range destClients {
9797
if destClient != nil {
9898
if err := destClient.Terminate(); err != nil {
99+
log.Error().Err(err).Msg("Failed to terminate destination client")
99100
fmt.Println("failed to terminate destination client: ", err)
100101
}
101102
}
@@ -123,6 +124,7 @@ func syncConnection(ctx context.Context, sourceSpec specs.Source, destinationsSp
123124

124125
resources := make(chan []byte)
125126
g, gctx := errgroup.WithContext(ctx)
127+
log.Info().Str("source", sourceSpec.Name).Strs("destinations", sourceSpec.Destinations).Msg("Start fetching resources")
126128
fmt.Println("Starting sync for: ", sourceSpec.Name, "->", sourceSpec.Destinations)
127129
g.Go(func() error {
128130
defer close(resources)
@@ -149,7 +151,7 @@ func syncConnection(ctx context.Context, sourceSpec specs.Source, destinationsSp
149151
var destFailedWrites uint64
150152
var err error
151153
if destFailedWrites, err = destClients[i].Write(gctx, sourceSpec.Path, syncTime, destSubscriptions[i]); err != nil {
152-
log.Error().Err(err).Msgf("failed to write for %s->%s", sourceSpec.Name, destination)
154+
return fmt.Errorf("failed to write for %s->%s: %w", sourceSpec.Name, destination, err)
153155
}
154156
failedWrites += destFailedWrites
155157
return nil
@@ -185,5 +187,7 @@ func syncConnection(ctx context.Context, sourceSpec specs.Source, destinationsSp
185187
_ = bar.Finish()
186188
fmt.Println("Sync completed successfully.")
187189
fmt.Printf("Summary: resources: %d, errors: %d, panic: %d failed_writes: %d\n", totalResources, summary.Errors, summary.Panics, failedWrites)
190+
log.Info().Str("source", sourceSpec.Name).Strs("destinations", sourceSpec.Destinations).
191+
Int("resources", totalResources).Uint64("errors", summary.Errors).Uint64("panic", summary.Panics).Uint64("failedWrites", failedWrites).Msg("sync completed successfully")
188192
return nil
189193
}

cli/main.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,38 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
56
"os"
7+
"os/signal"
68
"runtime/debug"
79

810
"github.com/cloudquery/cloudquery/cli/cmd"
911
"github.com/getsentry/sentry-go"
12+
"github.com/rs/zerolog/log"
1013
)
1114

15+
func executeRootCmdWithContext() error {
16+
ctx := context.Background()
17+
// trap Ctrl+C and call cancel on the context
18+
ctx, cancel := context.WithCancel(ctx)
19+
c := make(chan os.Signal, 1)
20+
signal.Notify(c, os.Interrupt)
21+
defer func() {
22+
signal.Stop(c)
23+
cancel()
24+
}()
25+
go func() {
26+
select {
27+
case <-c:
28+
cancel()
29+
case <-ctx.Done():
30+
}
31+
}()
32+
33+
return cmd.NewCmdRoot().ExecuteContext(ctx)
34+
}
35+
1236
func main() {
1337
defer func() {
1438
err := recover()
@@ -19,9 +43,9 @@ func main() {
1943
}
2044
}()
2145

22-
if err := cmd.NewCmdRoot().Execute(); err != nil {
23-
// This is fine that the defer function is not being calles as it means there was no panic
24-
//nolint:gocritic
46+
if err := executeRootCmdWithContext(); err != nil {
47+
log.Error().Err(err).Msg("exiting with error")
48+
//nolint:all This is fine if deffered is not called because there was no panic
2549
os.Exit(1)
2650
}
2751
}

0 commit comments

Comments
 (0)