Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit 3d101bb

Browse files
authored
Merge pull request #207 from carmark/ps_format
add format option for hyper volume ls
2 parents 2f3b6a6 + 688d476 commit 3d101bb

File tree

5 files changed

+155
-49
lines changed

5 files changed

+155
-49
lines changed

api/client/cli.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ func (cli *DockerCli) ImagesFormat() string {
8383
return cli.configFile.ImagesFormat
8484
}
8585

86+
// VolumesFormat returns the format string specified in the configuration.
87+
// String contains columns and format specification, for example {{ID}}\t{{Name}}.
88+
func (cli *DockerCli) VolumesFormat() string {
89+
return cli.configFile.VolumesFormat
90+
}
91+
8692
func (cli *DockerCli) setRawTerminal() error {
8793
if cli.isTerminalIn && os.Getenv("NORAW") == "" {
8894
state, err := term.SetRawTerminal(cli.inFd)

api/client/formatter/custom.go

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,37 @@ import (
66
"strings"
77
"time"
88

9+
"github.com/docker/engine-api/types"
10+
"github.com/docker/go-units"
911
"github.com/hyperhq/hypercli/api"
1012
"github.com/hyperhq/hypercli/pkg/stringid"
1113
"github.com/hyperhq/hypercli/pkg/stringutils"
12-
"github.com/docker/engine-api/types"
13-
"github.com/docker/go-units"
1414
)
1515

1616
const (
1717
tableKey = "table"
1818
fipLabel = "sh.hyper.fip"
1919

20-
containerIDHeader = "CONTAINER ID"
21-
imageHeader = "IMAGE"
22-
namesHeader = "NAMES"
23-
commandHeader = "COMMAND"
24-
createdSinceHeader = "CREATED"
25-
createdAtHeader = "CREATED AT"
26-
runningForHeader = "CREATED"
27-
statusHeader = "STATUS"
28-
portsHeader = "PORTS"
29-
sizeHeader = "SIZE"
30-
labelsHeader = "LABELS"
31-
imageIDHeader = "IMAGE ID"
32-
repositoryHeader = "REPOSITORY"
33-
tagHeader = "TAG"
34-
digestHeader = "DIGEST"
35-
fipHeader = "PUBLIC IP"
20+
containerIDHeader = "CONTAINER ID"
21+
imageHeader = "IMAGE"
22+
namesHeader = "NAMES"
23+
commandHeader = "COMMAND"
24+
createdSinceHeader = "CREATED"
25+
createdAtHeader = "CREATED AT"
26+
runningForHeader = "CREATED"
27+
statusHeader = "STATUS"
28+
portsHeader = "PORTS"
29+
sizeHeader = "SIZE"
30+
labelsHeader = "LABELS"
31+
imageIDHeader = "IMAGE ID"
32+
repositoryHeader = "REPOSITORY"
33+
tagHeader = "TAG"
34+
digestHeader = "DIGEST"
35+
fipHeader = "PUBLIC IP"
36+
volumeNameHeader = "NAME"
37+
volumeSizeHeader = "SIZE"
38+
volumeDriverHeader = "DRIVER"
39+
volumeContainerHeader = "CONTAINER"
3640
)
3741

3842
type containerContext struct {
@@ -201,6 +205,33 @@ func (c *imageContext) Size() string {
201205
return units.HumanSize(float64(c.i.Size))
202206
}
203207

208+
type volumeContext struct {
209+
baseSubContext
210+
i types.Volume
211+
}
212+
213+
func (c *volumeContext) Name() string {
214+
c.addHeader(volumeNameHeader)
215+
return c.i.Name
216+
}
217+
218+
func (c *volumeContext) Size() string {
219+
c.addHeader(volumeSizeHeader)
220+
size := c.i.Labels["size"]
221+
return size + " GB"
222+
}
223+
224+
func (c *volumeContext) Driver() string {
225+
c.addHeader(volumeDriverHeader)
226+
return c.i.Driver
227+
}
228+
229+
func (c *volumeContext) Container() string {
230+
c.addHeader(volumeContainerHeader)
231+
container := c.i.Labels["container"]
232+
return container
233+
}
234+
204235
type subContext interface {
205236
fullHeader() string
206237
addHeader(header string)

api/client/formatter/formatter.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"text/tabwriter"
99
"text/template"
1010

11-
"github.com/hyperhq/hypercli/reference"
1211
"github.com/docker/engine-api/types"
12+
"github.com/hyperhq/hypercli/reference"
1313
)
1414

1515
const (
@@ -19,6 +19,7 @@ const (
1919
defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}} ago\t{{.Status}}\t{{.Ports}}\t{{.Names}}\t{{.PublicIP}}"
2020
defaultImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}} ago\t{{.Size}}"
2121
defaultImageTableFormatWithDigest = "table {{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.ID}}\t{{.CreatedSince}} ago\t{{.Size}}"
22+
defaultVolumeTableFormat = "table {{.Driver}}\t{{.Name}}\t{{.Size}}\t{{.Container}}"
2223
defaultQuietFormat = "{{.ID}}"
2324
)
2425

