mirror of
https://github.com/yusing/godoxy.git
synced 2025-06-09 13:02:33 +02:00
port selection strategy fix
This commit is contained in:
parent
1fd7b50010
commit
206412d0ca
2 changed files with 48 additions and 33 deletions
BIN
bin/go-proxy
BIN
bin/go-proxy
Binary file not shown.
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/connhelper"
|
"github.com/docker/cli/cli/connhelper"
|
||||||
|
@ -15,6 +14,19 @@ import (
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (p *Provider) setConfigField(c *ProxyConfig, label string, value string, prefix string) error {
|
||||||
|
if strings.HasPrefix(label, prefix) {
|
||||||
|
field := strings.TrimPrefix(label, prefix)
|
||||||
|
field = utils.snakeToCamel(field)
|
||||||
|
prop := reflect.ValueOf(c).Elem().FieldByName(field)
|
||||||
|
if prop.Kind() == 0 {
|
||||||
|
return fmt.Errorf("ignoring unknown field %s", field)
|
||||||
|
}
|
||||||
|
prop.Set(reflect.ValueOf(value))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP string) []*ProxyConfig {
|
func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP string) []*ProxyConfig {
|
||||||
var aliases []string
|
var aliases []string
|
||||||
|
|
||||||
|
@ -22,50 +34,32 @@ func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP
|
||||||
|
|
||||||
container_name := strings.TrimPrefix(container.Names[0], "/")
|
container_name := strings.TrimPrefix(container.Names[0], "/")
|
||||||
aliases_label, ok := container.Labels["proxy.aliases"]
|
aliases_label, ok := container.Labels["proxy.aliases"]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
aliases = []string{container_name}
|
aliases = []string{container_name}
|
||||||
} else {
|
} else {
|
||||||
aliases = strings.Split(aliases_label, ",")
|
aliases = strings.Split(aliases_label, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isRemote := clientIP != ""
|
||||||
|
|
||||||
for _, alias := range aliases {
|
for _, alias := range aliases {
|
||||||
config := NewProxyConfig(p)
|
config := NewProxyConfig(p)
|
||||||
prefix := fmt.Sprintf("proxy.%s.", alias)
|
prefix := fmt.Sprintf("proxy.%s.", alias)
|
||||||
for label, value := range container.Labels {
|
for label, value := range container.Labels {
|
||||||
if strings.HasPrefix(label, prefix) {
|
err := p.setConfigField(&config, label, value, prefix)
|
||||||
field := strings.TrimPrefix(label, prefix)
|
if err != nil {
|
||||||
field = utils.snakeToCamel(field)
|
p.Errorf("Build", "%v", err)
|
||||||
prop := reflect.ValueOf(&config).Elem().FieldByName(field)
|
}
|
||||||
if prop.Kind() == 0 {
|
err = p.setConfigField(&config, label, value, wildcardPrefix)
|
||||||
p.Logf("Build", "ignoring unknown field %s", alias, field)
|
if err != nil {
|
||||||
continue
|
p.Errorf("Build", "%v", err)
|
||||||
}
|
|
||||||
prop.Set(reflect.ValueOf(value))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if config.Port == "" && clientIP != "" {
|
if config.Port == "" {
|
||||||
for _, port := range container.Ports {
|
config.Port = fmt.Sprintf("%d", selectPort(container))
|
||||||
config.Port = fmt.Sprintf("%d", port.PublicPort)
|
|
||||||
if config.Port != "0" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if config.Port == "" {
|
|
||||||
// usually the smaller port is the http one
|
|
||||||
// so make it the last one to be set (if 80 or 8080 are not exposed)
|
|
||||||
sort.Slice(container.Ports, func(i, j int) bool {
|
|
||||||
return container.Ports[i].PrivatePort > container.Ports[j].PrivatePort
|
|
||||||
})
|
|
||||||
for _, port := range container.Ports {
|
|
||||||
// set first, but keep trying
|
|
||||||
config.Port = fmt.Sprintf("%d", port.PrivatePort)
|
|
||||||
// until we find 80 or 8080
|
|
||||||
if port.PrivatePort == 80 || port.PrivatePort == 8080 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if config.Port == "" || config.Port == "0" {
|
if config.Port == "0" {
|
||||||
// no ports exposed or specified
|
// no ports exposed or specified
|
||||||
p.Logf("Build", "no ports exposed for %s, ignored", container_name)
|
p.Logf("Build", "no ports exposed for %s, ignored", container_name)
|
||||||
continue
|
continue
|
||||||
|
@ -94,7 +88,7 @@ func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP
|
||||||
}
|
}
|
||||||
if config.Host == "" {
|
if config.Host == "" {
|
||||||
switch {
|
switch {
|
||||||
case clientIP != "":
|
case isRemote:
|
||||||
config.Host = clientIP
|
config.Host = clientIP
|
||||||
case container.HostConfig.NetworkMode == "host":
|
case container.HostConfig.NetworkMode == "host":
|
||||||
config.Host = "host.docker.internal"
|
config.Host = "host.docker.internal"
|
||||||
|
@ -209,3 +203,24 @@ func (p *Provider) grWatchDockerChanges() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// var dockerUrlRegex = regexp.MustCompile(`^(?P<scheme>\w+)://(?P<host>[^:]+)(?P<port>:\d+)?(?P<path>/.*)?$`)
|
// var dockerUrlRegex = regexp.MustCompile(`^(?P<scheme>\w+)://(?P<host>[^:]+)(?P<port>:\d+)?(?P<path>/.*)?$`)
|
||||||
|
|
||||||
|
func getPublicPort(p types.Port) uint16 { return p.PublicPort }
|
||||||
|
func getPrivatePort(p types.Port) uint16 { return p.PrivatePort }
|
||||||
|
|
||||||
|
func selectPort(c types.Container) uint16 {
|
||||||
|
if c.HostConfig.NetworkMode == "host" {
|
||||||
|
return selectPortInternal(c, getPrivatePort)
|
||||||
|
}
|
||||||
|
return selectPortInternal(c, getPublicPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func selectPortInternal(c types.Container, getPort func(types.Port) uint16) uint16 {
|
||||||
|
for _, p := range c.Ports {
|
||||||
|
if port := getPort(p); port != 0 {
|
||||||
|
return port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const wildcardPrefix = "proxy.*"
|
||||||
|
|
Loading…
Add table
Reference in a new issue