Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
Add json output format to several commands
Browse files Browse the repository at this point in the history
- docker context ls
- docker ps
- docker compose ls
- docker compose ps
- docker secret ls
- docker volume ls
- docker version

Signed-off-by: Ulysses Souza <[email protected]>
  • Loading branch information
ulyssessouza committed Oct 1, 2020
1 parent abd6af6 commit 8961805
Show file tree
Hide file tree
Showing 23 changed files with 664 additions and 117 deletions.
1 change: 1 addition & 0 deletions cli/cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type composeOptions struct {
WorkingDir string
ConfigPaths []string
Environment []string
Format string
}

func (o *composeOptions) toProjectName() (string, error) {
Expand Down
37 changes: 32 additions & 5 deletions cli/cmd/compose/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ import (
"fmt"
"io"
"os"
"strings"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/docker/compose-cli/api/client"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/errdefs"
"github.com/docker/compose-cli/formatter"
)

func listCommand() *cobra.Command {
Expand All @@ -35,10 +41,15 @@ func listCommand() *cobra.Command {
return runList(cmd.Context(), opts)
},
}
lsCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name")
addComposeCommonFlags(lsCmd.Flags(), &opts)
return lsCmd
}

func addComposeCommonFlags(f *pflag.FlagSet, opts *composeOptions) {
f.StringVarP(&opts.Name, "project-name", "p", "", "Project name")
f.StringVar(&opts.Format, "format", "", "Format the output. Values: [pretty | json]. (Default: pretty)")
}

func runList(ctx context.Context, opts composeOptions) error {
c, err := client.New(ctx)
if err != nil {
Expand All @@ -49,10 +60,26 @@ func runList(ctx context.Context, opts composeOptions) error {
return err
}

err = printSection(os.Stdout, func(w io.Writer) {
for _, stack := range stackList {
fmt.Fprintf(w, "%s\t%s\n", stack.Name, stack.Status)
return printListFormatted(opts.Format, os.Stdout, stackList)
}

func printListFormatted(format string, out io.Writer, stackList []compose.Stack) error {
var err error
switch strings.ToLower(format) {
case formatter.PRETTY, "":
err = formatter.PrintPrettySection(out, func(w io.Writer) {
for _, stack := range stackList {
fmt.Fprintf(w, "%s\t%s\n", stack.Name, stack.Status)
}
}, "NAME", "STATUS")
case formatter.JSON:
outJSON, err := formatter.ToStandardJSON(stackList)
if err != nil {
return err
}
}, "NAME", "STATUS")
_, _ = fmt.Fprint(out, outJSON)
default:
err = errors.Wrapf(errdefs.ErrParsingFailed, "format value %q could not be parsed", format)
}
return err
}
45 changes: 45 additions & 0 deletions cli/cmd/compose/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
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 compose

import (
"bytes"
"testing"

"gotest.tools/assert"
"gotest.tools/golden"

"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/formatter"
)

func TestPrintComposeList(t *testing.T) {
secretList := []compose.Stack{
{
ID: "123",
Name: "myName123",
Status: "Running",
},
}
out := &bytes.Buffer{}
assert.NilError(t, printListFormatted(formatter.PRETTY, out, secretList))
golden.Assert(t, out.String(), "compose-list-out.golden")

out.Reset()
assert.NilError(t, printListFormatted(formatter.JSON, out, secretList))
golden.Assert(t, out.String(), "compose-list-out-json.golden")
}
39 changes: 25 additions & 14 deletions cli/cmd/compose/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ import (
"io"
"os"
"strings"
"text/tabwriter"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/docker/compose-cli/api/client"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/errdefs"
"github.com/docker/compose-cli/formatter"
)

func psCommand() *cobra.Command {
Expand All @@ -37,10 +40,9 @@ func psCommand() *cobra.Command {
return runPs(cmd.Context(), opts)
},
}
psCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name")
psCmd.Flags().StringVar(&opts.WorkingDir, "workdir", "", "Work dir")
psCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files")

addComposeCommonFlags(psCmd.Flags(), &opts)
return psCmd
}

Expand All @@ -59,17 +61,26 @@ func runPs(ctx context.Context, opts composeOptions) error {
return err
}

err = printSection(os.Stdout, func(w io.Writer) {
for _, service := range serviceList {
fmt.Fprintf(w, "%s\t%s\t%d/%d\t%s\n", service.ID, service.Name, service.Replicas, service.Desired, strings.Join(service.Ports, ", "))
}
}, "ID", "NAME", "REPLICAS", "PORTS")
return err
return printPsFormatted(opts.Format, os.Stdout, serviceList)
}

