2017-06-15 16:46:06 +00:00
|
|
|
package structs
|
|
|
|
|
2018-05-04 21:10:03 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
|
|
)
|
|
|
|
|
2018-03-12 17:13:44 +00:00
|
|
|
// ServiceDefinition is used to JSON decode the Service definitions. For
|
|
|
|
// documentation on specific fields see NodeService which is better documented.
|
2017-06-15 16:46:06 +00:00
|
|
|
type ServiceDefinition struct {
|
2018-03-10 01:16:12 +00:00
|
|
|
Kind ServiceKind
|
2017-06-15 16:46:06 +00:00
|
|
|
ID string
|
|
|
|
Name string
|
|
|
|
Tags []string
|
|
|
|
Address string
|
2018-03-28 14:04:50 +00:00
|
|
|
Meta map[string]string
|
2017-06-15 16:46:06 +00:00
|
|
|
Port int
|
|
|
|
Check CheckType
|
|
|
|
Checks CheckTypes
|
|
|
|
Token string
|
|
|
|
EnableTagOverride bool
|
2018-03-10 01:16:12 +00:00
|
|
|
ProxyDestination string
|
2018-04-17 12:29:02 +00:00
|
|
|
Connect *ServiceDefinitionConnect
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ServiceDefinition) NodeService() *NodeService {
|
|
|
|
ns := &NodeService{
|
2018-03-10 01:16:12 +00:00
|
|
|
Kind: s.Kind,
|
2017-06-15 16:46:06 +00:00
|
|
|
ID: s.ID,
|
|
|
|
Service: s.Name,
|
|
|
|
Tags: s.Tags,
|
|
|
|
Address: s.Address,
|
2018-03-28 14:04:50 +00:00
|
|
|
Meta: s.Meta,
|
2017-06-15 16:46:06 +00:00
|
|
|
Port: s.Port,
|
|
|
|
EnableTagOverride: s.EnableTagOverride,
|
2018-03-10 01:16:12 +00:00
|
|
|
ProxyDestination: s.ProxyDestination,
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
2018-06-04 05:20:16 +00:00
|
|
|
if s.Connect != nil {
|
|
|
|
ns.ConnectNative = s.Connect.Native
|
|
|
|
}
|
2017-06-15 16:46:06 +00:00
|
|
|
if ns.ID == "" && ns.Service != "" {
|
|
|
|
ns.ID = ns.Service
|
|
|
|
}
|
|
|
|
return ns
|
|
|
|
}
|
|
|
|
|
2018-04-17 12:29:02 +00:00
|
|
|
// ConnectManagedProxy returns a ConnectManagedProxy from the ServiceDefinition
|
|
|
|
// if one is configured validly. Note that is may return nil if no proxy is
|
|
|
|
// configured and will also return nil error in this case too as it's an
|
|
|
|
// expected case. The error returned indicates that there was an attempt to
|
|
|
|
// configure a proxy made but that it was invalid input, e.g. invalid
|
|
|
|
// "exec_mode".
|
|
|
|
func (s *ServiceDefinition) ConnectManagedProxy() (*ConnectManagedProxy, error) {
|
|
|
|
if s.Connect == nil || s.Connect.Proxy == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeService performs some simple normalization like copying ID from Name
|
|
|
|
// which we shouldn't hard code ourselves here...
|
|
|
|
ns := s.NodeService()
|
|
|
|
|
2018-05-03 17:44:10 +00:00
|
|
|
execMode, err := NewProxyExecMode(s.Connect.Proxy.ExecMode)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2018-04-17 12:29:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p := &ConnectManagedProxy{
|
|
|
|
ExecMode: execMode,
|
|
|
|
Command: s.Connect.Proxy.Command,
|
|
|
|
Config: s.Connect.Proxy.Config,
|
|
|
|
// ProxyService will be setup when the agent registers the configured
|
|
|
|
// proxies and starts them etc.
|
|
|
|
TargetServiceID: ns.ID,
|
|
|
|
}
|
|
|
|
|
|
|
|
return p, nil
|
|
|
|
}
|
|
|
|
|
2018-05-04 21:10:03 +00:00
|
|
|
// Validate validates the service definition. This also calls the underlying
|
|
|
|
// Validate method on the NodeService.
|
|
|
|
//
|
|
|
|
// NOTE(mitchellh): This currently only validates fields related to Connect
|
|
|
|
// and is incomplete with regards to other fields.
|
|
|
|
func (s *ServiceDefinition) Validate() error {
|
|
|
|
var result error
|
|
|
|
|
|
|
|
if s.Kind == ServiceKindTypical {
|
2018-06-04 05:20:16 +00:00
|
|
|
if s.Connect != nil {
|
|
|
|
if s.Connect.Proxy != nil {
|
|
|
|
if s.Connect.Native {
|
|
|
|
result = multierror.Append(result, fmt.Errorf(
|
|
|
|
"Services that are Connect native may not have a proxy configuration"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.Port == 0 {
|
|
|
|
result = multierror.Append(result, fmt.Errorf(
|
|
|
|
"Services with a Connect managed proxy must have a port set"))
|
|
|
|
}
|
2018-05-04 21:10:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate the NodeService which covers a lot
|
|
|
|
if err := s.NodeService().Validate(); err != nil {
|
|
|
|
result = multierror.Append(result, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:54:06 +00:00
|
|
|
func (s *ServiceDefinition) CheckTypes() (checks CheckTypes, err error) {
|
|
|
|
if !s.Check.Empty() {
|
|
|
|
err := s.Check.Validate()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
checks = append(checks, &s.Check)
|
|
|
|
}
|
2017-06-15 16:46:06 +00:00
|
|
|
for _, check := range s.Checks {
|
2017-10-10 23:54:06 +00:00
|
|
|
if err := check.Validate(); err != nil {
|
|
|
|
return nil, err
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
2017-10-10 23:54:06 +00:00
|
|
|
checks = append(checks, check)
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
2017-10-10 23:54:06 +00:00
|
|
|
return checks, nil
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
2018-04-17 12:29:02 +00:00
|
|
|
|
|
|
|
// ServiceDefinitionConnect is the connect block within a service registration.
|
|
|
|
// Note this is duplicated in config.ServiceConnect and needs to be kept in
|
|
|
|
// sync.
|
|
|
|
type ServiceDefinitionConnect struct {
|
2018-06-04 05:20:16 +00:00
|
|
|
// Native is true when this service can natively understand Connect.
|
|
|
|
Native bool
|
|
|
|
|
2018-04-17 12:29:02 +00:00
|
|
|
// Proxy configures a connect proxy instance for the service
|
2018-04-20 13:24:24 +00:00
|
|
|
Proxy *ServiceDefinitionConnectProxy
|
2018-04-17 12:29:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ServiceDefinitionConnectProxy is the connect proxy config within a service
|
|
|
|
// registration. Note this is duplicated in config.ServiceConnectProxy and needs
|
|
|
|
// to be kept in sync.
|
|
|
|
type ServiceDefinitionConnectProxy struct {
|
2018-04-27 05:16:21 +00:00
|
|
|
Command []string
|
2018-04-20 13:24:24 +00:00
|
|
|
ExecMode string
|
|
|
|
Config map[string]interface{}
|
2018-04-17 12:29:02 +00:00
|
|
|
}
|