mirror of https://github.com/docker/compose.git
111 lines
2.3 KiB
Go
111 lines
2.3 KiB
Go
package formatter
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/api/containers"
|
|
)
|
|
|
|
type portGroup struct {
|
|
first uint32
|
|
last uint32
|
|
}
|
|
|
|
// PortsString returns a human readable published ports
|
|
func PortsString(ports []containers.Port) string {
|
|
groupMap := make(map[string]*portGroup)
|
|
var (
|
|
result []string
|
|
hostMappings []string
|
|
groupMapKeys []string
|
|
)
|
|
|
|
sort.Slice(ports, func(i int, j int) bool {
|
|
return comparePorts(ports[i], ports[j])
|
|
})
|
|
|
|
for _, port := range ports {
|
|
// Simple case: HOST_IP:PORT1:PORT2
|
|
hostIP := "0.0.0.0"
|
|
if port.HostIP != "" {
|
|
hostIP = port.HostIP
|
|
}
|
|
|
|
if port.HostPort != port.ContainerPort {
|
|
hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", hostIP, port.HostPort, port.ContainerPort, port.Protocol))
|
|
continue
|
|
}
|
|
|
|
current := port.ContainerPort
|
|
portKey := fmt.Sprintf("%s/%s", hostIP, port.Protocol)
|
|
group := groupMap[portKey]
|
|
|
|
if group == nil {
|
|
groupMap[portKey] = &portGroup{first: current, last: current}
|
|
// record order that groupMap keys are created
|
|
groupMapKeys = append(groupMapKeys, portKey)
|
|
continue
|
|
}
|
|
|
|
if current == (group.last + 1) {
|
|
group.last = current
|
|
continue
|
|
}
|
|
|
|
result = append(result, formGroup(portKey, group.first, group.last))
|
|
groupMap[portKey] = &portGroup{first: current, last: current}
|
|
}
|
|
|
|
for _, portKey := range groupMapKeys {
|
|
g := groupMap[portKey]
|
|
result = append(result, formGroup(portKey, g.first, g.last))
|
|
}
|
|
|
|
result = append(result, hostMappings...)
|
|
|
|
return strings.Join(result, ", ")
|
|
}
|
|
|
|
func formGroup(key string, start uint32, last uint32) string {
|
|
parts := strings.Split(key, "/")
|
|
protocol := parts[0]
|
|
var ip string
|
|
if len(parts) > 1 {
|
|
ip = parts[0]
|
|
protocol = parts[1]
|
|
}
|
|
group := strconv.Itoa(int(start))
|
|
|
|
// add range
|
|
if start != last {
|
|
group = fmt.Sprintf("%s-%d", group, last)
|
|
}
|
|
|
|
// add host ip
|
|
if ip != "" {
|
|
group = fmt.Sprintf("%s:%s->%s", ip, group, group)
|
|
}
|
|
|
|
// add protocol
|
|
return fmt.Sprintf("%s/%s", group, protocol)
|
|
}
|
|
|
|
func comparePorts(i containers.Port, j containers.Port) bool {
|
|
if i.ContainerPort != j.ContainerPort {
|
|
return i.ContainerPort < j.ContainerPort
|
|
}
|
|
|
|
if i.HostIP != j.HostIP {
|
|
return i.HostIP < j.HostIP
|
|
}
|
|
|
|
if i.HostPort != j.HostPort {
|
|
return i.HostPort < j.HostPort
|
|
}
|
|
|
|
return i.Protocol < j.Protocol
|
|
}
|