More descriptive, easier to process container portmappings information in the API
This commit is contained in:
parent
4a3b039c2a
commit
98018df078
6 changed files with 50 additions and 16 deletions
|
@ -1,5 +1,7 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
type APIHistory struct {
|
type APIHistory struct {
|
||||||
ID string `json:"Id"`
|
ID string `json:"Id"`
|
||||||
Tags []string `json:",omitempty"`
|
Tags []string `json:",omitempty"`
|
||||||
|
@ -47,7 +49,7 @@ type APIContainers struct {
|
||||||
Command string
|
Command string
|
||||||
Created int64
|
Created int64
|
||||||
Status string
|
Status string
|
||||||
Ports string
|
Ports []APIPort
|
||||||
SizeRw int64
|
SizeRw int64
|
||||||
SizeRootFs int64
|
SizeRootFs int64
|
||||||
}
|
}
|
||||||
|
@ -67,7 +69,17 @@ type APIRun struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIPort struct {
|
type APIPort struct {
|
||||||
Port string
|
PrivatePort int64
|
||||||
|
PublicPort int64
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (port *APIPort) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(map[string]interface{}{
|
||||||
|
"PrivatePort": port.PrivatePort,
|
||||||
|
"PublicPort": port.PublicPort,
|
||||||
|
"Type": port.Type,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIVersion struct {
|
type APIVersion struct {
|
||||||
|
|
18
commands.go
18
commands.go
|
@ -20,6 +20,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -996,6 +997,19 @@ func (cli *DockerCli) CmdImages(args ...string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func displayablePorts(ports []APIPort) string {
|
||||||
|
result := []string{}
|
||||||
|
for _, port := range ports {
|
||||||
|
if port.Type == "tcp" {
|
||||||
|
result = append(result, fmt.Sprintf("%d->%d", port.PublicPort, port.PrivatePort))
|
||||||
|
} else {
|
||||||
|
result = append(result, fmt.Sprintf("%d->%d/%s", port.PublicPort, port.PrivatePort, port.Type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(result)
|
||||||
|
return strings.Join(result, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
func (cli *DockerCli) CmdPs(args ...string) error {
|
func (cli *DockerCli) CmdPs(args ...string) error {
|
||||||
cmd := Subcmd("ps", "[OPTIONS]", "List containers")
|
cmd := Subcmd("ps", "[OPTIONS]", "List containers")
|
||||||
quiet := cmd.Bool("q", false, "Only display numeric IDs")
|
quiet := cmd.Bool("q", false, "Only display numeric IDs")
|
||||||
|
@ -1053,9 +1067,9 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
||||||
for _, out := range outs {
|
for _, out := range outs {
|
||||||
if !*quiet {
|
if !*quiet {
|
||||||
if *noTrunc {
|
if *noTrunc {
|
||||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t", out.ID, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports)
|
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t", out.ID, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, displayablePorts(out.Ports))
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t", utils.TruncateID(out.ID), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports)
|
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t", utils.TruncateID(out.ID), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, displayablePorts(out.Ports))
|
||||||
}
|
}
|
||||||
if *size {
|
if *size {
|
||||||
if out.SizeRootFs > 0 {
|
if out.SizeRootFs > 0 {
|
||||||
|
|
|
@ -152,7 +152,6 @@ func TestRunWorkdirExists(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestRunExit(t *testing.T) {
|
func TestRunExit(t *testing.T) {
|
||||||
stdin, stdinPipe := io.Pipe()
|
stdin, stdinPipe := io.Pipe()
|
||||||
stdout, stdoutPipe := io.Pipe()
|
stdout, stdoutPipe := io.Pipe()
|
||||||
|
|
26
container.go
26
container.go
|
@ -15,7 +15,6 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -253,17 +252,28 @@ type NetworkSettings struct {
|
||||||
PortMapping map[string]PortMapping
|
PortMapping map[string]PortMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a human-readable description of the port mapping defined in the settings
|
// returns a more easy to process description of the port mapping defined in the settings
|
||||||
func (settings *NetworkSettings) PortMappingHuman() string {
|
func (settings *NetworkSettings) PortMappingAPI() []APIPort {
|
||||||
var mapping []string
|
var mapping []APIPort
|
||||||
for private, public := range settings.PortMapping["Tcp"] {
|
for private, public := range settings.PortMapping["Tcp"] {
|
||||||
mapping = append(mapping, fmt.Sprintf("%s->%s", public, private))
|
pubint, _ := strconv.ParseInt(public, 0, 0)
|
||||||
|
privint, _ := strconv.ParseInt(private, 0, 0)
|
||||||
|
mapping = append(mapping, APIPort{
|
||||||
|
PrivatePort: privint,
|
||||||
|
PublicPort: pubint,
|
||||||
|
Type: "tcp",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
for private, public := range settings.PortMapping["Udp"] {
|
for private, public := range settings.PortMapping["Udp"] {
|
||||||
mapping = append(mapping, fmt.Sprintf("%s->%s/udp", public, private))
|
pubint, _ := strconv.ParseInt(public, 0, 0)
|
||||||
|
privint, _ := strconv.ParseInt(private, 0, 0)
|
||||||
|
mapping = append(mapping, APIPort{
|
||||||
|
PrivatePort: privint,
|
||||||
|
PublicPort: pubint,
|
||||||
|
Type: "udp",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
sort.Strings(mapping)
|
return mapping
|
||||||
return strings.Join(mapping, ", ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inject the io.Reader at the given path. Note: do not close the reader
|
// Inject the io.Reader at the given path. Note: do not close the reader
|
||||||
|
|
|
@ -386,7 +386,7 @@ func (srv *Server) Containers(all, size bool, n int, since, before string) []API
|
||||||
c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
|
c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
|
||||||
c.Created = container.Created.Unix()
|
c.Created = container.Created.Unix()
|
||||||
c.Status = container.State.String()
|
c.Status = container.State.String()
|
||||||
c.Ports = container.NetworkSettings.PortMappingHuman()
|
c.Ports = container.NetworkSettings.PortMappingAPI()
|
||||||
if size {
|
if size {
|
||||||
c.SizeRw, c.SizeRootFs = container.GetSize()
|
c.SizeRw, c.SizeRootFs = container.GetSize()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,9 @@ func setupWorkingDirectory(workdir string) {
|
||||||
if workdir == "" {
|
if workdir == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
syscall.Chdir(workdir)
|
syscall.Chdir(workdir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Takes care of dropping privileges to the desired user
|
// Takes care of dropping privileges to the desired user
|
||||||
func changeUser(u string) {
|
func changeUser(u string) {
|
||||||
if u == "" {
|
if u == "" {
|
||||||
|
|
Loading…
Reference in a new issue