1
// Copyright (c) 2016-2019 Uber Technologies, Inc.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
17
"github.com/uber/kraken/lib/hashring"
18
"github.com/uber/kraken/lib/healthcheck"
19
"github.com/uber/kraken/lib/hostlist"
20
"github.com/uber/kraken/utils/log"
22
"github.com/andres-erbsen/clock"
25
// ActiveConfig composes host configuration for an upstream service with an
26
// active health check.
27
type ActiveConfig struct {
28
Hosts hostlist.Config `yaml:"hosts"`
29
HealthCheck ActiveHealthCheckConfig `yaml:"healthcheck"`
31
checker healthcheck.Checker
34
// ActiveHealthCheckConfig wraps health check configuration.
35
type ActiveHealthCheckConfig struct {
36
Filter healthcheck.FilterConfig `yaml:"filter"`
37
Monitor healthcheck.MonitorConfig `yaml:"monitor"`
38
Disabled bool `yaml:"disabled"`
41
// ActiveOption allows setting optional ActiveConfig parameters.
42
type ActiveOption func(*ActiveConfig)
44
// WithHealthCheck configures ActiveConfig with a custom health check.
45
func WithHealthCheck(checker healthcheck.Checker) ActiveOption {
46
return func(c *ActiveConfig) { c.checker = checker }
49
// Build creates a healthcheck.List with built-in active health checks.
50
func (c ActiveConfig) Build(opts ...ActiveOption) (healthcheck.List, error) {
51
hosts, err := hostlist.New(c.Hosts)
55
if c.HealthCheck.Disabled {
56
log.With("hosts", c.Hosts).Warn("Health checks disabled")
57
return healthcheck.NoopFailed(hosts), nil
59
c.checker = healthcheck.Default(nil)
60
for _, opt := range opts {
63
filter := healthcheck.NewFilter(c.HealthCheck.Filter, c.checker)
64
monitor := healthcheck.NewMonitor(c.HealthCheck.Monitor, hosts, filter)
65
return healthcheck.NoopFailed(monitor), nil
68
// StableAddr returns a stable address that can be advertised as the address
69
// for this service. If c is backed by DNS, returns the DNS record. If c is
70
// backed by a static list, returns a random address.
71
func (c ActiveConfig) StableAddr() (string, error) {
72
if c.Hosts.DNS != "" {
73
return c.Hosts.DNS, nil
75
hosts, err := hostlist.New(c.Hosts)
79
addr, err := hosts.Resolve().Random()
81
panic("invariant violation: " + err.Error())
86
// PassiveConfig composes host configuruation for an upstream service with a
87
// passive health check.
88
type PassiveConfig struct {
89
Hosts hostlist.Config `yaml:"hosts"`
90
HealthCheck healthcheck.PassiveFilterConfig `yaml:"healthcheck"`
93
// Build creates healthcheck.List enabled with passive health checks.
94
func (c PassiveConfig) Build() (healthcheck.List, error) {
95
hosts, err := hostlist.New(c.Hosts)
99
f := healthcheck.NewPassiveFilter(c.HealthCheck, clock.New())
100
return healthcheck.NewPassive(hosts, f), nil
103
// PassiveRingConfig composes host configuration for an upstream service with
104
// a passively health checked hash ring.
105
type PassiveHashRingConfig struct {
106
Hosts hostlist.Config `yaml:"hosts"`
107
HealthCheck healthcheck.PassiveFilterConfig `yaml:"healthcheck"`
108
HashRing hashring.Config `yaml:"hashring"`
111
// Build creates a hashring.PassiveRing.
112
func (c PassiveHashRingConfig) Build() (hashring.PassiveRing, error) {
113
hosts, err := hostlist.New(c.Hosts)
117
f := healthcheck.NewPassiveFilter(c.HealthCheck, clock.New())
118
return hashring.NewPassive(c.HashRing, hosts, f), nil