mirror of
https://github.com/KevinMidboe/traefik-etcd-advertiser.git
synced 2025-10-28 17:30:19 +00:00
init
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
vendor/
|
||||
26
Makefile
Normal file
26
Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
.PHONY: build install server
|
||||
|
||||
PROJECT_NAME=$(shell basename $(CURDIR))
|
||||
|
||||
## build: build the application
|
||||
build:
|
||||
export GO111MODULE="auto"; \
|
||||
go mod download; \
|
||||
go mod vendor; \
|
||||
CGO_ENABLED=0 go build -a -ldflags '-s' -installsuffix cgo -o main main.go
|
||||
|
||||
## install: fetches go modules
|
||||
install:
|
||||
export GO111MODULE="on"; \
|
||||
go mod tidy; \
|
||||
go mod download \
|
||||
|
||||
## server: runs the server with -race
|
||||
server:
|
||||
export GO111MODULE="on"; \
|
||||
go run main.go
|
||||
|
||||
## modd: Monitors the directory, and recompiles your app every time a file changes. Also runs tests.
|
||||
## (To install modd, run: go get github.com/cortesi/modd/cmd/modd)
|
||||
modd:
|
||||
modd
|
||||
24
assets/docker-compose-2.yml
Normal file
24
assets/docker-compose-2.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
# version: "3.9"
|
||||
|
||||
services:
|
||||
webapp:
|
||||
image: nginx:alpine
|
||||
container_name: webapp
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.webapp.rule=Host(`webapp.localhost`)"
|
||||
- "traefik.http.routers.webapp.entrypoints=web"
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.webapp.middlewares=redirect-to-https"
|
||||
- "traefik.http.routers.webapp.tls=true"
|
||||
- "traefik.http.services.webapp.loadbalancer.server.port=80"
|
||||
|
||||
backend:
|
||||
image: my-backend-app:latest
|
||||
container_name: backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.backend.rule=Host(`backend.localhost`)"
|
||||
- "traefik.http.routers.backend.entrypoints=web"
|
||||
- "traefik.http.routers.backend.tls=true"
|
||||
- "traefik.http.services.backend.loadbalancer.server.port=5000" # Port exposed by the backend app
|
||||
24
assets/docker-compose.yml
Normal file
24
assets/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
webapp:
|
||||
image: nginx:alpine
|
||||
container_name: webapp
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.webapp.rule=Host(`webapp.localhost`)"
|
||||
- "traefik.http.routers.webapp.entrypoints=web"
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.webapp.middlewares=redirect-to-https"
|
||||
- "traefik.http.routers.webapp.tls=true"
|
||||
- "traefik.http.services.webapp.loadbalancer.server.port=80"
|
||||
|
||||
backend:
|
||||
image: my-backend-app:latest
|
||||
container_name: backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.backend.rule=Host(`backend.localhost`)"
|
||||
- "traefik.http.routers.backend.entrypoints=web"
|
||||
- "traefik.http.routers.backend.tls=true"
|
||||
- "traefik.http.services.backend.loadbalancer.server.port=5000" # Port exposed by the backend app
|
||||
34
assets/dynamic.yml
Normal file
34
assets/dynamic.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
http:
|
||||
routers:
|
||||
request-router:
|
||||
rule: "Host(`request.test`)"
|
||||
service: request-service
|
||||
entryPoints:
|
||||
- web
|
||||
services:
|
||||
request-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://seasoned.schleppe:5000"
|
||||
weight: 100
|
||||
passHostHeader: true
|
||||
mirrored-service:
|
||||
mirroring:
|
||||
service: example-service
|
||||
mirrorBody: true
|
||||
maxBodySize: 1024
|
||||
mirrors:
|
||||
- name: mirror1
|
||||
percent: 10
|
||||
url: http://example.com
|
||||
- name: mirror2
|
||||
percent: 20
|
||||
url: http://example.org
|
||||
healthCheck:
|
||||
service: "request-service"
|
||||
|
||||
middlewares:
|
||||
redirect-to-https:
|
||||
redirectScheme:
|
||||
permanent: false
|
||||
scheme: https
|
||||
129
client/etcd/etcd.go
Normal file
129
client/etcd/etcd.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
etcd "go.etcd.io/etcd/client/v3"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
)
|
||||
|
||||
type EtcdManager struct {
|
||||
client *etcd.Client
|
||||
}
|
||||
|
||||
type EtcdPacket struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func NewClient() (*EtcdManager, error) {
|
||||
fmt.Println("setting up etcd client")
|
||||
|
||||
endpoints := []string{"localhost:2379"}
|
||||
if value, exists := os.LookupEnv("ETCD_ENDPOINTS"); exists {
|
||||
endpoints = strings.Split(value, ",")
|
||||
}
|
||||
|
||||
client, err := etcd.New(etcd.Config{
|
||||
Endpoints: endpoints,
|
||||
DialTimeout: 30 * time.Second,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create etcd manager")
|
||||
}
|
||||
|
||||
mgr := &EtcdManager{client}
|
||||
|
||||
err = mgr.runWithTimeout(func(e *EtcdManager, ctx context.Context) error {
|
||||
etcdStatus, err := e.client.Status(ctx, e.client.Endpoints()[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get etcd status: %v", err)
|
||||
}
|
||||
if len(etcdStatus.Errors) > 0 {
|
||||
return fmt.Errorf("etcd server has errors: %v", etcdStatus.Errors)
|
||||
}
|
||||
|
||||
connState := e.client.ActiveConnection().GetState()
|
||||
if connState != connectivity.Ready && connState != connectivity.Idle {
|
||||
return fmt.Errorf("etcd connection is in unexpecetd state: %s",
|
||||
e.client.ActiveConnection().GetState())
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mgr, nil
|
||||
}
|
||||
|
||||
func (e *EtcdManager) runWithTimeout(runnable func(e *EtcdManager, ctx context.Context) error) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
return runnable(e, ctx)
|
||||
}
|
||||
|
||||
func runWithTimeoutReturning[R any](
|
||||
e *EtcdManager,
|
||||
runnable func(e *EtcdManager, ctx context.Context) (R, error),
|
||||
) (R, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
return runnable(e, ctx)
|
||||
}
|
||||
|
||||
func (e *EtcdManager) Put(key string, val string, opts ...etcd.OpOption) error {
|
||||
log.Println("etcd: Putting key", key, val)
|
||||
return e.runWithTimeout(func(e *EtcdManager, ctx context.Context) error {
|
||||
_, err := e.client.Put(ctx, key, val, opts...)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (e *EtcdManager) Get(key string, opts ...etcd.OpOption) (string, error) {
|
||||
log.Println("etcd: Getting key", key)
|
||||
return runWithTimeoutReturning(e, func(e *EtcdManager, ctx context.Context) (string, error) {
|
||||
resp, err := e.client.Get(ctx, key, opts...)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return string(resp.Kvs[0].Value), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (e *EtcdManager) Remove(key string) error {
|
||||
log.Println("etcd: Removing key", key)
|
||||
return e.runWithTimeout(func(e *EtcdManager, ctx context.Context) error {
|
||||
_, err := e.client.Delete(ctx, key)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func RemoveDuplicatePackets(packets *[]EtcdPacket) {
|
||||
keys := make(map[string]bool)
|
||||
list := []EtcdPacket{}
|
||||
keysRm := []string{}
|
||||
|
||||
for _, entry := range *packets {
|
||||
if _, ok := keys[entry.Key]; !ok {
|
||||
keys[entry.Key] = true
|
||||
list = append(list, entry)
|
||||
} else {
|
||||
keysRm = append(keysRm, entry.Key)
|
||||
}
|
||||
}
|
||||
|
||||
if len(keysRm) > 0 {
|
||||
slog.Warn(fmt.Sprintf("keys squashed: %s", keysRm))
|
||||
}
|
||||
|
||||
*packets = list
|
||||
}
|
||||
26
config/config.go
Normal file
26
config/config.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
)
|
||||
|
||||
// Config contains environment variables.
|
||||
type Config struct {
|
||||
EtcdEndpoint string `envconfig:"ETCD_ENDPOINTS"`
|
||||
}
|
||||
|
||||
// LoadConfig reads environment variables, populates and returns Config.
|
||||
func LoadConfig() (*Config, error) {
|
||||
if err := godotenv.Load(); err != nil {
|
||||
log.Println("No .env file found")
|
||||
}
|
||||
|
||||
var c Config
|
||||
|
||||
err := envconfig.Process("", &c)
|
||||
|
||||
return &c, err
|
||||
}
|
||||
18
converter/json.go
Normal file
18
converter/json.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
)
|
||||
|
||||
func TraefikToJSON(config *dynamic.Configuration) map[string]interface{} {
|
||||
var data map[string]interface{}
|
||||
jsonData, _ := json.Marshal(config)
|
||||
if err := json.Unmarshal(jsonData, &data); err != nil {
|
||||
log.Printf("failed to unmarshal JSON: %w", err)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
28
converter/yaml.go
Normal file
28
converter/yaml.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TraefikFromYaml(filePath string) (*dynamic.Configuration, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var cfg dynamic.Configuration
|
||||
decoder := yaml.NewDecoder(file)
|
||||
if err := decoder.Decode(&cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
func TraefikToYaml(config *dynamic.Configuration) string {
|
||||
return ""
|
||||
}
|
||||
65
generator/docker.go
Normal file
65
generator/docker.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/cli"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/client/etcd"
|
||||
)
|
||||
|
||||
func dockerLabelToEtcdKey(key string) string {
|
||||
return strings.ReplaceAll(key, ".", "/")
|
||||
}
|
||||
|
||||
func ParseDockerCompose(composeFilePath string) (*types.Project, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
options, err := cli.NewProjectOptions(
|
||||
[]string{composeFilePath},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
project, err := options.LoadProject(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func createPacket2(config *types.Project) []etcd.EtcdPacket {
|
||||
blocks := []etcd.EtcdPacket{}
|
||||
|
||||
fmt.Println("DockerToEtcd")
|
||||
if config.Services == nil || len(config.Services) < 1 {
|
||||
fmt.Println("services not found - skipping")
|
||||
return blocks
|
||||
}
|
||||
|
||||
for serviceName, _ := range config.Services {
|
||||
if config.Services[serviceName].Labels == nil {
|
||||
fmt.Println("sevice, but no labels found - continuing")
|
||||
continue
|
||||
}
|
||||
|
||||
for key, val := range config.Services[serviceName].Labels {
|
||||
blocks = append(blocks, etcd.EtcdPacket{
|
||||
Key: dockerLabelToEtcdKey(key),
|
||||
Value: val,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
func DockerToEtcd(config *types.Project, packetList *[]etcd.EtcdPacket) {
|
||||
items := createPacket2(config)
|
||||
|
||||
*packetList = append(*packetList, items...)
|
||||
}
|
||||
83
generator/traefik.go
Normal file
83
generator/traefik.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/client/etcd"
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/converter"
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
)
|
||||
|
||||
const traefikPrefix = "traefik"
|
||||
|
||||
func isKnownGenericType(value interface{}) bool {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return true
|
||||
case float64:
|
||||
return true
|
||||
case bool:
|
||||
return true
|
||||
default:
|
||||
slog.Debug(fmt.Sprintf("found unknown generic %s\n", v))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func convertToGeneric(value interface{}) string {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return v
|
||||
case float64:
|
||||
return fmt.Sprintf("%d", int(math.Floor(v)))
|
||||
case bool:
|
||||
return strconv.FormatBool(v)
|
||||
}
|
||||
|
||||
return "unknown type"
|
||||
}
|
||||
|
||||
// recursively walks the JSON object and creates internal
|
||||
// `etcdPackets` per leaf node, returns list of packets.
|
||||
func createPacket(item interface{}, parentKey string) []etcd.EtcdPacket {
|
||||
blocks := []etcd.EtcdPacket{}
|
||||
|
||||
switch itemD := item.(type) {
|
||||
// input is JSON object
|
||||
case map[string]interface{}:
|
||||
for key, value := range itemD {
|
||||
// check for generic value type vs nested object,
|
||||
// either create block or recursively call obj again
|
||||
|
||||
if isKnownGenericType(value) {
|
||||
blocks = append(blocks, etcd.EtcdPacket{
|
||||
Key: parentKey + "/" + key,
|
||||
Value: convertToGeneric(value),
|
||||
})
|
||||
} else {
|
||||
blocks = append(blocks, createPacket(itemD[key], fmt.Sprintf("%s/%s", parentKey, key))...)
|
||||
}
|
||||
}
|
||||
// input is JSON list
|
||||
case []interface{}:
|
||||
for i, item := range itemD {
|
||||
blocks = append(blocks, createPacket(item, parentKey+"/"+strconv.Itoa(i))...)
|
||||
}
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
func TraefikToEtcd(config *dynamic.Configuration, packetList *[]etcd.EtcdPacket) {
|
||||
// always convert to json before converting to etcd
|
||||
data := converter.TraefikToJSON(config)
|
||||
|
||||
// generate list of etcd commands
|
||||
items := createPacket(data, traefikPrefix)
|
||||
*packetList = append(*packetList, items...)
|
||||
}
|
||||
|
||||
97
go.mod
Normal file
97
go.mod
Normal file
@@ -0,0 +1,97 @@
|
||||
module github.com/kevinmidboe/traefik-etcd-advertiser
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.3
|
||||
|
||||
require (
|
||||
github.com/compose-spec/compose-go/v2 v2.4.7
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/traefik/traefik/v3 v3.3.2
|
||||
go.etcd.io/etcd/client/v3 v3.5.17
|
||||
google.golang.org/grpc v1.67.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.32.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.44.327 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-acme/lego/v4 v4.21.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-github/v28 v28.1.1 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/http-wasm/http-wasm-host-go v0.7.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/miekg/dns v1.1.62 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/traefik/paerser v0.2.1 // indirect
|
||||
github.com/unrolled/render v1.0.2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.17 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.17 // indirect
|
||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/protobuf v1.35.2 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/apimachinery v0.32.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
66
main.go
Normal file
66
main.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/client/etcd"
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/config"
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/converter"
|
||||
"github.com/kevinmidboe/traefik-etcd-advertiser/generator"
|
||||
)
|
||||
|
||||
func getArgvFilename() string {
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatalf("Usage: %s <path-to-yaml-file>\n", os.Args[0])
|
||||
}
|
||||
|
||||
filename := os.Args[1]
|
||||
return filename
|
||||
}
|
||||
|
||||
func main() {
|
||||
_, err := config.LoadConfig()
|
||||
if err != nil {
|
||||
log.Println("Error from config loader", err)
|
||||
}
|
||||
|
||||
// setup etcd client
|
||||
// etcdManager, err := etcd.NewClient()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var packets []etcd.EtcdPacket
|
||||
|
||||
// parse traefik config from file
|
||||
filename := getArgvFilename()
|
||||
if strings.Contains(filename, "docker-compose.yml") {
|
||||
// build etcd packets from docker-compose config
|
||||
dockerConfig, err := generator.ParseDockerCompose(filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// generator.PrintLabels(labels)
|
||||
fmt.Println("compose")
|
||||
log.Println(dockerConfig)
|
||||
// generator.TraefikToEtcd(traefikConfig, &packets)
|
||||
|
||||
} else {
|
||||
// build etcd packets from traefik config
|
||||
traefikConfig, err := converter.TraefikFromYaml(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error loading traefik YAML config file: %v\n", err)
|
||||
}
|
||||
|
||||
generator.TraefikToEtcd(traefikConfig, &packets)
|
||||
}
|
||||
|
||||
for _, packet := range packets {
|
||||
log.Println(packet)
|
||||
// etcdManager.Put(packet.Key, packet.Value)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user