Skip to content
This repository has been archived by the owner on Oct 30, 2023. It is now read-only.

manage consul catalogue #10

Merged
merged 8 commits into from
Jun 12, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

This tool generates configuration files for [Homer](https://github.com/bastienwirtz/homer) using Docker container labels.

Using Docker container labels for service discovery is inspired by the same approach used by [Traefik](https://doc.traefik.io/traefik/providers/docker/) and [Watchtower](https://github.com/containrrr/watchtower).
Using Docker container or consul catalog labels for service discovery is inspired by the same approach used by [Traefik](https://doc.traefik.io/traefik/providers/docker/) and [Watchtower](https://github.com/containrrr/watchtower).
vincentDcmps marked this conversation as resolved.
Show resolved Hide resolved
## Features

- Generates Homer config using container labels
- Watches for container changes
- Watches for consul changes
vincentDcmps marked this conversation as resolved.
Show resolved Hide resolved
- Sort items by priority
- Multi-arch

Expand Down Expand Up @@ -112,3 +113,5 @@ The full list of labels are:
| `LOG_LEVEL` | The level of log verbosity | `Info` |
| `HOMER_BASE_CONFIG` | Where the base config is located | `/base.yml` |
| `HOMER_CONFIG` | Where the Homer config is located | `/config.yml` |
| `SERVICE_DISCOVERY` | Select between consul or docker | `Docker` |
vincentDcmps marked this conversation as resolved.
Show resolved Hide resolved
| `CONSUL_HOST` | Host for consul conenction | `consul.service.consul:8500` |
vincentDcmps marked this conversation as resolved.
Show resolved Hide resolved
110 changes: 73 additions & 37 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ import (

"github.com/calvinbui/homer-docker-service-discovery/internal/config"
"github.com/calvinbui/homer-docker-service-discovery/internal/docker"
"github.com/calvinbui/homer-docker-service-discovery/internal/entry"
"github.com/calvinbui/homer-docker-service-discovery/internal/consul"
"github.com/calvinbui/homer-docker-service-discovery/internal/logger"
"github.com/calvinbui/homer-docker-service-discovery/pkg/homer"
"github.com/hashicorp/consul/api/watch"
"github.com/hashicorp/go-hclog"
)

func main() {
Expand All @@ -23,60 +27,92 @@ func main() {
logger.Fatal("Error parsing config", err)
}

logger.Debug("Retrieving Docker server version")
serverVersion, err := docker.ServerVersion(conf.Docker)
if err != nil {
logger.Fatal("Failed to retrieve information about the Docker client and server host", err)
}
logger.Trace(fmt.Sprintf("Provider connection established with Docker %s (API %s)", serverVersion.Version, serverVersion.APIVersion))
if conf.ServiceDiscovery == config.Docker {
logger.Debug("Retrieving Docker server version")
serverVersion, err := docker.ServerVersion(conf.Docker)
if err != nil {
logger.Fatal("Failed to retrieve information about the Docker client and server host", err)
}
logger.Trace(fmt.Sprintf("Provider connection established with Docker %s (API %s)", serverVersion.Version, serverVersion.APIVersion))

}
logger.Info("Building Homer config from base config")

ctx := context.Background()
err = generateConfig(ctx, conf)
if err != nil {
logger.Fatal("Error generating Homer config", err)
}

logger.Info("Start watching for container creations and deletions")
eventsc, errc := docker.WatchEvents(ctx, conf.Docker)
for {
select {
case event := <-eventsc:
if event.Action == "start" || event.Action == "die" || strings.HasPrefix(event.Action, "health_status") {
logger.Trace(fmt.Sprintf("%+v", event))
logger.Debug("A " + event.Action + " event occurred")
logger.Info(fmt.Sprintf("Event '%s' received from %s. Generating Homer config...", event.Action, event.Actor.Attributes["name"]))
time.Sleep(1 * time.Second)
err = generateConfig(ctx, conf)
if err != nil {
logger.Fatal("Error generating Homer config", err)
if conf.ServiceDiscovery == config.Docker {
logger.Info("Start watching for container creations and deletions")
eventsc, errc := docker.WatchEvents(ctx, conf.Docker)
for {
select {
case event := <-eventsc:
if event.Action == "start" || event.Action == "die" || strings.HasPrefix(event.Action, "health_status") {
logger.Trace(fmt.Sprintf("%+v", event))
logger.Debug("A " + event.Action + " event occurred")
logger.Info(fmt.Sprintf("Event '%s' received from %s. Generating Homer config...", event.Action, event.Actor.Attributes["name"]))
time.Sleep(1 * time.Second)
err = generateConfig(ctx, conf)
if err != nil {
logger.Fatal("Error generating Homer config", err)
}
}
case err := <-errc:
if errors.Is(err, io.EOF) {
logger.Debug("Provider event stream closed")
}
case <-ctx.Done():
return
}
case err := <-errc:
if errors.Is(err, io.EOF) {
logger.Debug("Provider event stream closed")
}
case <-ctx.Done():
return
}
}else if conf.ServiceDiscovery == config.Consul {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you will need to run go fmt on your files

logger.Info("Start watching for consul services change")
hcLogger := hclog.New(&hclog.LoggerOptions{
Name: "consulcatalog",
Level: hclog.LevelFromString(conf.LogLevel),
JSONFormat: true,
})
for{
watcher := consul.WatchServices(conf.Consul)
watcher.HybridHandler=func(_ watch.BlockingParamVal, _ interface{}) {
logger.Info("consul handler fired")
vincentDcmps marked this conversation as resolved.
Show resolved Hide resolved
generateConfig(ctx,conf)
}
watcher.RunWithClientAndHclog(conf.Consul,hcLogger)
time.Sleep(1 * time.Second)
}
}
}

func generateConfig(ctx context.Context, conf config.Config) error {
logger.Debug("Getting Docker containers")
containers, err := docker.ListRunningContainers(ctx, conf.Docker)
if err != nil {
logger.Fatal("Failed to list containers for Docker", err)
}
var parsedContainers []docker.Container
for _, container := range containers {
parsedContainer, err := docker.ParseContainer(ctx, conf.Docker, container)
var parsedEntry []entry.RawEntry
if conf.ServiceDiscovery == config.Docker {
logger.Debug("Getting Docker containers")
containers, err := docker.ListRunningContainers(ctx, conf.Docker)
if err != nil {
logger.Error(fmt.Sprintf("Failed to inspect container %s", container.Names), err)
logger.Fatal("Failed to list containers for Docker", err)
}
for _, container := range containers {
parsedContainer, err := docker.ParseContainer(ctx, conf.Docker, container)
if err != nil {
logger.Error(fmt.Sprintf("Failed to inspect container %s", container.Names), err)
}
logger.Debug(fmt.Sprintf("Inspected container %s", parsedContainer.Name))
parsedEntry = append(parsedEntry, parsedContainer)
}
}else if conf.ServiceDiscovery == config.Consul {
logger.Debug("Getting Consul service")
services := consul.ListServices(conf.Consul)
for name,label := range services {

parsedService := consul.ParseService(name,label)
parsedEntry = append (parsedEntry,parsedService)
}
logger.Debug(fmt.Sprintf("Inspected container %s", parsedContainer.Name))
parsedContainers = append(parsedContainers, parsedContainer)
}


logger.Debug("Loading base config")
baseConfig, err := homer.GetConfig(conf.HomerBaseConfigPath)
Expand All @@ -86,7 +122,7 @@ func generateConfig(ctx context.Context, conf config.Config) error {
logger.Debug(fmt.Sprintf("Loaded base config: %+v", baseConfig))

logger.Debug("Generating config")
generatedConfig, err := homer.BuildConfig(baseConfig, parsedContainers)
generatedConfig, err := homer.BuildConfig(baseConfig, parsedEntry)
if err != nil {
logger.Fatal("Error building Homer config", err)
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/containerd/containerd v1.5.1 // indirect
github.com/docker/docker v20.10.6+incompatible
github.com/docker/go-connections v0.4.0 // indirect
github.com/hashicorp/consul/api v1.12.0
github.com/morikuni/aec v1.0.0 // indirect
github.com/rs/zerolog v1.23.0
github.com/sirupsen/logrus v1.8.1 // indirect
Expand Down
Loading