diff --git a/cli/app/logs.go b/cli/app/logs.go index ae32475b..ddb24b69 100644 --- a/cli/app/logs.go +++ b/cli/app/logs.go @@ -4,74 +4,54 @@ import ( "fmt" "io" "os" - "sync" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" - dockerClient "github.com/docker/docker/client" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) -// stackLogs lists logs for all stack services -func stackLogs(c *cli.Context, stackName string, client *dockerClient.Client) { - filters := filters.NewArgs() - filters.Add("name", stackName) - serviceOpts := types.ServiceListOptions{Filters: filters} - services, err := client.ServiceList(c.Context, serviceOpts) - if err != nil { - logrus.Fatal(err) - } - - var wg sync.WaitGroup - for _, service := range services { - wg.Add(1) - go func(s string) { - logOpts := types.ContainerLogsOptions{ - Details: false, - Follow: true, - ShowStderr: true, - ShowStdout: true, - Tail: "20", - Timestamps: true, - } - logs, err := client.ServiceLogs(c.Context, s, logOpts) - if err != nil { - logrus.Fatal(err) - } - // defer after err check as any err returns a nil io.ReadCloser - defer logs.Close() - - _, err = io.Copy(os.Stdout, logs) - if err != nil && err != io.EOF { - logrus.Fatal(err) - } - }(service.ID) - } - wg.Wait() - os.Exit(0) -} - var appLogsCommand = &cli.Command{ Name: "logs", Aliases: []string{"l"}, ArgsUsage: "[]", Usage: "Tail app logs", + Flags: []cli.Flag{ + internal.StderrFlag, + internal.StdoutFlag, + internal.HealthcheckFlag, + }, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + if !internal.Stderr && !internal.Stdout && !internal.Healthcheck { + internal.Stderr = true + internal.Stdout = true + internal.Healthcheck = true + } + + logrus.Debugf("flags parsed. --stderr: %t, --stdout: %t, --healthcheck: %t", internal.Stderr, internal.Stdout, internal.Healthcheck) cl, err := client.New(app.Server) if err != nil { logrus.Fatal(err) } + logOpts := types.ContainerLogsOptions{ + Details: false, + Follow: true, + ShowStderr: internal.Stderr, + ShowStdout: internal.Stdout, + Tail: "20", + Timestamps: true, + } + serviceName := c.Args().Get(1) if serviceName == "" { logrus.Debug("tailing logs for all app services") - stackLogs(c, app.StackName(), cl) + internal.StackLogs(c, app.StackName(), logOpts, cl) } logrus.Debugf("tailing logs for '%s'", serviceName) @@ -87,14 +67,6 @@ var appLogsCommand = &cli.Command{ logrus.Fatalf("expected 1 service but got %v", len(services)) } - logOpts := types.ContainerLogsOptions{ - Details: false, - Follow: true, - ShowStderr: true, - ShowStdout: true, - Tail: "20", - Timestamps: true, - } logs, err := cl.ServiceLogs(c.Context, services[0].ID, logOpts) if err != nil { logrus.Fatal(err) diff --git a/cli/internal/logs.go b/cli/internal/logs.go new file mode 100644 index 00000000..4ee22aaa --- /dev/null +++ b/cli/internal/logs.go @@ -0,0 +1,68 @@ +package internal + +import ( + "io" + "os" + "sync" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + dockerClient "github.com/docker/docker/client" + "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" +) + +var Stderr bool +var StderrFlag = &cli.BoolFlag{ + Name: "stderr", + Aliases: []string{"e"}, + Value: false, + Destination: &Stderr, +} + +var Stdout bool +var StdoutFlag = &cli.BoolFlag{ + Name: "stdout", + Aliases: []string{"o"}, + Value: false, + Destination: &Stdout, +} + +var Healthcheck bool +var HealthcheckFlag = &cli.BoolFlag{ + Name: "healthcheck", + Aliases: []string{"c"}, + Value: false, + Destination: &Healthcheck, +} + +// StackLogs lists logs for all stack services +func StackLogs(c *cli.Context, stackName string, logOpts types.ContainerLogsOptions, client *dockerClient.Client) { + filters := filters.NewArgs() + filters.Add("name", stackName) + serviceOpts := types.ServiceListOptions{Filters: filters} + services, err := client.ServiceList(c.Context, serviceOpts) + if err != nil { + logrus.Fatal(err) + } + + var wg sync.WaitGroup + for _, service := range services { + wg.Add(1) + go func(s string) { + logs, err := client.ServiceLogs(c.Context, s, logOpts) + if err != nil { + logrus.Fatal(err) + } + // defer after err check as any err returns a nil io.ReadCloser + defer logs.Close() + + _, err = io.Copy(os.Stdout, logs) + if err != nil && err != io.EOF { + logrus.Fatal(err) + } + }(service.ID) + } + wg.Wait() + os.Exit(0) +}