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) }