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) {
|
||||
return func(w io.Writer) {
|
||||
for _, container := range containers {
|
||||
var ports []string
|
||||
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))
|
||||
}
|
||||
}
|
||||
ports := DisplayablePorts(container)
|
||||
status := container.State
|
||||
if status == "running" && 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)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
Health string
|
||||
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
|
||||
|
|
|
@ -18,7 +18,6 @@ package compose
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"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
|
||||
})
|
||||
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{
|
||||
URL: url,
|
||||
URL: p.IP,
|
||||
TargetPort: int(p.PrivatePort),
|
||||
PublishedPort: int(p.PublicPort),
|
||||
Protocol: p.Type,
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestPs(t *testing.T) {
|
|||
|
||||
expected := []compose.ContainerSummary{
|
||||
{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}}},
|
||||
{ID: "789", Name: "789", Project: strings.ToLower(testProject), Service: "service2", State: "exited", Health: "", ExitCode: 130, Publishers: nil},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue