mirror of
https://github.com/itzg/mc-router.git
synced 2024-11-21 11:25:41 +01:00
Enable network filtering for docker swarm discovery (#143)
This commit is contained in:
parent
298ea8eef9
commit
c2b23d40c7
@ -206,6 +206,8 @@ label on the service. These are the labels scanned:
|
|||||||
The default value is 25565.
|
The default value is 25565.
|
||||||
- `mc-router.default`: Set this to a truthy value to make this server the deafult backend.
|
- `mc-router.default`: Set this to a truthy value to make this server the deafult backend.
|
||||||
Please note that `mc-router.host` is still required to be set.
|
Please note that `mc-router.host` is still required to be set.
|
||||||
|
- `mc-router.network`: Specify the network you are using for the router if multiple are
|
||||||
|
present in the service. You can either use the network ID, it's full name or an alias.
|
||||||
|
|
||||||
## Example Docker Swarm deployment
|
## Example Docker Swarm deployment
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ services:
|
|||||||
replicas: 1
|
replicas: 1
|
||||||
labels:
|
labels:
|
||||||
- "mc-router.host=foo.host.name,bar.host.name"
|
- "mc-router.host=foo.host.name,bar.host.name"
|
||||||
|
- "mc-router.network=minecraft" # not required in this case
|
||||||
volumes:
|
volumes:
|
||||||
- mcfoobardata:/data
|
- mcfoobardata:/data
|
||||||
networks:
|
networks:
|
||||||
@ -39,6 +40,9 @@ services:
|
|||||||
replicas: 1
|
replicas: 1
|
||||||
labels:
|
labels:
|
||||||
- "mc-router.host=baz.host.name"
|
- "mc-router.host=baz.host.name"
|
||||||
|
- "mc-router.network=minecraft" # required since we are exposing a port
|
||||||
|
ports:
|
||||||
|
- "25575:25575" # RCON
|
||||||
volumes:
|
volumes:
|
||||||
- mcbazdata:/data
|
- mcbazdata:/data
|
||||||
networks:
|
networks:
|
||||||
|
@ -37,6 +37,7 @@ const (
|
|||||||
DockerRouterLabelHost = "mc-router.host"
|
DockerRouterLabelHost = "mc-router.host"
|
||||||
DockerRouterLabelPort = "mc-router.port"
|
DockerRouterLabelPort = "mc-router.port"
|
||||||
DockerRouterLabelDefault = "mc-router.default"
|
DockerRouterLabelDefault = "mc-router.default"
|
||||||
|
DockerRouterLabelNetwork = "mc-router.network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *dockerWatcherImpl) makeWakerFunc(service *routableService) func(ctx context.Context) error {
|
func (w *dockerWatcherImpl) makeWakerFunc(service *routableService) func(ctx context.Context) error {
|
||||||
@ -179,7 +180,7 @@ func (w *dockerWatcherImpl) listServices(ctx context.Context) ([]*routableServic
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
data, ok := w.parseServiceData(&service)
|
data, ok := w.parseServiceData(&service, networkMap)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -201,21 +202,46 @@ func (w *dockerWatcherImpl) listServices(ctx context.Context) ([]*routableServic
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dockerCheckNetworkName(id string, name string, networkMap map[string]*dockertypes.NetworkResource, networkAliases map[string][]string) (bool, error) {
|
||||||
|
// we allow to specify the id instead
|
||||||
|
if id == name {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if network := networkMap[id]; network != nil {
|
||||||
|
if network.Name == name {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
aliases := networkAliases[id]
|
||||||
|
for _, alias := range aliases {
|
||||||
|
if alias == name {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("network not found %s", id)
|
||||||
|
}
|
||||||
|
|
||||||
type parsedDockerServiceData struct {
|
type parsedDockerServiceData struct {
|
||||||
hosts []string
|
hosts []string
|
||||||
port uint64
|
port uint64
|
||||||
def *bool
|
def *bool
|
||||||
|
network *string
|
||||||
ip string
|
ip string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parsedDockerServiceData, ok bool) {
|
func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service, networkMap map[string]*dockertypes.NetworkResource) (data parsedDockerServiceData, ok bool) {
|
||||||
ok = true
|
networkAliases := map[string][]string{}
|
||||||
|
for _, network := range service.Spec.TaskTemplate.Networks {
|
||||||
|
networkAliases[network.Target] = network.Aliases
|
||||||
|
}
|
||||||
|
|
||||||
for key, value := range service.Spec.Labels {
|
for key, value := range service.Spec.Labels {
|
||||||
if key == DockerRouterLabelHost {
|
if key == DockerRouterLabelHost {
|
||||||
if data.hosts != nil {
|
if data.hosts != nil {
|
||||||
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
Warnf("ignoring service with duplicate %s", DockerRouterLabelHost)
|
Warnf("ignoring service with duplicate %s", DockerRouterLabelHost)
|
||||||
ok = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data.hosts = strings.Split(value, ",")
|
data.hosts = strings.Split(value, ",")
|
||||||
@ -224,7 +250,6 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
|
|||||||
if data.port != 0 {
|
if data.port != 0 {
|
||||||
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
Warnf("ignoring service with duplicate %s", DockerRouterLabelPort)
|
Warnf("ignoring service with duplicate %s", DockerRouterLabelPort)
|
||||||
ok = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
@ -233,7 +258,6 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
|
|||||||
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
WithError(err).
|
WithError(err).
|
||||||
Warnf("ignoring service with invalid %s", DockerRouterLabelPort)
|
Warnf("ignoring service with invalid %s", DockerRouterLabelPort)
|
||||||
ok = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,7 +265,6 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
|
|||||||
if data.def != nil {
|
if data.def != nil {
|
||||||
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
Warnf("ignoring service with duplicate %s", DockerRouterLabelDefault)
|
Warnf("ignoring service with duplicate %s", DockerRouterLabelDefault)
|
||||||
ok = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data.def = new(bool)
|
data.def = new(bool)
|
||||||
@ -249,19 +272,58 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
|
|||||||
lowerValue := strings.TrimSpace(strings.ToLower(value))
|
lowerValue := strings.TrimSpace(strings.ToLower(value))
|
||||||
*data.def = lowerValue != "" && lowerValue != "0" && lowerValue != "false" && lowerValue != "no"
|
*data.def = lowerValue != "" && lowerValue != "0" && lowerValue != "false" && lowerValue != "no"
|
||||||
}
|
}
|
||||||
}
|
if key == DockerRouterLabelNetwork {
|
||||||
if len(data.hosts) == 0 {
|
if data.network != nil {
|
||||||
ok = false
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
|
Warnf("ignoring service with duplicate %s", DockerRouterLabelNetwork)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
data.network = new(string)
|
||||||
|
*data.network = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// probably not minecraft related
|
||||||
|
if len(data.hosts) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(service.Endpoint.VirtualIPs) == 0 {
|
||||||
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
|
Warnf("ignoring service, no VirtualIPs found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if data.port == 0 {
|
if data.port == 0 {
|
||||||
data.port = 25565
|
data.port = 25565
|
||||||
}
|
}
|
||||||
|
|
||||||
virtualIP := service.Endpoint.VirtualIPs[0]
|
vipIndex := -1
|
||||||
|
if data.network != nil {
|
||||||
|
for i, vip := range service.Endpoint.VirtualIPs {
|
||||||
|
if ok, err := dockerCheckNetworkName(vip.NetworkID, *data.network, networkMap, networkAliases); ok {
|
||||||
|
vipIndex = i
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
// we intentionally ignore name check errors
|
||||||
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
|
Debugf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if vipIndex == -1 {
|
||||||
|
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
|
||||||
|
Warnf("ignoring service, network %s not found", *data.network)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if network isn't specified assume it's the first one
|
||||||
|
vipIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
virtualIP := service.Endpoint.VirtualIPs[vipIndex]
|
||||||
ip, _, _ := net.ParseCIDR(virtualIP.Addr)
|
ip, _, _ := net.ParseCIDR(virtualIP.Addr)
|
||||||
data.ip = ip.String()
|
data.ip = ip.String()
|
||||||
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user