-
Notifications
You must be signed in to change notification settings - Fork 617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add option to allow Fabio to register frontend services in Consul on behalf of user services #426
Conversation
46c2cec
to
760a15e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a cool idea. I would structure the implementation a bit different and keep the parsing code together. Also, I wouldn't distinguish between registering and updating registrations since the update call does all the heavy lifting and register then becomes a special case.
I'm not sure if alias
is a good name for the option since it is quite generic and it isn't clear what this is an alias for. Maybe register
?
registry/backend.go
Outdated
@@ -2,10 +2,13 @@ package registry | |||
|
|||
type Backend interface { | |||
// Register registers fabio as a service in the registry. | |||
Register() error | |||
Register(serviceName string) error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a better approach would be to just extend the register function since you need to keep the state of what is registered in the backend anyway.
type Backend interface {
Register(name ...string) error
DeregisterAll() error
...
}
registry/consul/backend.go
Outdated
@@ -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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then here you first unregister names that no longer exist and register new names.
registry/consul/backend.go
Outdated
if b.dereg != nil { | ||
b.dereg <- true // trigger deregistration | ||
<-b.dereg // wait for completion | ||
func (b *be) Deregister(serviceName string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function then deregisters all currently registered services.
registry/consul/backend.go
Outdated
@@ -100,6 +122,54 @@ func (b *be) WatchNoRouteHTML() chan string { | |||
return html | |||
} | |||
|
|||
func (b *be) UpdateAliases(config string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move the parsing code into the route/parse_new.go
since there you already have all the parse helpers. Return a list of alias names to register, e.g.
func ParseAliases(config string) (names []string, error) {...}
main.go
Outdated
@@ -396,6 +397,8 @@ func watchBackend(cfg *config.Config, first chan bool) { | |||
continue | |||
} | |||
|
|||
registry.Default.UpdateAliases(next) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then here you call
aliases, err := route.ParseAliases(config)
registry.Default.Register(aliases)
760a15e
to
4823267
Compare
Thanks @magiconair. I tried to address your feedback with these changes:
I had a couple of questions while working on this:
I see the Travis CI build failed, I'll look in to that. |
You may be able to register existing services and checks with Update: No, that does not have the intended effect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some more comments, some on style and some on dependencies. The Commands
const in https://github.com/fabiolb/fabio/blob/master/route/parse_new.go#L19-L58 needs to be updated to contain the new option.
Also, could you please update the docs? I've just noticed that I forgot to migrate https://github.com/fabiolb/fabio/wiki/Routing to the new website. I'll do that now and that's where the new option should go.
Update: added https://github.com/fabiolb/fabio/blob/master/docs/content/cfg/_index.md
registry/consul/backend.go
Outdated
b.dereg <- true // trigger deregistration | ||
<-b.dereg // wait for completion | ||
func (b *be) Deregister(serviceName string) error { | ||
if len(serviceName) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since DeregisterAll()
exists I wouldn't use a magic value ""
to deregister all services. Every now and then I am tempted to do that but then opt for simplicity. Deregister(service)
deregisters a service if it is currently registered, otherwise it does nothing. DeregisterAll()
deregisters all currently registered services.
registry/consul/backend.go
Outdated
// register new service names | ||
for _, serviceName := range services { | ||
if _, ok := b.dereg[serviceName]; ok { | ||
log.Printf("[DEBUG]: %q already registered (appears in dereg map)\n", serviceName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pls drop the text in (...)
since that is an implementation detail.
registry/consul/backend.go
Outdated
func (b *be) DeregisterAll() error { | ||
log.Printf("[DEBUG]: consul: Deregistering all registered Fabio aliases.") | ||
for name, dereg := range b.dereg { | ||
if dereg != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer less indents
for name, dereg := range b.dereg {
if dereg == nil {
continue
}
...
}
registry/consul/backend.go
Outdated
} | ||
|
||
// register new service names | ||
for _, serviceName := range services { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
less indents
for _, name := range services {
if b.dereg[name] == nil {
continue
}
...
}
registry/consul/register.go
Outdated
return "" | ||
} | ||
|
||
log.Printf("[INFO] consul: Registered fabio with name %q", service.Name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Registered fabio as %q
route/parse_new.go
Outdated
@@ -87,6 +90,42 @@ func Parse(in string) (defs []*RouteDef, err error) { | |||
return defs, nil | |||
} | |||
|
|||
func ParseAliases(in string, cfg *config.Config) (names []string, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pls add a comment on what this function does.
route/parse_new.go
Outdated
|
||
var aliases []string | ||
|
||
if cfg.Registry.Backend == "consul" && cfg.Registry.Consul.Register { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that important here? I'd just parse the aliases and let the backend decide what to do with them.
route/parse_new.go
Outdated
for _, d := range defs { | ||
registerName, ok := d.Opts["register"] | ||
if ok { | ||
log.Printf("[DEBUG]: consul: Service %q wants alias %q", d.Service, registerName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should log that here.
I think adding |
Ah, and please add some tests to https://github.com/fabiolb/fabio/blob/master/route/parse_test.go |
This patch adds a "register=<name>" 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, provided as the <name> argument to "register". Fabio will deregister front end services when the backend services leave, and will deregister all Fabio-registered services on exit.
Consul can automatically deregister services if the health check is critical for a given amount of time. This is useful if fabio exits abnormally without deregistering services.
4823267
to
9ece33a
Compare
@magiconair here is the latest version of the patch.
|
I think this is good enough as is. Thanks a lot! |
Great, thank you! |
We would like to have Fabio re-register itself in Consul under user-specified names, so that users can access their services through Fabio via Consul-provided A records. The motivation for this is:
The intended usage is that users will give their service a backend-specific name, and pass to Fabio the name they wish to use for the front end via a new "alias" option. For example:
Fabio then registers new service foo.service.example.com with its own host and port information and creates routes "foo.service.example.com/" and "foo/" to foo-backend.service.example.com as usual.