@@ -110,6 +111,12 @@ type ImageContext struct {
110111
Images []types.Image
111112
}
112113

114+
type VolumeContext struct {
115+
Context
116+
// Volumes
117+
Volumes []*types.Volume
118+
}
119+
113120
func (ctx ContainerContext) Write() {
114121
switch ctx.Format {
115122
case tableFormatKey:
@@ -253,3 +260,43 @@ virtual_size: {{.Size}}
253260

254261
ctx.postformat(tmpl, &imageContext{})
255262
}
263+
264+
func (ctx VolumeContext) Write() {
265+
switch ctx.Format {
266+
case tableFormatKey:
267+
ctx.Format = defaultVolumeTableFormat
268+
if ctx.Quiet {
269+
ctx.Format = "{{.Name}}"
270+
}
271+
case rawFormatKey:
272+
if ctx.Quiet {
273+
ctx.Format = `name: {{.Name}}`
274+
} else {
275+
ctx.Format = `name: {{.Name}}
276+
driver: {{.Driver}}
277+
size: {{.Size}}
278+
container: {{.Container}}
279+
`
280+
}
281+
}
282+
283+
ctx.buffer = bytes.NewBufferString("")
284+
ctx.preformat()
285+
286+
tmpl, err := ctx.parseFormat()
287+
if err != nil {
288+
return
289+
}
290+
291+
for _, vol := range ctx.Volumes {
292+
volCtx := &volumeContext{
293+
i: *vol,
294+
}
295+
err = ctx.contextFormat(tmpl, volCtx)
296+
if err != nil {
297+
return
298+
}
299+
}
300+
301+
ctx.postformat(tmpl, &volumeContext{})
302+
}

api/client/volume.go

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@ import (
99
"path/filepath"
1010
"strings"
1111
"sync"
12-
"text/tabwriter"
1312

13+
"github.com/hyperhq/hypercli/api/client/formatter"
1414
Cli "github.com/hyperhq/hypercli/cli"
15+
"github.com/hyperhq/hypercli/opts"
1516
flag "github.com/hyperhq/hypercli/pkg/mflag"
16-
"github.com/hyperhq/hypercli/pkg/stringid"
1717

1818
"github.com/cheggaaa/pb"
1919
"github.com/docker/engine-api/types"
2020
"github.com/docker/engine-api/types/filters"
21-
"github.com/hyperhq/hypercli/opts"
2221
"golang.org/x/net/context"
2322
)
2423

@@ -55,6 +54,7 @@ func (cli *DockerCli) CmdVolumeLs(args ...string) error {
5554
cmd := Cli.Subcmd("volume ls", nil, "List volumes", true)
5655

5756
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display volume names")
57+
format := cmd.String([]string{"-format"}, "", "Pretty-print containers using a Go template")
5858
flFilter := opts.NewListOpts(nil)
5959
cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e. 'dangling=true')")
6060

@@ -75,31 +75,52 @@ func (cli *DockerCli) CmdVolumeLs(args ...string) error {
7575
return err
7676
}
7777

78-
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
79-
if !*quiet {
80-
for _, warn := range volumes.Warnings {
81-
fmt.Fprintln(cli.err, warn)
78+
/*
79+
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
80+
if !*quiet {
81+
for _, warn := range volumes.Warnings {
82+
fmt.Fprintln(cli.err, warn)
83+
}
84+
fmt.Fprintf(w, "DRIVER \tVOLUME NAME\tSIZE\tCONTAINER")
85+
fmt.Fprintf(w, "\n")
8286
}
83-
fmt.Fprintf(w, "DRIVER \tVOLUME NAME\tSIZE\tCONTAINER")
84-
fmt.Fprintf(w, "\n")
85-
}
8687
87-
for _, vol := range volumes.Volumes {
88-
if *quiet {
89-
fmt.Fprintln(w, vol.Name)
90-
continue
91-
}
92-
var size, container string
93-
if vol.Labels != nil {
94-
size = vol.Labels["size"]
95-
container = vol.Labels["container"]
96-
if container != "" {
97-
container = stringid.TruncateID(container)
88+
for _, vol := range volumes.Volumes {
89+
if *quiet {
90+
fmt.Fprintln(w, vol.Name)
91+
continue
9892
}
93+
var size, container string
94+
if vol.Labels != nil {
95+
size = vol.Labels["size"]
96+
container = vol.Labels["container"]
97+
if container != "" {
98+
container = stringid.TruncateID(container)
99+
}
100+
}
101+
fmt.Fprintf(w, "%s\t%s\t%s GB\t%s\n", vol.Driver, vol.Name, size, container)
102+
}
103+
w.Flush()
104+
*/
105+
f := *format
106+
if len(f) == 0 {
107+
if len(cli.VolumesFormat()) > 0 && !*quiet {
108+
f = cli.VolumesFormat()
109+
} else {
110+
f = "table"
99111
}
100-
fmt.Fprintf(w, "%s\t%s\t%s GB\t%s\n", vol.Driver, vol.Name, size, container)
101112
}
102-
w.Flush()
113+
114+
volCtx := formatter.VolumeContext{
115+
Context: formatter.Context{
116+
Output: cli.out,
117+
Format: f,
118+
Quiet: *quiet,
119+
},
120+
Volumes: volumes.Volumes,
121+
}
122+
123+
volCtx.Write()
103124
return nil
104125
}
105126

cliconfig/config.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@ type CloudConfig struct {
5454

5555
// ConfigFile ~/.docker/config.json file info
5656
type ConfigFile struct {
57-
AuthConfigs map[string]types.AuthConfig `json:"auths"`
58-
CloudConfig map[string]CloudConfig `json:"clouds"`
59-
HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"`
60-
PsFormat string `json:"psFormat,omitempty"`
61-
ImagesFormat string `json:"imagesFormat,omitempty"`
62-
DetachKeys string `json:"detachKeys,omitempty"`
63-
filename string // Note: not serialized - for internal use only
57+
AuthConfigs map[string]types.AuthConfig `json:"auths"`
58+
CloudConfig map[string]CloudConfig `json:"clouds"`
59+
HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"`
60+
PsFormat string `json:"psFormat,omitempty"`
61+
ImagesFormat string `json:"imagesFormat,omitempty"`
62+
VolumesFormat string `json:"volumesFormat,omitempty"`
63+
DetachKeys string `json:"detachKeys,omitempty"`
64+
filename string // Note: not serialized - for internal use only
6465
}
6566

6667
// NewConfigFile initializes an empty configuration file for the given filename 'fn'

0 commit comments

Comments
 (0)