Skip to content

Commit

Permalink
Merge branch 'v2' into push-include-deps
Browse files Browse the repository at this point in the history
  • Loading branch information
gferon committed Dec 15, 2022
2 parents 4b1c435 + 8c39b5b commit 660e259
Show file tree
Hide file tree
Showing 37 changed files with 241 additions and 115 deletions.
19 changes: 9 additions & 10 deletions cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,6 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
return nil, compose.WrapComposeError(err)
}

ef := o.EnvFile
if ef != "" && !filepath.IsAbs(ef) {
ef, err = filepath.Abs(ef)
if err != nil {
return nil, err
}
}
for i, s := range project.Services {
s.CustomLabels = map[string]string{
api.ProjectLabel: project.Name,
Expand All @@ -203,8 +196,8 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
api.ConfigFilesLabel: strings.Join(project.ComposeFiles, ","),
api.OneoffLabel: "False", // default, will be overridden by `run` command
}
if ef != "" {
s.CustomLabels[api.EnvironmentFileLabel] = ef
if o.EnvFile != "" {
s.CustomLabels[api.EnvironmentFileLabel] = o.EnvFile
}
project.Services[i] = s
}
Expand Down Expand Up @@ -250,7 +243,7 @@ func RunningAsStandalone() bool {
}

// RootCommand returns the compose command with its child commands
func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //nolint:gocyclo
// 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"
// https://github.com/docker/cli/blob/e1f24d3c93df6752d3c27c8d61d18260f141310c/cli/connhelper/commandconn/commandconn.go#L203-L215
Expand Down Expand Up @@ -326,6 +319,12 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
opts.ProjectDir = opts.WorkDir
fmt.Fprint(os.Stderr, aec.Apply("option '--workdir' is DEPRECATED at root level! Please use '--project-directory' instead.\n", aec.RedF))
}
if opts.EnvFile != "" && !filepath.IsAbs(opts.EnvFile) {
opts.EnvFile, err = filepath.Abs(opts.EnvFile)
if err != nil {
return err
}
}
if parallel > 0 {
backend.MaxConcurrency(parallel)
}
Expand Down
8 changes: 5 additions & 3 deletions cmd/compose/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import (

type imageOptions struct {
*projectOptions
Quiet bool
Quiet bool
Format string
}

func imagesCommand(p *projectOptions, backend api.Service) *cobra.Command {
Expand All @@ -50,6 +51,7 @@ func imagesCommand(p *projectOptions, backend api.Service) *cobra.Command {
}),
ValidArgsFunction: completeServiceNames(p),
}
imgCmd.Flags().StringVar(&opts.Format, "format", "table", "Format the output. Values: [table | json].")
imgCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
return imgCmd
}
Expand Down Expand Up @@ -88,7 +90,7 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
return images[i].ContainerName < images[j].ContainerName
})

return formatter.Print(images, formatter.PRETTY, os.Stdout,
return formatter.Print(images, opts.Format, os.Stdout,
func(w io.Writer) {
for _, img := range images {
id := stringid.TruncateID(img.ID)
Expand All @@ -104,5 +106,5 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", img.ContainerName, repo, tag, id, size)
}
},
"Container", "Repository", "Tag", "Image Id", "Size")
"CONTAINER", "REPOSITORY", "TAG", "IMAGE ID", "SIZE")
}
2 changes: 1 addition & 1 deletion cmd/compose/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func listCommand(backend api.Service) *cobra.Command {
Args: cobra.NoArgs,
ValidArgsFunction: noCompletion(),
}
lsCmd.Flags().StringVar(&lsOpts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
lsCmd.Flags().StringVar(&lsOpts.Format, "format", "table", "Format the output. Values: [table | json].")
lsCmd.Flags().BoolVarP(&lsOpts.Quiet, "quiet", "q", false, "Only display IDs.")
lsCmd.Flags().Var(&lsOpts.Filter, "filter", "Filter output based on conditions provided.")
lsCmd.Flags().BoolVarP(&lsOpts.All, "all", "a", false, "Show all stopped Compose projects")
Expand Down
2 changes: 1 addition & 1 deletion cmd/compose/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func runLogs(ctx context.Context, backend api.Service, opts logsOptions, service
if err != nil {
return err
}
consumer := formatter.NewLogConsumer(ctx, os.Stdout, !opts.noColor, !opts.noPrefix)
consumer := formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !opts.noColor, !opts.noPrefix)
return backend.Logs(ctx, name, consumer, api.LogOptions{
Project: project,
Services: services,
Expand Down
17 changes: 8 additions & 9 deletions cmd/compose/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ import (
"sort"
"strconv"
"strings"
"time"

"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/pkg/utils"
"github.com/docker/docker/api/types"

formatter2 "github.com/docker/cli/cli/command/formatter"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"

Expand Down Expand Up @@ -81,7 +83,7 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
ValidArgsFunction: completeServiceNames(p),
}
flags := psCmd.Flags()
flags.StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json]")
flags.StringVar(&opts.Format, "format", "table", "Format the output. Values: [table | json]")
flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property (supported filters: status).")
flags.StringArrayVar(&opts.Status, "status", []string{}, "Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]")
flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
Expand Down Expand Up @@ -142,21 +144,18 @@ SERVICES:

return formatter.Print(containers, opts.Format, os.Stdout,
writer(containers),
"NAME", "COMMAND", "SERVICE", "STATUS", "PORTS")
"NAME", "IMAGE", "COMMAND", "SERVICE", "CREATED", "STATUS", "PORTS")
}

