Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.config
interlock/interlock
*.swp
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Rule struct {
// the extension itself will use whichever options needed
type ExtensionConfig struct {
Name string // extension name
ServiceName string // service name
ConfigPath string // config file path
ConfigBasePath string `toml:"-"` // internal
PidPath string // haproxy, nginx
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ they are compatible:
|Option|Type|Extensions Supported|
|----|----|----|
|Name | string | extension name |
|ServiceName | string | service name |
|ConfigPath | string | config file path |
|PidPath | string | haproxy, nginx |
|BackendOverrideAddress | string | haproxy, nginx |
Expand Down
25 changes: 25 additions & 0 deletions docs/interlock_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ compatibility.
|Label|Extensions Supported|
|----|----|
|`interlock.ext.name` | internal |
|`interlock.ext.service_name` | internal |
|`interlock.hostname` | haproxy, nginx|
|`interlock.domain` | haproxy, nginx|
|`interlock.ssl` | nginx|
Expand All @@ -27,6 +28,30 @@ compatibility.
|`interlock.balance_algorithm` | haproxy|
|`interlock.backend_option` | haproxy|

# Service Name
To have Interlock work with multiple independent services, run the Interlock
container with the `interlock.ext.service_name` label. This will cause it to
only manage the load balancer and all application service containers with the
same label. For example:

```
docker run -d -p 8080:8080 \
--name interlock_foo \
--label interlock.ext.service_name=foo \
ehazlett/interlock:1.2.0 \
-D run -c /etc/interlock/config.toml

docker run -d -p 80:80 \
--name nginx_foo \
--label interlock.ext.name=nginx \
--label interlock.ext.service_name=foo \
nginx

docker run -d -P \
--label interlock.ext.service_name=foo \
ehazlett/docker-demo
```

# Port
If an upstream container uses multiple ports you can select the port for
the proxy to use by specifying the following label: `interlock.port=8080`.
Expand Down
1 change: 1 addition & 0 deletions ext/ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
const (
InterlockAppLabel = "interlock.app" // internal
InterlockExtNameLabel = "interlock.ext.name" // common
InterlockExtServiceNameLabel = "interlock.ext.service_name" // common
InterlockHostnameLabel = "interlock.hostname" // haproxy, nginx
InterlockNetworkLabel = "interlock.network" // common
InterlockDomainLabel = "interlock.domain" // haproxy, nginx
Expand Down
52 changes: 42 additions & 10 deletions ext/lb/lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ func NewLoadBalancer(c *config.ExtensionConfig, client *dockerclient.DockerClien

log().Debug("updating load balancers")

containers, err := client.ListContainers(true, false, "")
containers, err := extension.ListContainers()

if err != nil {
errChan <- err
continue
Expand All @@ -202,7 +203,7 @@ func NewLoadBalancer(c *config.ExtensionConfig, client *dockerclient.DockerClien

proxyNetworks := map[string]string{}

proxyContainers, err := extension.ProxyContainers(extension.backend.Name())
proxyContainers, err := extension.ProxyContainers(extension.backend.Name(), containers)
if err != nil {
errChan <- err
continue
Expand Down Expand Up @@ -298,12 +299,26 @@ func (l *LoadBalancer) Name() string {
return pluginName
}

func (l *LoadBalancer) ProxyContainers(name string) ([]dockerclient.Container, error) {
containers, err := l.client.ListContainers(true, false, "")
func (l *LoadBalancer) ListContainers() ([]dockerclient.Container, error) {
var containers []dockerclient.Container
var err error

allContainers, err := l.client.ListContainers(true, false, "")

if err != nil {
return nil, err
}

for _, cnt := range allContainers {
if l.isServiceContainer(cnt.Labels) {
containers = append(containers, cnt)
}
}

return containers, nil
}

func (l *LoadBalancer) ProxyContainers(name string, containers []dockerclient.Container) ([]dockerclient.Container, error) {
proxyContainers := []dockerclient.Container{}

// find interlock proxy containers
Expand Down Expand Up @@ -461,10 +476,8 @@ func (l *LoadBalancer) isExposedContainer(id string) bool {
return false
}

log().Debugf("checking container labels: id=%s", id)
// ignore proxy containers
if _, ok := c.Config.Labels[ext.InterlockExtNameLabel]; ok {
log().Debugf("ignoring proxy container: id=%s", id)
if !l.isServiceContainer(c.Config.Labels) {
log().Debugf("ignoring service container: id=%s labels=%s", id, c.Config.Labels)
return false
}

Expand All @@ -473,8 +486,6 @@ func (l *LoadBalancer) isExposedContainer(id string) bool {
return false
}

log().Debugf("checking container ports: id=%s", id)
// ignore containers without exposed ports
if len(c.Config.ExposedPorts) == 0 {
log().Debugf("no ports exposed; ignoring: id=%s", id)
return false
Expand All @@ -483,3 +494,24 @@ func (l *LoadBalancer) isExposedContainer(id string) bool {
log().Debugf("container is monitored; triggering reload: id=%s", id)
return true
}

func (l *LoadBalancer) isServiceContainer(labels map[string]string) bool {
serviceName, labelled := labels[ext.InterlockExtServiceNameLabel]

switch {
case l.serviceNameMatch(serviceName):
return true
case l.serviceNamelessMatch(serviceName, labelled):
return true
default:
return false
}
}

func (l *LoadBalancer) serviceNameMatch(serviceName string) bool {
return len(l.cfg.ServiceName) > 0 && serviceName == l.cfg.ServiceName
}

func (l *LoadBalancer) serviceNamelessMatch(serviceName string, labelled bool) bool {
return len(l.cfg.ServiceName) == 0 && !labelled
}
9 changes: 8 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/ehazlett/interlock/ext/lb"
"github.com/prometheus/client_golang/prometheus"
"github.com/samalba/dockerclient"
"fmt"
)

type Server struct {
Expand Down Expand Up @@ -165,7 +166,13 @@ func (s *Server) waitForSwarm() {

func (s *Server) loadExtensions(client *dockerclient.DockerClient) {
for _, x := range s.cfg.Extensions {
log.Debugf("loading extension: name=%s", x.Name)
loadingMsg := fmt.Sprintf("loading extension: name=%s", x.Name)
if len(x.ServiceName) > 0 {
loadingMsg = fmt.Sprintf("%s serviceName=%s", loadingMsg, x.ServiceName)
}

log.Debugf(loadingMsg)

switch strings.ToLower(x.Name) {
case "haproxy", "nginx":
p, err := lb.NewLoadBalancer(x, client)
Expand Down