Skip to content

Commit

Permalink
refactoring into subpackages
Browse files Browse the repository at this point in the history
  • Loading branch information
progrium committed Feb 19, 2015
1 parent 342b3eb commit 453e55c
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 142 deletions.
170 changes: 104 additions & 66 deletions bridge.go → bridge/bridge.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package main
//go:generate go-extpoints .
package bridge

import (
"log"
Expand All @@ -9,17 +10,14 @@ import (
"strings"
"sync"

"github.com/cenkalti/backoff"
dockerapi "github.com/fsouza/go-dockerclient"
)

type PublishedPort struct {
HostPort string
HostIP string
HostName string
ExposedPort string
ExposedIP string
PortType string
Container *dockerapi.Container
type ServiceRegistry interface {
Register(service *Service) error
Deregister(service *Service) error
Refresh(service *Service) error
}

type Service struct {
Expand All @@ -32,10 +30,32 @@ type Service struct {
Attrs map[string]string
TTL int

pp PublishedPort
Origin ServicePort
}

type ServicePort struct {
HostPort string
HostIP string
HostName string
ExposedPort string
ExposedIP string
PortType string
Container *dockerapi.Container
}

func retry(fn func() error) error {
return backoff.Retry(fn, backoff.NewExponentialBackOff())
}

func mapDefault(m map[string]string, key, default_ string) string {
v, ok := m[key]
if !ok {
return default_
}
return v
}

func CombineTags(tagParts ...string) []string {
func combineTags(tagParts ...string) []string {
tags := make([]string, 0)
for _, element := range tagParts {
if element != "" {
Expand All @@ -45,7 +65,52 @@ func CombineTags(tagParts ...string) []string {
return tags
}

func NewService(port PublishedPort, isgroup bool) *Service {
func serviceMetaData(env []string, port string) map[string]string {
metadata := make(map[string]string)
for _, kv := range env {
kvp := strings.SplitN(kv, "=", 2)
if strings.HasPrefix(kvp[0], "SERVICE_") && len(kvp) > 1 {
key := strings.ToLower(strings.TrimPrefix(kvp[0], "SERVICE_"))
portkey := strings.SplitN(key, "_", 2)
_, err := strconv.Atoi(portkey[0])
if err == nil && len(portkey) > 1 {
if portkey[0] != port {
continue
}
metadata[portkey[1]] = kvp[1]
} else {
metadata[key] = kvp[1]
}
}
}
return metadata
}

type RegistryBridge struct {
sync.Mutex
Registry ServiceRegistry
docker *dockerapi.Client
services map[string][]*Service
config Config
}

type Config struct {
HostIp string
Internal bool
ForceTags string
RefreshTtl int
RefreshInterval int
}

func New(docker *dockerapi.Client, config Config) *RegistryBridge {
return &RegistryBridge{
docker: docker,
config: config,
services: make(map[string][]*Service),
}
}

func (b *RegistryBridge) newService(port ServicePort, isgroup bool) *Service {
container := port.Container
defaultName := strings.Split(path.Base(container.Config.Image), ":")[0]
if isgroup {
Expand All @@ -64,27 +129,27 @@ func NewService(port PublishedPort, isgroup bool) *Service {
}
}

if *hostIp != "" {
port.HostIP = *hostIp
if b.config.HostIp != "" {
port.HostIP = b.config.HostIp
}

metadata := serviceMetaData(container.Config.Env, port.ExposedPort)

ignore := mapdefault(metadata, "ignore", "")
ignore := mapDefault(metadata, "ignore", "")
if ignore != "" {
return nil
}

service := new(Service)
service.pp = port
if *internal {
service.Origin = port
if b.config.Internal {
service.ID = port.HostName + ":" + container.Name[1:] + ":" + port.ExposedPort
} else {
service.ID = hostname + ":" + container.Name[1:] + ":" + port.ExposedPort
}
service.Name = mapdefault(metadata, "name", defaultName)
service.Name = mapDefault(metadata, "name", defaultName)
var p int
if *internal == true {
if b.config.Internal == true {
service.IP = port.ExposedIP
p, _ = strconv.Atoi(port.ExposedPort)
// service.HostName = port.HostName
Expand All @@ -95,13 +160,15 @@ func NewService(port PublishedPort, isgroup bool) *Service {
service.Port = p

if port.PortType == "udp" {
service.Tags = CombineTags(mapdefault(metadata, "tags", ""), *forceTags, "udp")
service.Tags = combineTags(
mapDefault(metadata, "tags", ""), b.config.ForceTags, "udp")
service.ID = service.ID + ":udp"
} else {
service.Tags = CombineTags(mapdefault(metadata, "tags", ""), *forceTags)
service.Tags = combineTags(
mapDefault(metadata, "tags", ""), b.config.ForceTags)
}

id := mapdefault(metadata, "id", "")
id := mapDefault(metadata, "id", "")
if id != "" {
service.ID = id
}
Expand All @@ -110,51 +177,22 @@ func NewService(port PublishedPort, isgroup bool) *Service {
delete(metadata, "tags")
delete(metadata, "name")
service.Attrs = metadata

service.TTL = *refreshTtl
service.TTL = b.config.RefreshTtl

return service
}

func serviceMetaData(env []string, port string) map[string]string {
metadata := make(map[string]string)
for _, kv := range env {
kvp := strings.SplitN(kv, "=", 2)
if strings.HasPrefix(kvp[0], "SERVICE_") && len(kvp) > 1 {
key := strings.ToLower(strings.TrimPrefix(kvp[0], "SERVICE_"))
portkey := strings.SplitN(key, "_", 2)
_, err := strconv.Atoi(portkey[0])
if err == nil && len(portkey) > 1 {
if portkey[0] != port {
continue
}
metadata[portkey[1]] = kvp[1]
} else {
metadata[key] = kvp[1]
}
}
}
return metadata
}

type RegistryBridge struct {
sync.Mutex
docker *dockerapi.Client
registry ServiceRegistry
services map[string][]*Service
}

func MakePublishedPort(container *dockerapi.Container, port dockerapi.Port, published []dockerapi.PortBinding) PublishedPort {
func servicePort(container *dockerapi.Container, port dockerapi.Port, published []dockerapi.PortBinding) ServicePort {
var hp, hip string
if len(published) > 0 {
hp = published[0].HostPort
hip = published[0].HostIP
}
if (hip == "") {
if hip == "" {
hip = "0.0.0.0"
}
}
p := strings.Split(string(port), "/")
return PublishedPort{
return ServicePort{
HostPort: hp,
HostIP: hip,
HostName: container.Config.Hostname,
Expand Down Expand Up @@ -184,16 +222,16 @@ func (b *RegistryBridge) addInternal(containerId string, quiet bool) {
return
}

ports := make(map[string]PublishedPort)
ports := make(map[string]ServicePort)

// Extract configured host port mappings, relevant when using --net=host
for port, published := range container.HostConfig.PortBindings {
ports[string(port)] = MakePublishedPort(container, port, published)
ports[string(port)] = servicePort(container, port, published)
}
// Extract runtime port mappings, relevant when using e.g. --net=bridge

// Extract runtime port mappings, relevant when using --net=bridge
for port, published := range container.NetworkSettings.Ports {
ports[string(port)] = MakePublishedPort(container, port, published)
ports[string(port)] = servicePort(container, port, published)
}

for _, port := range ports {
Expand All @@ -203,15 +241,15 @@ func (b *RegistryBridge) addInternal(containerId string, quiet bool) {
}
continue
}
service := NewService(port, len(ports) > 1)
service := b.newService(port, len(ports) > 1)
if service == nil {
if !quiet {
log.Println("registrator: ignored:", container.ID[:12], "service on port", port.ExposedPort)
}
continue
}
err := retry(func() error {
return b.registry.Register(service)
return b.Registry.Register(service)
})
if err != nil {
log.Println("registrator: unable to register service:", service, err)
Expand All @@ -231,7 +269,7 @@ func (b *RegistryBridge) Remove(containerId string) {
defer b.Unlock()
for _, service := range b.services[containerId] {
err := retry(func() error {
return b.registry.Deregister(service)
return b.Registry.Deregister(service)
})
if err != nil {
log.Println("registrator: unable to deregister service:", service.ID, err)
Expand All @@ -247,7 +285,7 @@ func (b *RegistryBridge) Refresh() {
defer b.Unlock()
for containerId, services := range b.services {
for _, service := range services {
err := b.registry.Refresh(service)
err := b.Registry.Refresh(service)
if err != nil {
log.Println("registrator: unable to refresh service:", service.ID, err)
continue
Expand Down
Loading

0 comments on commit 453e55c

Please sign in to comment.