477 lines
13 KiB
Go
477 lines
13 KiB
Go
/*
|
|
Copyright 2021 The Dapr Authors
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package consul
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
consul "github.com/hashicorp/consul/api"
|
|
|
|
"github.com/dapr/kit/config"
|
|
)
|
|
|
|
// The intermediateConfig is based off of the consul api types. User configurations are
|
|
// deserialized into this type before being converted to the equivalent consul types
|
|
// that way breaking changes in future versions of the consul api cannot break user configuration.
|
|
type intermediateConfig struct {
|
|
Client *Config
|
|
Checks []*AgentServiceCheck
|
|
Tags []string
|
|
Meta map[string]string
|
|
QueryOptions *QueryOptions
|
|
AdvancedRegistration *AgentServiceRegistration // advanced use-case
|
|
SelfRegister bool
|
|
DaprPortMetaKey string
|
|
}
|
|
|
|
type configSpec struct {
|
|
Client *consul.Config
|
|
Checks []*consul.AgentServiceCheck
|
|
Tags []string
|
|
Meta map[string]string
|
|
QueryOptions *consul.QueryOptions
|
|
AdvancedRegistration *consul.AgentServiceRegistration // advanced use-case
|
|
SelfRegister bool
|
|
DaprPortMetaKey string
|
|
}
|
|
|
|
func parseConfig(rawConfig interface{}) (configSpec, error) {
|
|
var result configSpec
|
|
rawConfig, err := config.Normalize(rawConfig)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
|
|
data, err := json.Marshal(rawConfig)
|
|
if err != nil {
|
|
return result, fmt.Errorf("error serializing to json: %w", err)
|
|
}
|
|
|
|
decoder := json.NewDecoder(bytes.NewReader(data))
|
|
decoder.DisallowUnknownFields()
|
|
|
|
var configuration intermediateConfig
|
|
if err := decoder.Decode(&configuration); err != nil {
|
|
return result, fmt.Errorf("error deserializing to configSpec: %w", err)
|
|
}
|
|
|
|
result = mapConfig(configuration)
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func mapConfig(config intermediateConfig) configSpec {
|
|
return configSpec{
|
|
Client: mapClientConfig(config.Client),
|
|
Checks: mapChecks(config.Checks),
|
|
Tags: config.Tags,
|
|
Meta: config.Meta,
|
|
QueryOptions: mapQueryOptions(config.QueryOptions),
|
|
AdvancedRegistration: mapAdvancedRegistration(config.AdvancedRegistration),
|
|
SelfRegister: config.SelfRegister,
|
|
DaprPortMetaKey: config.DaprPortMetaKey,
|
|
}
|
|
}
|
|
|
|
func mapClientConfig(config *Config) *consul.Config {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
mapBasicAuth := func(config *HttpBasicAuth) *consul.HttpBasicAuth {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
return &consul.HttpBasicAuth{
|
|
Username: config.Username,
|
|
Password: config.Password,
|
|
}
|
|
}
|
|
|
|
return &consul.Config{
|
|
Address: config.Address,
|
|
Scheme: config.Scheme,
|
|
Datacenter: config.Datacenter,
|
|
HttpAuth: mapBasicAuth(config.HttpAuth),
|
|
WaitTime: config.WaitTime,
|
|
Token: config.Token,
|
|
TokenFile: config.TokenFile,
|
|
TLSConfig: consul.TLSConfig{
|
|
Address: config.TLSConfig.Address,
|
|
CAFile: config.TLSConfig.CAFile,
|
|
CAPath: config.TLSConfig.CAPath,
|
|
CertFile: config.TLSConfig.CertFile,
|
|
KeyFile: config.TLSConfig.KeyFile,
|
|
InsecureSkipVerify: config.TLSConfig.InsecureSkipVerify,
|
|
},
|
|
}
|
|
}
|
|
|
|
func mapChecks(config []*AgentServiceCheck) []*consul.AgentServiceCheck {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
mapped := []*consul.AgentServiceCheck{}
|
|
|
|
for i := 0; i < len(config); i++ {
|
|
mapped = append(mapped, mapCheck(config[i]))
|
|
}
|
|
|
|
return mapped
|
|
}
|
|
|
|
func mapCheck(config *AgentServiceCheck) *consul.AgentServiceCheck {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
return &consul.AgentServiceCheck{
|
|
CheckID: config.CheckID,
|
|
Name: config.Name,
|
|
Args: config.Args,
|
|
DockerContainerID: config.DockerContainerID,
|
|
Shell: config.Shell,
|
|
Interval: config.Interval,
|
|
Timeout: config.Timeout,
|
|
TTL: config.TTL,
|
|
HTTP: config.HTTP,
|
|
Header: config.Header,
|
|
Method: config.Method,
|
|
TCP: config.TCP,
|
|
Status: config.Status,
|
|
Notes: config.Notes,
|
|
TLSSkipVerify: config.TLSSkipVerify,
|
|
GRPC: config.GRPC,
|
|
GRPCUseTLS: config.GRPCUseTLS,
|
|
AliasNode: config.AliasNode,
|
|
AliasService: config.AliasService,
|
|
DeregisterCriticalServiceAfter: config.DeregisterCriticalServiceAfter,
|
|
}
|
|
}
|
|
|
|
func mapQueryOptions(config *QueryOptions) *consul.QueryOptions {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
return &consul.QueryOptions{
|
|
Datacenter: config.Datacenter,
|
|
AllowStale: config.AllowStale,
|
|
RequireConsistent: config.RequireConsistent,
|
|
UseCache: config.UseCache,
|
|
MaxAge: config.MaxAge,
|
|
StaleIfError: config.StaleIfError,
|
|
WaitIndex: config.WaitIndex,
|
|
WaitHash: config.WaitHash,
|
|
WaitTime: config.WaitTime,
|
|
Token: config.Token,
|
|
Near: config.Near,
|
|
NodeMeta: config.NodeMeta,
|
|
RelayFactor: config.RelayFactor,
|
|
LocalOnly: config.LocalOnly,
|
|
Connect: config.Connect,
|
|
Filter: config.Filter,
|
|
}
|
|
}
|
|
|
|
func mapAdvancedRegistration(config *AgentServiceRegistration) *consul.AgentServiceRegistration {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
mapExposeConfig := func(config ExposeConfig) consul.ExposeConfig {
|
|
mapped := consul.ExposeConfig{}
|
|
|
|
mapped.Checks = config.Checks
|
|
|
|
for i := 0; i < len(config.Paths); i++ {
|
|
tmp := consul.ExposePath{
|
|
ListenerPort: config.Paths[i].ListenerPort,
|
|
Path: config.Paths[i].Path,
|
|
LocalPathPort: config.Paths[i].LocalPathPort,
|
|
Protocol: config.Paths[i].Protocol,
|
|
ParsedFromCheck: config.Paths[i].ParsedFromCheck,
|
|
}
|
|
mapped.Paths = append(mapped.Paths, tmp)
|
|
}
|
|
|
|
return mapped
|
|
}
|
|
|
|
mapUpstreams := func(config []Upstream) []consul.Upstream {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
mapped := []consul.Upstream{}
|
|
|
|
for i := 0; i < len(config); i++ {
|
|
tmp := consul.Upstream{
|
|
DestinationType: consul.UpstreamDestType(config[i].DestinationType),
|
|
DestinationNamespace: config[i].DestinationNamespace,
|
|
DestinationName: config[i].DestinationName,
|
|
Datacenter: config[i].Datacenter,
|
|
LocalBindAddress: config[i].LocalBindAddress,
|
|
LocalBindPort: config[i].LocalBindPort,
|
|
Config: config[i].Config,
|
|
MeshGateway: consul.MeshGatewayConfig{Mode: consul.MeshGatewayMode(config[i].MeshGateway.Mode)},
|
|
}
|
|
mapped = append(mapped, tmp)
|
|
}
|
|
|
|
return mapped
|
|
}
|
|
|
|
mapProxy := func(config *AgentServiceConnectProxyConfig) *consul.AgentServiceConnectProxyConfig {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
return &consul.AgentServiceConnectProxyConfig{
|
|
DestinationServiceName: config.DestinationServiceName,
|
|
DestinationServiceID: config.DestinationServiceID,
|
|
LocalServiceAddress: config.LocalServiceAddress,
|
|
LocalServicePort: config.LocalServicePort,
|
|
Config: config.Config,
|
|
Upstreams: mapUpstreams(config.Upstreams),
|
|
MeshGateway: consul.MeshGatewayConfig{Mode: consul.MeshGatewayMode(config.MeshGateway.Mode)},
|
|
Expose: mapExposeConfig(config.Expose),
|
|
}
|
|
}
|
|
|
|
mapAgentServiceChecks := func(config AgentServiceChecks) consul.AgentServiceChecks {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
mapped := consul.AgentServiceChecks{}
|
|
|
|
for i := 0; i < len(config); i++ {
|
|
mapped = append(mapped, mapCheck(config[i]))
|
|
}
|
|
|
|
return mapped
|
|
}
|
|
|
|
mapTaggedAddresses := func(config map[string]ServiceAddress) map[string]consul.ServiceAddress {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
mapped := map[string]consul.ServiceAddress{}
|
|
for k, v := range config {
|
|
mapped[k] = consul.ServiceAddress{
|
|
Address: v.Address,
|
|
Port: v.Port,
|
|
}
|
|
}
|
|
|
|
return mapped
|
|
}
|
|
|
|
mapConnect := func(config *AgentServiceConnect) *consul.AgentServiceConnect {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
return &consul.AgentServiceConnect{
|
|
Native: config.Native,
|
|
SidecarService: mapAdvancedRegistration(config.SidecarService),
|
|
}
|
|
}
|
|
|
|
mapAgentWeights := func(config *AgentWeights) *consul.AgentWeights {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
return &consul.AgentWeights{
|
|
Passing: config.Passing,
|
|
Warning: config.Warning,
|
|
}
|
|
}
|
|
|
|
mapped := &consul.AgentServiceRegistration{
|
|
Kind: consul.ServiceKind(config.Kind),
|
|
ID: config.ID,
|
|
Name: config.Name,
|
|
Tags: config.Tags,
|
|
Port: config.Port,
|
|
Address: config.Address,
|
|
TaggedAddresses: mapTaggedAddresses(config.TaggedAddresses),
|
|
EnableTagOverride: config.EnableTagOverride,
|
|
Meta: config.Meta,
|
|
Weights: mapAgentWeights(config.Weights),
|
|
Check: mapCheck(config.Check),
|
|
Checks: mapAgentServiceChecks(config.Checks),
|
|
Proxy: mapProxy(config.Proxy),
|
|
Connect: mapConnect(config.Connect),
|
|
}
|
|
|
|
return mapped
|
|
}
|
|
|
|
//nolint:stylecheck
|
|
type HttpBasicAuth struct {
|
|
Username string
|
|
Password string
|
|
}
|
|
|
|
type Config struct {
|
|
Address string
|
|
Scheme string
|
|
Datacenter string
|
|
//nolint:stylecheck
|
|
HttpAuth *HttpBasicAuth
|
|
WaitTime time.Duration
|
|
Token string
|
|
TokenFile string
|
|
TLSConfig TLSConfig
|
|
}
|
|
|
|
type TLSConfig struct {
|
|
Address string
|
|
CAFile string
|
|
CAPath string
|
|
CertFile string
|
|
KeyFile string
|
|
InsecureSkipVerify bool
|
|
}
|
|
|
|
type AgentServiceCheck struct {
|
|
Args []string
|
|
CheckID string
|
|
Name string
|
|
DockerContainerID string
|
|
Shell string
|
|
Interval string
|
|
Timeout string
|
|
TTL string
|
|
HTTP string
|
|
Method string
|
|
TCP string
|
|
Status string
|
|
Notes string
|
|
GRPC string
|
|
AliasNode string
|
|
AliasService string
|
|
DeregisterCriticalServiceAfter string
|
|
Header map[string][]string
|
|
TLSSkipVerify bool
|
|
GRPCUseTLS bool
|
|
}
|
|
|
|
type QueryOptions struct {
|
|
Namespace string
|
|
Partition string
|
|
Datacenter string
|
|
WaitHash string
|
|
Token string
|
|
Near string
|
|
Filter string
|
|
MaxAge time.Duration
|
|
StaleIfError time.Duration
|
|
WaitIndex uint64
|
|
WaitTime time.Duration
|
|
NodeMeta map[string]string
|
|
AllowStale bool
|
|
RequireConsistent bool
|
|
UseCache bool
|
|
RelayFactor uint8
|
|
LocalOnly bool
|
|
Connect bool
|
|
}
|
|
|
|
type AgentServiceRegistration struct {
|
|
Kind string // original: type ServiceKind string
|
|
ID string
|
|
Name string
|
|
Tags []string
|
|
Port int
|
|
Address string
|
|
TaggedAddresses map[string]ServiceAddress
|
|
EnableTagOverride bool
|
|
Meta map[string]string
|
|
Weights *AgentWeights
|
|
Check *AgentServiceCheck
|
|
Checks AgentServiceChecks
|
|
Proxy *AgentServiceConnectProxyConfig
|
|
Connect *AgentServiceConnect
|
|
}
|
|
|
|
type AgentServiceChecks []*AgentServiceCheck
|
|
|
|
type ServiceAddress struct {
|
|
Address string
|
|
Port int
|
|
}
|
|
|
|
type AgentWeights struct {
|
|
Passing int
|
|
Warning int
|
|
}
|
|
|
|
type AgentServiceConnectProxyConfig struct {
|
|
DestinationServiceName string
|
|
DestinationServiceID string
|
|
LocalServiceAddress string
|
|
LocalServicePort int
|
|
Config map[string]interface{}
|
|
Upstreams []Upstream
|
|
MeshGateway MeshGatewayConfig
|
|
Expose ExposeConfig
|
|
}
|
|
|
|
type AgentServiceConnect struct {
|
|
Native bool
|
|
SidecarService *AgentServiceRegistration
|
|
}
|
|
|
|
type ExposeConfig struct {
|
|
Checks bool
|
|
Paths []ExposePath
|
|
}
|
|
|
|
type ExposePath struct {
|
|
ListenerPort int
|
|
Path string
|
|
LocalPathPort int
|
|
Protocol string
|
|
ParsedFromCheck bool
|
|
}
|
|
|
|
type MeshGatewayMode string
|
|
|
|
type MeshGatewayConfig struct {
|
|
Mode MeshGatewayMode
|
|
}
|
|
|
|
type UpstreamDestType string
|
|
|
|
type Upstream struct {
|
|
DestinationType UpstreamDestType
|
|
DestinationNamespace string
|
|
DestinationName string
|
|
Datacenter string
|
|
LocalBindAddress string
|
|
LocalBindPort int
|
|
Config map[string]interface{}
|
|
MeshGateway MeshGatewayConfig
|
|
}
|