mirror of
https://github.com/docker/compose.git
synced 2025-07-01 02:44:25 +02:00
don't assume os.Stdout and rely on dockerCLI.streams
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
dacf24374d
commit
24f83271f2
@ -73,7 +73,7 @@ var printerModes = []string{
|
|||||||
buildx.PrinterModeQuiet,
|
buildx.PrinterModeQuiet,
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func buildCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := buildOptions{
|
opts := buildOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ func buildCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
Short: "Build or rebuild services",
|
Short: "Build or rebuild services",
|
||||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
if opts.memory != "" {
|
if opts.memory != "" {
|
||||||
fmt.Println("WARNING --memory is ignored as not supported in buildkit.")
|
fmt.Fprintln(streams.Err(), "WARNING --memory is ignored as not supported in buildkit.")
|
||||||
}
|
}
|
||||||
if opts.quiet {
|
if opts.quiet {
|
||||||
opts.progress = buildx.PrinterModeQuiet
|
opts.progress = buildx.PrinterModeQuiet
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"github.com/docker/buildx/util/logutil"
|
"github.com/docker/buildx/util/logutil"
|
||||||
dockercli "github.com/docker/cli/cli"
|
dockercli "github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli-plugins/manager"
|
"github.com/docker/cli/cli-plugins/manager"
|
||||||
"github.com/docker/cli/cli/command"
|
|
||||||
"github.com/morikuni/aec"
|
"github.com/morikuni/aec"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -243,7 +242,7 @@ func RunningAsStandalone() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RootCommand returns the compose command with its child commands
|
// RootCommand returns the compose command with its child commands
|
||||||
func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //nolint:gocyclo
|
func RootCommand(streams api.Streams, backend api.Service) *cobra.Command { //nolint:gocyclo
|
||||||
// filter out useless commandConn.CloseWrite warning message that can occur
|
// filter out useless commandConn.CloseWrite warning message that can occur
|
||||||
// when using a remote context that is unreachable: "commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
|
// when using a remote context that is unreachable: "commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
|
||||||
// https://github.com/docker/cli/blob/e1f24d3c93df6752d3c27c8d61d18260f141310c/cli/connhelper/commandconn/commandconn.go#L203-L215
|
// https://github.com/docker/cli/blob/e1f24d3c93df6752d3c27c8d61d18260f141310c/cli/connhelper/commandconn/commandconn.go#L203-L215
|
||||||
@ -305,7 +304,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
|
|||||||
if verbose {
|
if verbose {
|
||||||
logrus.SetLevel(logrus.TraceLevel)
|
logrus.SetLevel(logrus.TraceLevel)
|
||||||
}
|
}
|
||||||
formatter.SetANSIMode(ansi)
|
formatter.SetANSIMode(streams, ansi)
|
||||||
switch ansi {
|
switch ansi {
|
||||||
case "never":
|
case "never":
|
||||||
progress.Mode = progress.ModePlain
|
progress.Mode = progress.ModePlain
|
||||||
@ -333,27 +332,27 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.AddCommand(
|
c.AddCommand(
|
||||||
upCommand(&opts, backend),
|
upCommand(&opts, streams, backend),
|
||||||
downCommand(&opts, backend),
|
downCommand(&opts, backend),
|
||||||
startCommand(&opts, backend),
|
startCommand(&opts, backend),
|
||||||
restartCommand(&opts, backend),
|
restartCommand(&opts, backend),
|
||||||
stopCommand(&opts, backend),
|
stopCommand(&opts, backend),
|
||||||
psCommand(&opts, backend),
|
psCommand(&opts, streams, backend),
|
||||||
listCommand(backend),
|
listCommand(streams, backend),
|
||||||
logsCommand(&opts, backend),
|
logsCommand(&opts, streams, backend),
|
||||||
convertCommand(&opts, backend),
|
convertCommand(&opts, streams, backend),
|
||||||
killCommand(&opts, backend),
|
killCommand(&opts, backend),
|
||||||
runCommand(&opts, dockerCli, backend),
|
runCommand(&opts, streams, backend),
|
||||||
removeCommand(&opts, backend),
|
removeCommand(&opts, backend),
|
||||||
execCommand(&opts, dockerCli, backend),
|
execCommand(&opts, streams, backend),
|
||||||
pauseCommand(&opts, backend),
|
pauseCommand(&opts, backend),
|
||||||
unpauseCommand(&opts, backend),
|
unpauseCommand(&opts, backend),
|
||||||
topCommand(&opts, backend),
|
topCommand(&opts, streams, backend),
|
||||||
eventsCommand(&opts, backend),
|
eventsCommand(&opts, streams, backend),
|
||||||
portCommand(&opts, backend),
|
portCommand(&opts, streams, backend),
|
||||||
imagesCommand(&opts, backend),
|
imagesCommand(&opts, streams, backend),
|
||||||
versionCommand(),
|
versionCommand(),
|
||||||
buildCommand(&opts, backend),
|
buildCommand(&opts, streams, backend),
|
||||||
pushCommand(&opts, backend),
|
pushCommand(&opts, backend),
|
||||||
pullCommand(&opts, backend),
|
pullCommand(&opts, backend),
|
||||||
createCommand(&opts, backend),
|
createCommand(&opts, backend),
|
||||||
|
@ -50,7 +50,7 @@ type convertOptions struct {
|
|||||||
noConsistency bool
|
noConsistency bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func convertCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := convertOptions{
|
opts := convertOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -73,22 +73,22 @@ func convertCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
}),
|
}),
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
if opts.services {
|
if opts.services {
|
||||||
return runServices(opts)
|
return runServices(streams, opts)
|
||||||
}
|
}
|
||||||
if opts.volumes {
|
if opts.volumes {
|
||||||
return runVolumes(opts)
|
return runVolumes(streams, opts)
|
||||||
}
|
}
|
||||||
if opts.hash != "" {
|
if opts.hash != "" {
|
||||||
return runHash(opts)
|
return runHash(streams, opts)
|
||||||
}
|
}
|
||||||
if opts.profiles {
|
if opts.profiles {
|
||||||
return runProfiles(opts, args)
|
return runProfiles(streams, opts, args)
|
||||||
}
|
}
|
||||||
if opts.images {
|
if opts.images {
|
||||||
return runConfigImages(opts, args)
|
return runConfigImages(streams, opts, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runConvert(ctx, backend, opts, args)
|
return runConvert(ctx, streams, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ func convertCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runConvert(ctx context.Context, backend api.Service, opts convertOptions, services []string) error {
|
func runConvert(ctx context.Context, streams api.Streams, backend api.Service, opts convertOptions, services []string) error {
|
||||||
var content []byte
|
var content []byte
|
||||||
project, err := opts.ToProject(services,
|
project, err := opts.ToProject(services,
|
||||||
cli.WithInterpolation(!opts.noInterpolate),
|
cli.WithInterpolation(!opts.noInterpolate),
|
||||||
@ -139,7 +139,7 @@ func runConvert(ctx context.Context, backend api.Service, opts convertOptions, s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var out io.Writer = os.Stdout
|
var out io.Writer = streams.Out()
|
||||||
if opts.Output != "" && len(content) > 0 {
|
if opts.Output != "" && len(content) > 0 {
|
||||||
file, err := os.Create(opts.Output)
|
file, err := os.Create(opts.Output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,29 +151,29 @@ func runConvert(ctx context.Context, backend api.Service, opts convertOptions, s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func runServices(opts convertOptions) error {
|
func runServices(streams api.Streams, opts convertOptions) error {
|
||||||
project, err := opts.ToProject(nil)
|
project, err := opts.ToProject(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return project.WithServices(project.ServiceNames(), func(s types.ServiceConfig) error {
|
return project.WithServices(project.ServiceNames(), func(s types.ServiceConfig) error {
|
||||||
fmt.Println(s.Name)
|
fmt.Fprintln(streams.Out(), s.Name)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func runVolumes(opts convertOptions) error {
|
func runVolumes(streams api.Streams, opts convertOptions) error {
|
||||||
project, err := opts.ToProject(nil)
|
project, err := opts.ToProject(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for n := range project.Volumes {
|
for n := range project.Volumes {
|
||||||
fmt.Println(n)
|
fmt.Fprintln(streams.Out(), n)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHash(opts convertOptions) error {
|
func runHash(streams api.Streams, opts convertOptions) error {
|
||||||
var services []string
|
var services []string
|
||||||
if opts.hash != "*" {
|
if opts.hash != "*" {
|
||||||
services = append(services, strings.Split(opts.hash, ",")...)
|
services = append(services, strings.Split(opts.hash, ",")...)
|
||||||
@ -187,12 +187,12 @@ func runHash(opts convertOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("%s %s\n", s.Name, hash)
|
fmt.Fprintf(streams.Out(), "%s %s\n", s.Name, hash)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runProfiles(opts convertOptions, services []string) error {
|
func runProfiles(streams api.Streams, opts convertOptions, services []string) error {
|
||||||
set := map[string]struct{}{}
|
set := map[string]struct{}{}
|
||||||
project, err := opts.ToProject(services)
|
project, err := opts.ToProject(services)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -209,21 +209,21 @@ func runProfiles(opts convertOptions, services []string) error {
|
|||||||
}
|
}
|
||||||
sort.Strings(profiles)
|
sort.Strings(profiles)
|
||||||
for _, p := range profiles {
|
for _, p := range profiles {
|
||||||
fmt.Println(p)
|
fmt.Fprintln(streams.Out(), p)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runConfigImages(opts convertOptions, services []string) error {
|
func runConfigImages(streams api.Streams, opts convertOptions, services []string) error {
|
||||||
project, err := opts.ToProject(services)
|
project, err := opts.ToProject(services)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, s := range project.Services {
|
for _, s := range project.Services {
|
||||||
if s.Image != "" {
|
if s.Image != "" {
|
||||||
fmt.Println(s.Image)
|
fmt.Fprintln(streams.Out(), s.Image)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s%s%s\n", project.Name, api.Separator, s.Name)
|
fmt.Fprintf(streams.Out(), "%s%s%s\n", project.Name, api.Separator, s.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -31,7 +31,7 @@ type eventsOpts struct {
|
|||||||
json bool
|
json bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func eventsCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func eventsCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := eventsOpts{
|
opts := eventsOpts{
|
||||||
composeOptions: &composeOptions{
|
composeOptions: &composeOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
@ -41,7 +41,7 @@ func eventsCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
Use: "events [OPTIONS] [SERVICE...]",
|
Use: "events [OPTIONS] [SERVICE...]",
|
||||||
Short: "Receive real time events from containers.",
|
Short: "Receive real time events from containers.",
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runEvents(ctx, backend, opts, args)
|
return runEvents(ctx, streams, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ func eventsCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error {
|
func runEvents(ctx context.Context, streams api.Streams, backend api.Service, opts eventsOpts, services []string) error {
|
||||||
name, err := opts.toProjectName()
|
name, err := opts.toProjectName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -71,9 +71,9 @@ func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, servic
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println(string(marshal))
|
fmt.Fprintln(streams.Out(), string(marshal))
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(event)
|
fmt.Fprintln(streams.Out(), event)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
"github.com/docker/compose/v2/pkg/compose"
|
"github.com/docker/compose/v2/pkg/compose"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -43,7 +42,7 @@ type execOpts struct {
|
|||||||
interactive bool
|
interactive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func execCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
|
func execCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := execOpts{
|
opts := execOpts{
|
||||||
composeOptions: &composeOptions{
|
composeOptions: &composeOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
@ -69,7 +68,7 @@ func execCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
|
|||||||
runCmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
|
runCmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
|
||||||
runCmd.Flags().BoolVarP(&opts.privileged, "privileged", "", false, "Give extended privileges to the process.")
|
runCmd.Flags().BoolVarP(&opts.privileged, "privileged", "", false, "Give extended privileges to the process.")
|
||||||
runCmd.Flags().StringVarP(&opts.user, "user", "u", "", "Run the command as this user.")
|
runCmd.Flags().StringVarP(&opts.user, "user", "u", "", "Run the command as this user.")
|
||||||
runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")
|
runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", !streams.Out().IsTerminal(), "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")
|
||||||
runCmd.Flags().StringVarP(&opts.workingDir, "workdir", "w", "", "Path to workdir directory for this command.")
|
runCmd.Flags().StringVarP(&opts.workingDir, "workdir", "w", "", "Path to workdir directory for this command.")
|
||||||
|
|
||||||
runCmd.Flags().BoolVarP(&opts.interactive, "interactive", "i", true, "Keep STDIN open even if not attached.")
|
runCmd.Flags().BoolVarP(&opts.interactive, "interactive", "i", true, "Keep STDIN open even if not attached.")
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ type imageOptions struct {
|
|||||||
Format string
|
Format string
|
||||||
}
|
}
|
||||||
|
|
||||||
func imagesCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func imagesCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := imageOptions{
|
opts := imageOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -47,7 +46,7 @@ func imagesCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
Use: "images [OPTIONS] [SERVICE...]",
|
Use: "images [OPTIONS] [SERVICE...]",
|
||||||
Short: "List images used by the created containers",
|
Short: "List images used by the created containers",
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runImages(ctx, backend, opts, args)
|
return runImages(ctx, streams, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -56,7 +55,7 @@ func imagesCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return imgCmd
|
return imgCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runImages(ctx context.Context, backend api.Service, opts imageOptions, services []string) error {
|
func runImages(ctx context.Context, streams api.Streams, backend api.Service, opts imageOptions, services []string) error {
|
||||||
projectName, err := opts.toProjectName()
|
projectName, err := opts.toProjectName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -81,7 +80,7 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, img := range ids {
|
for _, img := range ids {
|
||||||
fmt.Println(img)
|
fmt.Fprintln(streams.Out(), img)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -90,7 +89,7 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
|
|||||||
return images[i].ContainerName < images[j].ContainerName
|
return images[i].ContainerName < images[j].ContainerName
|
||||||
})
|
})
|
||||||
|
|
||||||
return formatter.Print(images, opts.Format, os.Stdout,
|
return formatter.Print(images, opts.Format, streams.Out(),
|
||||||
func(w io.Writer) {
|
func(w io.Writer) {
|
||||||
for _, img := range images {
|
for _, img := range images {
|
||||||
id := stringid.TruncateID(img.ID)
|
id := stringid.TruncateID(img.ID)
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/compose/v2/cmd/formatter"
|
"github.com/docker/compose/v2/cmd/formatter"
|
||||||
@ -38,13 +37,13 @@ type lsOptions struct {
|
|||||||
Filter opts.FilterOpt
|
Filter opts.FilterOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
func listCommand(backend api.Service) *cobra.Command {
|
func listCommand(streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
lsOpts := lsOptions{Filter: opts.NewFilterOpt()}
|
lsOpts := lsOptions{Filter: opts.NewFilterOpt()}
|
||||||
lsCmd := &cobra.Command{
|
lsCmd := &cobra.Command{
|
||||||
Use: "ls [OPTIONS]",
|
Use: "ls [OPTIONS]",
|
||||||
Short: "List running compose projects",
|
Short: "List running compose projects",
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runList(ctx, backend, lsOpts)
|
return runList(ctx, streams, backend, lsOpts)
|
||||||
}),
|
}),
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
ValidArgsFunction: noCompletion(),
|
ValidArgsFunction: noCompletion(),
|
||||||
@ -61,7 +60,7 @@ var acceptedListFilters = map[string]bool{
|
|||||||
"name": true,
|
"name": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
|
func runList(ctx context.Context, streams api.Streams, backend api.Service, lsOpts lsOptions) error {
|
||||||
filters := lsOpts.Filter.Value()
|
filters := lsOpts.Filter.Value()
|
||||||
err := filters.Validate(acceptedListFilters)
|
err := filters.Validate(acceptedListFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -74,7 +73,7 @@ func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
|
|||||||
}
|
}
|
||||||
if lsOpts.Quiet {
|
if lsOpts.Quiet {
|
||||||
for _, s := range stackList {
|
for _, s := range stackList {
|
||||||
fmt.Println(s.Name)
|
fmt.Fprintln(streams.Out(), s.Name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -91,7 +90,7 @@ func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
view := viewFromStackList(stackList)
|
view := viewFromStackList(stackList)
|
||||||
return formatter.Print(view, lsOpts.Format, os.Stdout, func(w io.Writer) {
|
return formatter.Print(view, lsOpts.Format, streams.Out(), func(w io.Writer) {
|
||||||
for _, stack := range view {
|
for _, stack := range view {
|
||||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", stack.Name, stack.Status, stack.ConfigFiles)
|
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", stack.Name, stack.Status, stack.ConfigFiles)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ type logsOptions struct {
|
|||||||
timestamps bool
|
timestamps bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func logsCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func logsCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := logsOptions{
|
opts := logsOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -46,7 +45,7 @@ func logsCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
Use: "logs [OPTIONS] [SERVICE...]",
|
Use: "logs [OPTIONS] [SERVICE...]",
|
||||||
Short: "View output from containers",
|
Short: "View output from containers",
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runLogs(ctx, backend, opts, args)
|
return runLogs(ctx, streams, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -61,12 +60,12 @@ func logsCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return logsCmd
|
return logsCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runLogs(ctx context.Context, backend api.Service, opts logsOptions, services []string) error {
|
func runLogs(ctx context.Context, streams api.Streams, backend api.Service, opts logsOptions, services []string) error {
|
||||||
project, name, err := opts.projectOrName(services...)
|
project, name, err := opts.projectOrName(services...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
consumer := formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !opts.noColor, !opts.noPrefix, false)
|
consumer := formatter.NewLogConsumer(ctx, streams.Out(), streams.Err(), !opts.noColor, !opts.noPrefix, false)
|
||||||
return backend.Logs(ctx, name, consumer, api.LogOptions{
|
return backend.Logs(ctx, name, consumer, api.LogOptions{
|
||||||
Project: project,
|
Project: project,
|
||||||
Services: services,
|
Services: services,
|
||||||
|
@ -34,7 +34,7 @@ type portOptions struct {
|
|||||||
index int
|
index int
|
||||||
}
|
}
|
||||||
|
|
||||||
func portCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func portCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := portOptions{
|
opts := portOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ func portCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return nil
|
return nil
|
||||||
}),
|
}),
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runPort(ctx, backend, opts, args[0])
|
return runPort(ctx, streams, backend, opts, args[0])
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ func portCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPort(ctx context.Context, backend api.Service, opts portOptions, service string) error {
|
func runPort(ctx context.Context, streams api.Streams, backend api.Service, opts portOptions, service string) error {
|
||||||
projectName, err := opts.toProjectName()
|
projectName, err := opts.toProjectName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -74,6 +74,6 @@ func runPort(ctx context.Context, backend api.Service, opts portOptions, service
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%s:%d\n", ip, port)
|
fmt.Fprintf(streams.Out(), "%s:%d\n", ip, port)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -67,7 +66,7 @@ func (p *psOptions) parseFilter() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func psCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func psCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := psOptions{
|
opts := psOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -78,7 +77,7 @@ func psCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return opts.parseFilter()
|
return opts.parseFilter()
|
||||||
},
|
},
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runPs(ctx, backend, args, opts)
|
return runPs(ctx, streams, backend, args, opts)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -92,7 +91,7 @@ func psCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
return psCmd
|
return psCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error {
|
func runPs(ctx context.Context, streams api.Streams, backend api.Service, services []string, opts psOptions) error {
|
||||||
project, name, err := opts.projectOrName(services...)
|
project, name, err := opts.projectOrName(services...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -126,7 +125,7 @@ SERVICES:
|
|||||||
|
|
||||||
if opts.Quiet {
|
if opts.Quiet {
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
fmt.Println(c.ID)
|
fmt.Fprintln(streams.Out(), c.ID)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -138,11 +137,11 @@ SERVICES:
|
|||||||
services = append(services, s.Service)
|
services = append(services, s.Service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println(strings.Join(services, "\n"))
|
fmt.Fprintln(streams.Out(), strings.Join(services, "\n"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatter.Print(containers, opts.Format, os.Stdout,
|
return formatter.Print(containers, opts.Format, streams.Out(),
|
||||||
writer(containers),
|
writer(containers),
|
||||||
"NAME", "IMAGE", "COMMAND", "SERVICE", "CREATED", "STATUS", "PORTS")
|
"NAME", "IMAGE", "COMMAND", "SERVICE", "CREATED", "STATUS", "PORTS")
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,12 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/streams"
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
"github.com/docker/compose/v2/pkg/mocks"
|
"github.com/docker/compose/v2/pkg/mocks"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@ -30,10 +32,6 @@ import (
|
|||||||
|
|
||||||
func TestPsTable(t *testing.T) {
|
func TestPsTable(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
origStdout := os.Stdout
|
|
||||||
t.Cleanup(func() {
|
|
||||||
os.Stdout = origStdout
|
|
||||||
})
|
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
out := filepath.Join(dir, "output.txt")
|
out := filepath.Join(dir, "output.txt")
|
||||||
f, err := os.Create(out)
|
f, err := os.Create(out)
|
||||||
@ -42,7 +40,6 @@ func TestPsTable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
|
|
||||||
os.Stdout = f
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
@ -72,7 +69,7 @@ func TestPsTable(t *testing.T) {
|
|||||||
}).AnyTimes()
|
}).AnyTimes()
|
||||||
|
|
||||||
opts := psOptions{ProjectOptions: &ProjectOptions{ProjectName: "test"}}
|
opts := psOptions{ProjectOptions: &ProjectOptions{ProjectName: "test"}}
|
||||||
err = runPs(ctx, backend, nil, opts)
|
err = runPs(ctx, stream{out: streams.NewOut(f)}, backend, nil, opts)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = f.Seek(0, 0)
|
_, err = f.Seek(0, 0)
|
||||||
@ -83,3 +80,21 @@ func TestPsTable(t *testing.T) {
|
|||||||
|
|
||||||
assert.Contains(t, string(output), "8080/tcp, 8443/tcp")
|
assert.Contains(t, string(output), "8080/tcp, 8443/tcp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type stream struct {
|
||||||
|
out *streams.Out
|
||||||
|
err io.Writer
|
||||||
|
in *streams.In
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stream) Out() *streams.Out {
|
||||||
|
return s.out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stream) Err() io.Writer {
|
||||||
|
return s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stream) In() *streams.In {
|
||||||
|
return s.in
|
||||||
|
}
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
cgo "github.com/compose-spec/compose-go/cli"
|
cgo "github.com/compose-spec/compose-go/cli"
|
||||||
"github.com/compose-spec/compose-go/loader"
|
"github.com/compose-spec/compose-go/loader"
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/docker/cli/cli/command"
|
|
||||||
"github.com/mattn/go-shellwords"
|
"github.com/mattn/go-shellwords"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
@ -108,7 +107,7 @@ func (opts runOptions) apply(project *types.Project) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
|
func runCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := runOptions{
|
opts := runOptions{
|
||||||
composeOptions: &composeOptions{
|
composeOptions: &composeOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
@ -151,7 +150,7 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
|
|||||||
flags.StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
|
flags.StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
|
||||||
flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
|
flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
|
||||||
flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
|
flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
|
||||||
flags.BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
|
flags.BoolVarP(&opts.noTty, "no-TTY", "T", !streams.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
|
||||||
flags.StringVar(&opts.name, "name", "", "Assign a name to the container")
|
flags.StringVar(&opts.name, "name", "", "Assign a name to the container")
|
||||||
flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
|
flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
|
||||||
flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
|
flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
@ -34,7 +33,7 @@ type topOptions struct {
|
|||||||
*ProjectOptions
|
*ProjectOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func topCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func topCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
opts := topOptions{
|
opts := topOptions{
|
||||||
ProjectOptions: p,
|
ProjectOptions: p,
|
||||||
}
|
}
|
||||||
@ -42,14 +41,14 @@ func topCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
Use: "top [SERVICES...]",
|
Use: "top [SERVICES...]",
|
||||||
Short: "Display the running processes",
|
Short: "Display the running processes",
|
||||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||||
return runTop(ctx, backend, opts, args)
|
return runTop(ctx, streams, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
return topCmd
|
return topCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTop(ctx context.Context, backend api.Service, opts topOptions, services []string) error {
|
func runTop(ctx context.Context, streams api.Streams, backend api.Service, opts topOptions, services []string) error {
|
||||||
projectName, err := opts.toProjectName()
|
projectName, err := opts.toProjectName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -64,8 +63,8 @@ func runTop(ctx context.Context, backend api.Service, opts topOptions, services
|
|||||||
})
|
})
|
||||||
|
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
fmt.Printf("%s\n", container.Name)
|
fmt.Fprintf(streams.Out(), "%s\n", container.Name)
|
||||||
err := psPrinter(os.Stdout, func(w io.Writer) {
|
err := psPrinter(streams.Out(), func(w io.Writer) {
|
||||||
for _, proc := range container.Processes {
|
for _, proc := range container.Processes {
|
||||||
info := []interface{}{}
|
info := []interface{}{}
|
||||||
for _, p := range proc {
|
for _, p := range proc {
|
||||||
|
@ -19,7 +19,6 @@ package compose
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -87,7 +86,7 @@ func (opts upOptions) apply(project *types.Project, services []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func upCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
func upCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||||
up := upOptions{}
|
up := upOptions{}
|
||||||
create := createOptions{}
|
create := createOptions{}
|
||||||
upCmd := &cobra.Command{
|
upCmd := &cobra.Command{
|
||||||
@ -102,7 +101,7 @@ func upCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
|||||||
if create.ignoreOrphans && create.removeOrphans {
|
if create.ignoreOrphans && create.removeOrphans {
|
||||||
return fmt.Errorf("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined")
|
return fmt.Errorf("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined")
|
||||||
}
|
}
|
||||||
return runUp(ctx, backend, create, up, project, services)
|
return runUp(ctx, streams, backend, create, up, project, services)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: completeServiceNames(p),
|
ValidArgsFunction: completeServiceNames(p),
|
||||||
}
|
}
|
||||||
@ -158,7 +157,7 @@ func validateFlags(up *upOptions, create *createOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runUp(ctx context.Context, backend api.Service, createOptions createOptions, upOptions upOptions, project *types.Project, services []string) error {
|
func runUp(ctx context.Context, streams api.Streams, backend api.Service, createOptions createOptions, upOptions upOptions, project *types.Project, services []string) error {
|
||||||
if len(project.Services) == 0 {
|
if len(project.Services) == 0 {
|
||||||
return fmt.Errorf("no service selected")
|
return fmt.Errorf("no service selected")
|
||||||
}
|
}
|
||||||
@ -172,7 +171,7 @@ func runUp(ctx context.Context, backend api.Service, createOptions createOptions
|
|||||||
|
|
||||||
var consumer api.LogConsumer
|
var consumer api.LogConsumer
|
||||||
if !upOptions.Detach {
|
if !upOptions.Detach {
|
||||||
consumer = formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp)
|
consumer = formatter.NewLogConsumer(ctx, streams.Out(), streams.Err(), !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
attachTo := services
|
attachTo := services
|
||||||
|
@ -18,10 +18,9 @@ package formatter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var names = []string{
|
var names = []string{
|
||||||
@ -47,20 +46,20 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// SetANSIMode configure formatter for colored output on ANSI-compliant console
|
// SetANSIMode configure formatter for colored output on ANSI-compliant console
|
||||||
func SetANSIMode(ansi string) {
|
func SetANSIMode(streams api.Streams, ansi string) {
|
||||||
if !useAnsi(ansi) {
|
if !useAnsi(streams, ansi) {
|
||||||
nextColor = func() colorFunc {
|
nextColor = func() colorFunc {
|
||||||
return monochrome
|
return monochrome
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func useAnsi(ansi string) bool {
|
func useAnsi(streams api.Streams, ansi string) bool {
|
||||||
switch ansi {
|
switch ansi {
|
||||||
case Always:
|
case Always:
|
||||||
return true
|
return true
|
||||||
case Auto:
|
case Auto:
|
||||||
return isatty.IsTerminal(os.Stdout.Fd())
|
return streams.Out().IsTerminal()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@ -18,7 +18,7 @@ require (
|
|||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/mattn/go-isatty v0.0.16
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/mattn/go-shellwords v1.0.12
|
github.com/mattn/go-shellwords v1.0.12
|
||||||
github.com/moby/buildkit v0.10.4 // replaced; see replace rule for actual version
|
github.com/moby/buildkit v0.10.4 // replaced; see replace rule for actual version
|
||||||
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f
|
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f
|
||||||
|
29
pkg/api/io.go
Normal file
29
pkg/api/io.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/streams"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Streams interface {
|
||||||
|
Out() *streams.Out
|
||||||
|
Err() io.Writer
|
||||||
|
In() *streams.In
|
||||||
|
}
|
@ -48,7 +48,7 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, lis
|
|||||||
names = append(names, getContainerNameWithoutProject(c))
|
names = append(names, getContainerNameWithoutProject(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Attaching to %s\n", strings.Join(names, ", "))
|
fmt.Fprintf(s.stdout(), "Attaching to %s\n", strings.Join(names, ", "))
|
||||||
|
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
err := s.attachContainer(ctx, container, listener)
|
err := s.attachContainer(ctx, container, listener)
|
||||||
|
@ -94,7 +94,6 @@ func (p *printer) Run(cascadeStop bool, exitCodeFrom string, stopFn func() error
|
|||||||
if cascadeStop {
|
if cascadeStop {
|
||||||
if !aborting {
|
if !aborting {
|
||||||
aborting = true
|
aborting = true
|
||||||
fmt.Println("Aborting on container exit...")
|
|
||||||
err := stopFn()
|
err := stopFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -59,7 +59,7 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
|
|||||||
}
|
}
|
||||||
msg := fmt.Sprintf("Going to remove %s", strings.Join(names, ", "))
|
msg := fmt.Sprintf("Going to remove %s", strings.Join(names, ", "))
|
||||||
if options.Force {
|
if options.Force {
|
||||||
fmt.Println(msg)
|
fmt.Fprintln(s.stdout(), msg)
|
||||||
} else {
|
} else {
|
||||||
confirm, err := prompt.User{}.Confirm(msg, false)
|
confirm, err := prompt.User{}.Confirm(msg, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -55,6 +55,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
stopFunc := func() error {
|
stopFunc := func() error {
|
||||||
|
fmt.Fprintln(s.stderr(), "Aborting on container exit...")
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
return progress.Run(ctx, func(ctx context.Context) error {
|
return progress.Run(ctx, func(ctx context.Context) error {
|
||||||
go func() {
|
go func() {
|
||||||
@ -74,7 +75,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
go func() {
|
go func() {
|
||||||
<-signalChan
|
<-signalChan
|
||||||
printer.Cancel()
|
printer.Cancel()
|
||||||
fmt.Println("Gracefully stopping... (press Ctrl+C again to force)")
|
fmt.Fprintln(s.stderr(), "Gracefully stopping... (press Ctrl+C again to force)")
|
||||||
stopFunc() //nolint:errcheck
|
stopFunc() //nolint:errcheck
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user