func printSection(out io.Writer, printer func(io.Writer), headers ...string) error {
w := tabwriter.NewWriter(out, 20, 1, 3, ' ', 0)
fmt.Fprintln(w, strings.Join(headers, "\t"))
printer(w)
return w.Flush()
func printPsFormatted(format string, out io.Writer, serviceList []compose.ServiceStatus) error {
var err error
switch strings.ToLower(format) {
case formatter.PRETTY, "":
err = formatter.PrintPrettySection(out, func(w io.Writer) {
for _, service := range serviceList {
fmt.Fprintf(w, "%s\t%s\t%d/%d\t%s\n", service.ID, service.Name, service.Replicas, service.Desired, strings.Join(service.Ports, ", "))
}
}, "ID", "NAME", "REPLICAS", "PORTS")
case formatter.JSON:
outJSON, err := formatter.ToStandardJSON(serviceList)
if err != nil {
return err
}
_, _ = fmt.Fprint(out, outJSON)
default:
err = errors.Wrapf(errdefs.ErrParsingFailed, "format value %q could not be parsed", format)
}
return err
}
7 changes: 7 additions & 0 deletions cli/cmd/compose/testdata/compose-list-out-json.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"ID": "123",
"Name": "myName123",
"Status": "Running"
}
]
2 changes: 2 additions & 0 deletions cli/cmd/compose/testdata/compose-list-out.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NAME STATUS
myName123 Running
64 changes: 36 additions & 28 deletions cli/cmd/context/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@
package context

import (
"errors"
"fmt"
"io"
"os"
"sort"
"strings"
"text/tabwriter"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/docker/compose-cli/cli/mobycli"
apicontext "github.com/docker/compose-cli/context"
"github.com/docker/compose-cli/context/store"
"github.com/docker/compose-cli/errdefs"
"github.com/docker/compose-cli/formatter"
)

Expand Down Expand Up @@ -58,7 +59,8 @@ func listCommand() *cobra.Command {
}
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Only show context names")
cmd.Flags().BoolVar(&opts.json, "json", false, "Format output as JSON")
cmd.Flags().StringVar(&opts.format, "format", "", "Format output as JSON")
cmd.Flags().StringVar(&opts.format, "format", "", "Format the output. Values: [pretty | json | go template]. (Default: pretty)")
_ = cmd.Flags().MarkHidden("json")

return cmd
}
Expand All @@ -68,7 +70,7 @@ func runList(cmd *cobra.Command, opts lsOpts) error {
if err != nil {
return err
}
if opts.format != "" {
if opts.format != "" && opts.format != formatter.JSON && opts.format != formatter.PRETTY {
mobycli.Exec(cmd.Root())
return nil
}
Expand All @@ -93,35 +95,41 @@ func runList(cmd *cobra.Command, opts lsOpts) error {
}

if opts.json {
j, err := formatter.ToStandardJSON(contexts)
if err != nil {
return err
}
fmt.Println(j)
return nil
opts.format = formatter.JSON
}

w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
fmt.Fprintln(w, "NAME\tTYPE\tDESCRIPTION\tDOCKER ENDPOINT\tKUBERNETES ENDPOINT\tORCHESTRATOR")
format := "%s\t%s\t%s\t%s\t%s\t%s\n"
return printContextLsFormatted(opts.format, currentContext, os.Stdout, contexts)
}

for _, c := range contexts {
contextName := c.Name
if c.Name == currentContext {
contextName += " *"
func printContextLsFormatted(format string, currContext string, out io.Writer, contexts []*store.DockerContext) error {
var err error
switch strings.ToLower(format) {
case formatter.PRETTY, "":
err = formatter.PrintPrettySection(out, func(w io.Writer) {
for _, c := range contexts {
contextName := c.Name
if c.Name == currContext {
contextName += " *"
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
contextName,
c.Type(),
c.Metadata.Description,
getEndpoint("docker", c.Endpoints),
getEndpoint("kubernetes", c.Endpoints),
c.Metadata.StackOrchestrator)
}
}, "NAME", "TYPE", "DESCRIPTION", "DOCKER ENDPOINT", "KUBERNETES ENDPOINT", "ORCHESTRATOR")
case formatter.JSON:
out, err := formatter.ToStandardJSON(contexts)
if err != nil {
return err
}

fmt.Fprintf(w,
format,
contextName,
c.Type(),
c.Metadata.Description,
getEndpoint("docker", c.Endpoints),
getEndpoint("kubernetes", c.Endpoints),
c.Metadata.StackOrchestrator)
fmt.Println(out)
default:
err = errors.Wrapf(errdefs.ErrParsingFailed, "format value %q could not be parsed", format)
}

return w.Flush()
return err
}

func getEndpoint(name string, meta map[string]interface{}) string {
Expand Down
Loading

0 comments on commit 8961805

Please sign in to comment.