func writer(containers []api.ContainerSummary) func(w io.Writer) {
return func(w io.Writer) {
for _, container := range containers {
ports := displayablePorts(container)
status := container.State
if status == "running" && container.Health != "" {
status = fmt.Sprintf("%s (%s)", container.State, container.Health)
} else if status == "exited" || status == "dead" {
status = fmt.Sprintf("%s (%d)", container.State, container.ExitCode)
}
createdAt := time.Unix(container.Created, 0)
created := units.HumanDuration(time.Now().UTC().Sub(createdAt)) + " ago"
status := container.Status
command := formatter2.Ellipsis(container.Command, 20)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", container.Name, strconv.Quote(command), container.Service, status, ports)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", container.Name, container.Image, strconv.Quote(command), container.Service, created, status, ports)
}
}
}
Expand Down
13 changes: 7 additions & 6 deletions cmd/compose/ps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ import (
"github.com/stretchr/testify/assert"
)

func TestPsPretty(t *testing.T) {
func TestPsTable(t *testing.T) {
ctx := context.Background()
origStdout := os.Stdout
t.Cleanup(func() {
os.Stdout = origStdout
})
dir := t.TempDir()
f, err := os.Create(filepath.Join(dir, "output.txt"))
out := filepath.Join(dir, "output.txt")
f, err := os.Create(out)
if err != nil {
t.Fatal("could not create output file")
}
Expand All @@ -51,8 +52,9 @@ func TestPsPretty(t *testing.T) {
DoAndReturn(func(ctx context.Context, projectName string, options api.PsOptions) ([]api.ContainerSummary, error) {
return []api.ContainerSummary{
{
ID: "abc123",
Name: "ABC",
ID: "abc123",
Name: "ABC",
Image: "foo/bar",
Publishers: api.PortPublishers{
{
TargetPort: 8080,
Expand All @@ -76,8 +78,7 @@ func TestPsPretty(t *testing.T) {
_, err = f.Seek(0, 0)
assert.NoError(t, err)

output := make([]byte, 256)
_, err = f.Read(output)
output, err := os.ReadFile(out)
assert.NoError(t, err)

assert.Contains(t, string(output), "8080/tcp, 8443/tcp")
Expand Down
2 changes: 1 addition & 1 deletion cmd/compose/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func runUp(ctx context.Context, backend api.Service, createOptions createOptions

var consumer api.LogConsumer
if !upOptions.Detach {
consumer = formatter.NewLogConsumer(ctx, os.Stdout, !upOptions.noColor, !upOptions.noPrefix)
consumer = formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !upOptions.noColor, !upOptions.noPrefix)
}

attachTo := services
Expand Down
5 changes: 4 additions & 1 deletion cmd/formatter/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
package formatter

const (
// JSON is the constant for Json formats on list commands
// JSON Print in JSON format
JSON = "json"
// TemplateLegacyJSON the legacy json formatting value using go template
TemplateLegacyJSON = "{{json.}}"
// PRETTY is the constant for default formats on list commands
// Deprecated: use TABLE
PRETTY = "pretty"
// TABLE Print output in table format with column headers (default)
TABLE = "table"
)
2 changes: 1 addition & 1 deletion cmd/formatter/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
// Print prints formatted lists in different formats
func Print(toJSON interface{}, format string, outWriter io.Writer, writerFn func(w io.Writer), headers ...string) error {
switch strings.ToLower(format) {
case PRETTY, "":
case TABLE, PRETTY, "":
return PrintPrettySection(outWriter, writerFn, headers...)
case TemplateLegacyJSON:
switch reflect.TypeOf(toJSON).Kind() {
Expand Down
23 changes: 17 additions & 6 deletions cmd/formatter/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,20 @@ type logConsumer struct {
ctx context.Context
presenters sync.Map // map[string]*presenter
width int
writer io.Writer
stdout io.Writer
stderr io.Writer
color bool
prefix bool
}

// NewLogConsumer creates a new LogConsumer
func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) api.LogConsumer {
func NewLogConsumer(ctx context.Context, stdout, stderr io.Writer, color bool, prefix bool) api.LogConsumer {
return &logConsumer{
ctx: ctx,
presenters: sync.Map{},
width: 0,
writer: w,
stdout: stdout,
stderr: stderr,
color: color,
prefix: prefix,
}
Expand Down Expand Up @@ -83,20 +85,29 @@ func (l *logConsumer) getPresenter(container string) *presenter {
}

// Log formats a log message as received from name/container
func (l *logConsumer) Log(container, service, message string) {
func (l *logConsumer) Log(container, message string) {
l.write(l.stdout, container, message)
}

// Log formats a log message as received from name/container
func (l *logConsumer) Err(container, message string) {
l.write(l.stderr, container, message)
}

func (l *logConsumer) write(w io.Writer, container, message string) {
if l.ctx.Err() != nil {
return
}
p := l.getPresenter(container)
for _, line := range strings.Split(message, "\n") {
fmt.Fprintf(l.writer, "%s%s\n", p.prefix, line)
fmt.Fprintf(w, "%s%s\n", p.prefix, line)
}
}

func (l *logConsumer) Status(container, msg string) {
p := l.getPresenter(container)
s := p.colors(fmt.Sprintf("%s %s\n", container, msg))
l.writer.Write([]byte(s)) //nolint:errcheck
l.stdout.Write([]byte(s)) //nolint:errcheck
}

func (l *logConsumer) computeWidth() {
Expand Down
1 change: 1 addition & 0 deletions docs/reference/compose_images.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ List images used by the created containers

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `--format` | `string` | `table` | Format the output. Values: [table \| json]. |
| `-q`, `--quiet` | | | Only display IDs |


Expand Down
2 changes: 1 addition & 1 deletion docs/reference/compose_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ List running compose projects
| --- | --- | --- | --- |
| `-a`, `--all` | | | Show all stopped Compose projects |
| `--filter` | `filter` | | Filter output based on conditions provided. |
| `--format` | `string` | `pretty` | Format the output. Values: [pretty \| json]. |
| `--format` | `string` | `table` | Format the output. Values: [table \| json]. |
| `-q`, `--quiet` | | | Only display IDs. |


Expand Down
2 changes: 1 addition & 1 deletion docs/reference/compose_ps.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ List containers
| --- | --- | --- | --- |
| `-a`, `--all` | | | Show all stopped containers (including those created by the run command) |
| [`--filter`](#filter) | `string` | | Filter services by a property (supported filters: status). |
| [`--format`](#format) | `string` | `pretty` | Format the output. Values: [pretty \| json] |
| [`--format`](#format) | `string` | `table` | Format the output. Values: [table \| json] |
| `-q`, `--quiet` | | | Only display IDs |
| `--services` | | | Display services |
| [`--status`](#status) | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |
Expand Down
10 changes: 10 additions & 0 deletions docs/reference/docker_compose_images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ usage: docker compose images [OPTIONS] [SERVICE...]
pname: docker compose
plink: docker_compose.yaml
options:
- option: format
value_type: string
default_value: table
description: 'Format the output. Values: [table | json].'
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet
shorthand: q
value_type: bool
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/docker_compose_ls.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ options:
swarm: false
- option: format
value_type: string
default_value: pretty
description: 'Format the output. Values: [pretty | json].'
default_value: table
description: 'Format the output. Values: [table | json].'
deprecated: false
hidden: false
experimental: false
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/docker_compose_ps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ options:
swarm: false
- option: format
value_type: string
default_value: pretty
description: 'Format the output. Values: [pretty | json]'
default_value: table
description: 'Format the output. Values: [table | json]'
details_url: '#format'
deprecated: false
hidden: false
Expand Down
10 changes: 8 additions & 2 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,13 @@ type PortPublisher struct {
type ContainerSummary struct {
ID string
Name string
Image any
Command string
Project string
Service string
Created int64
State string
Status string
Health string
ExitCode int
Publishers PortPublishers
Expand Down Expand Up @@ -437,7 +440,8 @@ type Stack struct {

// LogConsumer is a callback to process log messages from services
type LogConsumer interface {
Log(containerName, service, message string)
Log(containerName, message string)
Err(containerName, message string)
Status(container, msg string)
Register(container string)
}
Expand All @@ -461,8 +465,10 @@ type ContainerEvent struct {
}

const (
// ContainerEventLog is a ContainerEvent of type log. Line is set
// ContainerEventLog is a ContainerEvent of type log on stdout. Line is set
ContainerEventLog = iota
// ContainerEventErr is a ContainerEvent of type log on stderr. Line is set
ContainerEventErr
// ContainerEventAttach is a ContainerEvent of type attach. First event sent about a container
ContainerEventAttach
// ContainerEventStopped is a ContainerEvent of type stopped.
Expand Down

0 comments on commit 660e259

Please sign in to comment.