mirror of https://github.com/docker/compose.git
Implement quiet flag for ps command
This commit is contained in:
parent
28299c099d
commit
688e7e5deb
6
Makefile
6
Makefile
|
@ -53,7 +53,7 @@ test: ## Run unit tests
|
|||
@docker build . \
|
||||
--target test
|
||||
|
||||
cache-clear: # Clear the builder cache
|
||||
cache-clear: ## Clear the builder cache
|
||||
@docker builder prune --force --filter type=exec.cachemount --filter=unused-for=24h
|
||||
|
||||
lint: ## run linter(s)
|
||||
|
@ -62,8 +62,8 @@ lint: ## run linter(s)
|
|||
|
||||
help: ## Show help
|
||||
@echo Please specify a build target. The choices are:
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all protos cli cross test cache-clear lint help
|
||||
.PHONY: all protos cli e2e-local cross test cache-clear lint help
|
||||
|
|
11
README.md
11
README.md
|
@ -23,3 +23,14 @@ $ make
|
|||
```
|
||||
|
||||
If you make changes to the `.proto` files, make sure to `make protos` to generate go code.
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
To run unit tests:
|
||||
|
||||
```
|
||||
make test
|
||||
```
|
||||
|
||||
If you need to update a golden file simply do `go test ./... -test.update-golden`.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
@ -11,29 +12,50 @@ import (
|
|||
"github.com/docker/api/client"
|
||||
)
|
||||
|
||||
// PsCommand lists containers
|
||||
var PsCommand = cobra.Command{
|
||||
Use: "ps",
|
||||
Short: "List containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot connect to backend")
|
||||
}
|
||||
|
||||
containers, err := c.ContainerService().List(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch containers")
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintf(w, "NAME\tIMAGE\tSTATUS\tCOMMAND\n")
|
||||
format := "%s\t%s\t%s\t%s\n"
|
||||
for _, c := range containers {
|
||||
fmt.Fprintf(w, format, c.ID, c.Image, c.Status, c.Command)
|
||||
}
|
||||
return w.Flush()
|
||||
},
|
||||
type psOpts struct {
|
||||
quiet bool
|
||||
}
|
||||
|
||||
// PsCommand lists containers
|
||||
func PsCommand() *cobra.Command {
|
||||
var opts psOpts
|
||||
cmd := &cobra.Command{
|
||||
Use: "ps",
|
||||
Short: "List containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runPs(cmd.Context(), opts)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPs(ctx context.Context, opts psOpts) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot connect to backend")
|
||||
}
|
||||
|
||||
containers, err := c.ContainerService().List(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch containers")
|
||||
}
|
||||
|
||||
if opts.quiet {
|
||||
for _, c := range containers {
|
||||
fmt.Println(c.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintf(w, "NAME\tIMAGE\tSTATUS\tCOMMAND\n")
|
||||
format := "%s\t%s\t%s\t%s\n"
|
||||
for _, c := range containers {
|
||||
fmt.Fprintf(w, format, c.ID, c.Image, c.Status, c.Command)
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
apicontext "github.com/docker/api/context"
|
||||
"github.com/docker/api/context/store"
|
||||
_ "github.com/docker/api/example"
|
||||
)
|
||||
|
||||
type PsSuite struct {
|
||||
suite.Suite
|
||||
ctx context.Context
|
||||
writer *os.File
|
||||
reader *os.File
|
||||
originalStdout *os.File
|
||||
storeRoot string
|
||||
}
|
||||
|
||||
func (sut *PsSuite) BeforeTest(suiteName, testName string) {
|
||||
ctx := context.Background()
|
||||
ctx = apicontext.WithCurrentContext(ctx, "example")
|
||||
dir, err := ioutil.TempDir("", "store")
|
||||
require.Nil(sut.T(), err)
|
||||
s, err := store.New(
|
||||
store.WithRoot(dir),
|
||||
)
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
err = s.Create("example", store.TypedContext{
|
||||
Type: "example",
|
||||
})
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
sut.storeRoot = dir
|
||||
|
||||
ctx = store.WithContextStore(ctx, s)
|
||||
sut.ctx = ctx
|
||||
|
||||
sut.originalStdout = os.Stdout
|
||||
r, w, err := os.Pipe()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
os.Stdout = w
|
||||
sut.writer = w
|
||||
sut.reader = r
|
||||
}
|
||||
|
||||
func (sut *PsSuite) getStdOut() string {
|
||||
err := sut.writer.Close()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
out, _ := ioutil.ReadAll(sut.reader)
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func (sut *PsSuite) AfterTest(suiteName, testName string) {
|
||||
os.Stdout = sut.originalStdout
|
||||
err := os.RemoveAll(sut.storeRoot)
|
||||
require.Nil(sut.T(), err)
|
||||
}
|
||||
|
||||
func (sut *PsSuite) TestPs() {
|
||||
opts := psOpts{
|
||||
quiet: false,
|
||||
}
|
||||
|
||||
err := runPs(sut.ctx, opts)
|
||||
assert.NilError(sut.T(), err)
|
||||
|
||||
golden.Assert(sut.T(), sut.getStdOut(), "ps-out.golden")
|
||||
}
|
||||
|
||||
func (sut *PsSuite) TestPsQuiet() {
|
||||
opts := psOpts{
|
||||
quiet: true,
|
||||
}
|
||||
|
||||
err := runPs(sut.ctx, opts)
|
||||
assert.NilError(sut.T(), err)
|
||||
|
||||
golden.Assert(sut.T(), sut.getStdOut(), "ps-out-quiet.golden")
|
||||
}
|
||||
|
||||
func TestPs(t *testing.T) {
|
||||
suite.Run(t, new(PsSuite))
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
id
|
||||
1234
|
|
@ -0,0 +1,3 @@
|
|||
NAME IMAGE STATUS COMMAND
|
||||
id nginx
|
||||
1234 alpine
|
|
@ -96,7 +96,7 @@ func main() {
|
|||
|
||||
root.AddCommand(
|
||||
cmd.ContextCommand(),
|
||||
&cmd.PsCommand,
|
||||
cmd.PsCommand(),
|
||||
cmd.ServeCommand(),
|
||||
run.Command(),
|
||||
cmd.ExecCommand(),
|
||||
|
|
1
go.mod
1
go.mod
|
@ -31,4 +31,5 @@ require (
|
|||
golang.org/x/text v0.3.2 // indirect
|
||||
google.golang.org/grpc v1.29.1
|
||||
google.golang.org/protobuf v1.21.0
|
||||
gotest.tools/v3 v3.0.2
|
||||
)
|
||||
|
|
|
@ -7,8 +7,9 @@ import (
|
|||
|
||||
"github.com/robpike/filter"
|
||||
|
||||
f "github.com/docker/api/tests/framework"
|
||||
g "github.com/onsi/gomega"
|
||||
|
||||
f "github.com/docker/api/tests/framework"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -69,6 +70,14 @@ func main() {
|
|||
g.Expect(lines[2]).To(g.ContainSubstring("1234 alpine"))
|
||||
})
|
||||
|
||||
It("can run quiet ps command", func() {
|
||||
output := f.NewDockerCommand("ps", "-q").ExecOrDie()
|
||||
lines := lines(output)
|
||||
g.Expect(len(lines)).To(g.Equal(2))
|
||||
g.Expect(lines[0]).To(g.Equal("id"))
|
||||
g.Expect(lines[1]).To(g.Equal("1234"))
|
||||
})
|
||||
|
||||
It("can run 'run' command", func() {
|
||||
output := f.NewDockerCommand("run", "nginx", "-p", "80:80").ExecOrDie()
|
||||
g.Expect(output).To(g.ContainSubstring("Running container \"nginx\" with name"))
|
||||
|
|
Loading…
Reference in New Issue