Skip to content

Commit

Permalink
add option to register service alias for fabio
Browse files Browse the repository at this point in the history
This patch adds an "alias" option which tells Fabio to register a new
frontend service in Consul on behalf of the requesting backend service.
The new service provides Consul-hosted A records to Fabio with the
desired service name.
  • Loading branch information
rileyje committed Jan 24, 2018
1 parent 2b7594a commit 760a15e
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 20 deletions.
7 changes: 5 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func main() {
if registry.Default == nil {
return
}
registry.Default.Deregister()
registry.Default.Deregister("")
})

// init metrics early since that create the global metric registries
Expand Down Expand Up @@ -284,6 +284,7 @@ func startServers(cfg *config.Config) {
ConnFail: metrics.DefaultRegistry.GetCounter("tcp_sni.connfail"),
Noroute: metrics.DefaultRegistry.GetCounter("tcp_sni.noroute"),
}

if err := proxy.ListenAndServeTCP(l, h, tlscfg); err != nil {
exit.Fatal("[FATAL] ", err)
}
Expand Down Expand Up @@ -354,7 +355,7 @@ func initBackend(cfg *config.Config) {
}

if err == nil {
if err = registry.Default.Register(); err == nil {
if err = registry.Default.Register(""); err == nil {
return
}
}
Expand Down Expand Up @@ -396,6 +397,8 @@ func watchBackend(cfg *config.Config, first chan bool) {
continue
}

registry.Default.UpdateAliases(next)

t, err := route.NewTable(next)
if err != nil {
log.Printf("[WARN] %s", err)
Expand Down
7 changes: 5 additions & 2 deletions registry/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package registry

type Backend interface {
// Register registers fabio as a service in the registry.
Register() error
Register(serviceName string) error

// Deregister removes the service registration for fabio.
Deregister() error
Deregister(serviceName string) error

// UpdateAliases() is used to add new aliases and remove obsolete aliases
UpdateAliases(config string) error

// ReadManual returns the current manual overrides and
// their version as seen by the registry.
Expand Down
97 changes: 88 additions & 9 deletions registry/consul/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/fabiolb/fabio/config"
"github.com/fabiolb/fabio/registry"
"github.com/fabiolb/fabio/route"

"github.com/hashicorp/consul/api"
)
Expand All @@ -15,7 +16,7 @@ type be struct {
c *api.Client
dc string
cfg *config.Consul
dereg chan bool
dereg map[string](chan bool)
}

func NewBackend(cfg *config.Consul) (registry.Backend, error) {
Expand All @@ -36,26 +37,47 @@ func NewBackend(cfg *config.Consul) (registry.Backend, error) {
return &be{c: c, dc: dc, cfg: cfg}, nil
}

func (b *be) Register() error {
if !b.cfg.Register {
func (b *be) Register(serviceName string) error {
if len(serviceName) == 0 {
serviceName = b.cfg.ServiceName
}

if serviceName == b.cfg.ServiceName && !b.cfg.Register {
log.Printf("[INFO] consul: Not registering fabio in consul")
return nil
}

service, err := serviceRegistration(b.cfg)
service, err := serviceRegistration(b.cfg, serviceName)
if err != nil {
return err
}

b.dereg = register(b.c, service)
if b.dereg == nil {
b.dereg = make(map[string](chan bool))
}

b.dereg[serviceName] = register(b.c, service)

return nil
}

func (b *be) Deregister() error {
if b.dereg != nil {
b.dereg <- true // trigger deregistration
<-b.dereg // wait for completion
func (b *be) Deregister(serviceName string) error {
if len(serviceName) == 0 {
for name, dereg := range b.dereg {
if dereg != nil {
log.Printf("[INFO]: consul: Deregistering %q", name)
dereg <- true // trigger deregistration
<-dereg // wait for completion
}
}
} else {
if dereg := b.dereg[serviceName]; dereg != nil {
dereg <- true
<-dereg
delete(b.dereg, serviceName)
}
}

return nil
}

Expand Down Expand Up @@ -100,6 +122,54 @@ func (b *be) WatchNoRouteHTML() chan string {
return html
}

func (b *be) UpdateAliases(config string) error {
defs, err := route.Parse(config)
if err != nil {
return err
}

var aliases []string

if b.cfg.Register {
aliases = append(aliases, b.cfg.ServiceName)
}

for _, d := range defs {
if d.Opts["alias"] != "" {
log.Printf("[DEBUG]: consul: Service %q wants alias %q", d.Service, d.Opts["alias"])
aliases = append(aliases, d.Opts["alias"])
}
}

// register new aliases
for _, alias := range aliases {
if _, hasAlias := b.dereg[alias]; hasAlias {
log.Printf("[DEBUG]: consul: Skipping registration for existing alias %q", alias)
continue
}
log.Printf("[DEBUG]: consul: Registering new alias %q", alias)
err := registry.Default.Register(alias)
if err != nil {
log.Printf("[WARN] %q", err)
}
}

// deregister old aliases
for alias := range b.dereg {
if stringInSlice(alias, aliases) {
log.Printf("[DEBUG]: consul: Keeping alias %q", alias)
continue
}
log.Printf("[DEBUG]: consul: Deregister alias %q", alias)
err := registry.Default.Deregister(alias)
if err != nil {
log.Printf("[WARN] %s", err)
}
}

return nil
}

// datacenter returns the datacenter of the local agent
func datacenter(c *api.Client) (string, error) {
self, err := c.Agent().Self()
Expand All @@ -117,3 +187,12 @@ func datacenter(c *api.Client) (string, error) {
}
return dc, nil
}

func stringInSlice(str string, strSlice []string) bool {
for _, s := range strSlice {
if s == str {
return true
}
}
return false
}
11 changes: 6 additions & 5 deletions registry/consul/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ func register(c *api.Client, service *api.AgentServiceRegistration) chan bool {

register := func() string {
if err := c.Agent().ServiceRegister(service); err != nil {
log.Printf("[ERROR] consul: Cannot register fabio in consul. %s", err)
log.Printf("[ERROR] consul: Cannot register fabio [name:%q] in Consul. %s", service.Name, err)
return ""
}

log.Printf("[INFO] consul: Registered fabio with name %q", service.Name)
log.Printf("[INFO] consul: Registered fabio with id %q", service.ID)
log.Printf("[INFO] consul: Registered fabio with address %q", service.Address)
log.Printf("[INFO] consul: Registered fabio with tags %q", strings.Join(service.Tags, ","))
Expand All @@ -51,7 +52,7 @@ func register(c *api.Client, service *api.AgentServiceRegistration) chan bool {
}

deregister := func(serviceID string) {
log.Printf("[INFO] consul: Deregistering fabio")
log.Printf("[INFO] consul: Deregistering %s", service.Name)
c.Agent().ServiceDeregister(serviceID)
}

Expand All @@ -76,7 +77,7 @@ func register(c *api.Client, service *api.AgentServiceRegistration) chan bool {
return dereg
}

func serviceRegistration(cfg *config.Consul) (*api.AgentServiceRegistration, error) {
func serviceRegistration(cfg *config.Consul, serviceName string) (*api.AgentServiceRegistration, error) {
hostname, err := os.Hostname()
if err != nil {
return nil, err
Expand All @@ -101,7 +102,7 @@ func serviceRegistration(cfg *config.Consul) (*api.AgentServiceRegistration, err
}
}

serviceID := fmt.Sprintf("%s-%s-%d", cfg.ServiceName, hostname, port)
serviceID := fmt.Sprintf("%s-%s-%d", serviceName, hostname, port)

checkURL := fmt.Sprintf("%s://%s:%d/health", cfg.CheckScheme, ip, port)
if ip.To16() != nil {
Expand All @@ -110,7 +111,7 @@ func serviceRegistration(cfg *config.Consul) (*api.AgentServiceRegistration, err

service := &api.AgentServiceRegistration{
ID: serviceID,
Name: cfg.ServiceName,
Name: serviceName,
Address: ip.String(),
Port: port,
Tags: cfg.ServiceTags,
Expand Down
8 changes: 6 additions & 2 deletions registry/static/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ func NewBackend(cfg *config.Static) (registry.Backend, error) {
return &be{cfg}, nil
}

func (b *be) Register() error {
func (b *be) Register(serviceName string) error {
return nil
}

func (b *be) Deregister() error {
func (b *be) Deregister(serviceName string) error {
return nil
}

func (b *be) UpdateAliases(config string) error {
return nil
}

Expand Down

0 comments on commit 760a15e

Please sign in to comment.