mirror of https://github.com/docker/compose.git
group ports to render ranges as ... ranges
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
e39ea13002
commit
97a0efd7c3
|
@ -147,14 +147,7 @@ SERVICES:
|
||||||
func writter(containers []api.ContainerSummary) func(w io.Writer) {
|
func writter(containers []api.ContainerSummary) func(w io.Writer) {
|
||||||
return func(w io.Writer) {
|
return func(w io.Writer) {
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
var ports []string
|
ports := DisplayablePorts(container)
|
||||||
for _, p := range container.Publishers {
|
|
||||||
if p.URL == "" {
|
|
||||||
ports = append(ports, fmt.Sprintf("%d/%s", p.TargetPort, p.Protocol))
|
|
||||||
} else {
|
|
||||||
ports = append(ports, fmt.Sprintf("%s->%d/%s", p.URL, p.TargetPort, p.Protocol))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
status := container.State
|
status := container.State
|
||||||
if status == "running" && container.Health != "" {
|
if status == "running" && container.Health != "" {
|
||||||
status = fmt.Sprintf("%s (%s)", container.State, container.Health)
|
status = fmt.Sprintf("%s (%s)", container.State, container.Health)
|
||||||
|
@ -162,7 +155,7 @@ func writter(containers []api.ContainerSummary) func(w io.Writer) {
|
||||||
status = fmt.Sprintf("%s (%d)", container.State, container.ExitCode)
|
status = fmt.Sprintf("%s (%d)", container.State, container.ExitCode)
|
||||||
}
|
}
|
||||||
command := formatter2.Ellipsis(container.Command, 20)
|
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, strings.Join(ports, ", "))
|
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", container.Name, strconv.Quote(command), container.Service, status, ports)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,3 +175,73 @@ func filterByStatus(containers []api.ContainerSummary, status string) []api.Cont
|
||||||
}
|
}
|
||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type portRange struct {
|
||||||
|
pStart int
|
||||||
|
pEnd int
|
||||||
|
tStart int
|
||||||
|
tEnd int
|
||||||
|
IP string
|
||||||
|
protocol string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr portRange) String() string {
|
||||||
|
var (
|
||||||
|
pub string
|
||||||
|
tgt string
|
||||||
|
)
|
||||||
|
|
||||||
|
if pr.pEnd > pr.pStart {
|
||||||
|
pub = fmt.Sprintf("%s:%d-%d->", pr.IP, pr.pStart, pr.pEnd)
|
||||||
|
} else if pr.pStart > 0 {
|
||||||
|
pub = fmt.Sprintf("%s:%d->", pr.IP, pr.pStart)
|
||||||
|
}
|
||||||
|
if pr.tEnd > pr.tStart {
|
||||||
|
tgt = fmt.Sprintf("%d-%d", pr.tStart, pr.tEnd)
|
||||||
|
} else {
|
||||||
|
tgt = fmt.Sprintf("%d", pr.tStart)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s%s/%s", pub, tgt, pr.protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisplayablePorts is copy pasted from https://github.com/docker/cli/pull/581/files
|
||||||
|
func DisplayablePorts(c api.ContainerSummary) string {
|
||||||
|
if c.Publishers == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(c.Publishers)
|
||||||
|
|
||||||
|
pr := portRange{}
|
||||||
|
ports := []string{}
|
||||||
|
for _, p := range c.Publishers {
|
||||||
|
prIsRange := pr.tEnd != pr.tStart
|
||||||
|
tOverlaps := p.TargetPort <= pr.tEnd
|
||||||
|
|
||||||
|
// Start a new port-range if:
|
||||||
|
// - the protocol is different from the current port-range
|
||||||
|
// - published or target port are not consecutive to the current port-range
|
||||||
|
// - the current port-range is a _range_, and the target port overlaps with the current range's target-ports
|
||||||
|
if p.Protocol != pr.protocol || p.URL != pr.IP || p.PublishedPort-pr.pEnd > 1 || p.TargetPort-pr.tEnd > 1 || prIsRange && tOverlaps {
|
||||||
|
// start a new port-range, and print the previous port-range (if any)
|
||||||
|
if pr.pStart > 0 {
|
||||||
|
ports = append(ports, pr.String())
|
||||||
|
}
|
||||||
|
pr = portRange{
|
||||||
|
pStart: p.PublishedPort,
|
||||||
|
pEnd: p.PublishedPort,
|
||||||
|
tStart: p.TargetPort,
|
||||||
|
tEnd: p.TargetPort,
|
||||||
|
protocol: p.Protocol,
|
||||||
|
IP: p.URL,
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pr.pEnd = p.PublishedPort
|
||||||
|
pr.tEnd = p.TargetPort
|
||||||
|
}
|
||||||
|
if pr.tStart > 0 {
|
||||||
|
ports = append(ports, pr.String())
|
||||||
|
}
|
||||||
|
return strings.Join(ports, ", ")
|
||||||
|
}
|
||||||
|
|
|
@ -297,7 +297,36 @@ type ContainerSummary struct {
|
||||||
State string
|
State string
|
||||||
Health string
|
Health string
|
||||||
ExitCode int
|
ExitCode int
|
||||||
Publishers []PortPublisher
|
Publishers PortPublishers
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortPublishers is a slice of PortPublisher
|
||||||
|
type PortPublishers []PortPublisher
|
||||||
|
|
||||||
|
// Len implements sort.Interface
|
||||||
|
func (p PortPublishers) Len() int {
|
||||||
|
return len(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less implements sort.Interface
|
||||||
|
func (p PortPublishers) Less(i, j int) bool {
|
||||||
|
left := p[i]
|
||||||
|
right := p[j]
|
||||||
|
if left.URL != right.URL {
|
||||||
|
return left.URL < right.URL
|
||||||
|
}
|
||||||
|
if left.TargetPort != right.TargetPort {
|
||||||
|
return left.TargetPort < right.TargetPort
|
||||||
|
}
|
||||||
|
if left.PublishedPort != right.PublishedPort {
|
||||||
|
return left.PublishedPort < right.PublishedPort
|
||||||
|
}
|
||||||
|
return left.Protocol < right.Protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap implements sort.Interface
|
||||||
|
func (p PortPublishers) Swap(i, j int) {
|
||||||
|
p[i], p[j] = p[j], p[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerProcSummary holds container processes top data
|
// ContainerProcSummary holds container processes top data
|
||||||
|
|
|
@ -18,7 +18,6 @@ package compose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
@ -46,12 +45,8 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
|
||||||
return container.Ports[i].PrivatePort < container.Ports[j].PrivatePort
|
return container.Ports[i].PrivatePort < container.Ports[j].PrivatePort
|
||||||
})
|
})
|
||||||
for _, p := range container.Ports {
|
for _, p := range container.Ports {
|
||||||
var url string
|
|
||||||
if p.PublicPort != 0 {
|
|
||||||
url = fmt.Sprintf("%s:%d", p.IP, p.PublicPort)
|
|
||||||
}
|
|
||||||
publishers = append(publishers, api.PortPublisher{
|
publishers = append(publishers, api.PortPublisher{
|
||||||
URL: url,
|
URL: p.IP,
|
||||||
TargetPort: int(p.PrivatePort),
|
TargetPort: int(p.PrivatePort),
|
||||||
PublishedPort: int(p.PublicPort),
|
PublishedPort: int(p.PublicPort),
|
||||||
Protocol: p.Type,
|
Protocol: p.Type,
|
||||||
|
|
|
@ -54,7 +54,7 @@ func TestPs(t *testing.T) {
|
||||||
|
|
||||||
expected := []compose.ContainerSummary{
|
expected := []compose.ContainerSummary{
|
||||||
{ID: "123", Name: "123", Project: strings.ToLower(testProject), Service: "service1", State: "running", Health: "healthy", Publishers: nil},
|
{ID: "123", Name: "123", Project: strings.ToLower(testProject), Service: "service1", State: "running", Health: "healthy", Publishers: nil},
|
||||||
{ID: "456", Name: "456", Project: strings.ToLower(testProject), Service: "service1", State: "running", Health: "", Publishers: []compose.PortPublisher{{URL: "localhost:80", TargetPort: 90,
|
{ID: "456", Name: "456", Project: strings.ToLower(testProject), Service: "service1", State: "running", Health: "", Publishers: []compose.PortPublisher{{URL: "localhost", TargetPort: 90,
|
||||||
PublishedPort: 80}}},
|
PublishedPort: 80}}},
|
||||||
{ID: "789", Name: "789", Project: strings.ToLower(testProject), Service: "service2", State: "exited", Health: "", ExitCode: 130, Publishers: nil},
|
{ID: "789", Name: "789", Project: strings.ToLower(testProject), Service: "service2", State: "exited", Health: "", ExitCode: 130, Publishers: nil},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue