2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2017-06-15 16:46:06 +00:00
|
|
|
package structs
|
|
|
|
|
2018-05-04 21:10:03 +00:00
|
|
|
import (
|
2021-09-14 16:47:52 +00:00
|
|
|
"fmt"
|
|
|
|
|
2018-05-04 21:10:03 +00:00
|
|
|
"github.com/hashicorp/go-multierror"
|
2021-09-14 16:47:52 +00:00
|
|
|
|
2022-03-13 03:55:53 +00:00
|
|
|
"github.com/hashicorp/consul/acl"
|
2021-09-14 16:47:52 +00:00
|
|
|
"github.com/hashicorp/consul/lib"
|
2018-05-04 21:10:03 +00:00
|
|
|
)
|
|
|
|
|
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-06-21 15:17:17 +00:00
|
|
|
Kind ServiceKind `json:",omitempty"`
|
2017-06-15 16:46:06 +00:00
|
|
|
ID string
|
|
|
|
Name string
|
|
|
|
Tags []string
|
|
|
|
Address string
|
2019-06-17 14:51:50 +00:00
|
|
|
TaggedAddresses map[string]ServiceAddress
|
2018-03-28 14:04:50 +00:00
|
|
|
Meta map[string]string
|
2017-06-15 16:46:06 +00:00
|
|
|
Port int
|
2021-05-04 04:43:55 +00:00
|
|
|
SocketPath string
|
2017-06-15 16:46:06 +00:00
|
|
|
Check CheckType
|
|
|
|
Checks CheckTypes
|
2018-09-07 14:30:47 +00:00
|
|
|
Weights *Weights
|
2017-06-15 16:46:06 +00:00
|
|
|
Token string
|
|
|
|
EnableTagOverride bool
|
2023-03-10 14:36:15 +00:00
|
|
|
Locality *Locality
|
2018-09-12 16:07:47 +00:00
|
|
|
|
|
|
|
// Proxy is the configuration set for Kind = connect-proxy. It is mandatory in
|
|
|
|
// that case and an error to be set for any other kind. This config is part of
|
2019-08-09 19:19:30 +00:00
|
|
|
// a proxy service definition. ProxyConfig may be a more natural name here, but
|
|
|
|
// it's confusing for the UX because one of the fields in ConnectProxyConfig is
|
2018-09-12 16:07:47 +00:00
|
|
|
// also called just "Config"
|
|
|
|
Proxy *ConnectProxyConfig
|
|
|
|
|
2022-03-13 03:55:53 +00:00
|
|
|
acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
|
2019-12-10 02:26:41 +00:00
|
|
|
|
2018-09-12 16:07:47 +00:00
|
|
|
Connect *ServiceConnect
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 18:13:36 +00:00
|
|
|
func (t *ServiceDefinition) UnmarshalJSON(data []byte) (err error) {
|
|
|
|
type Alias ServiceDefinition
|
|
|
|
|
|
|
|
aux := &struct {
|
|
|
|
EnableTagOverrideSnake bool `json:"enable_tag_override"`
|
|
|
|
TaggedAddressesSnake map[string]ServiceAddress `json:"tagged_addresses"`
|
|
|
|
|
|
|
|
*Alias
|
|
|
|
}{
|
|
|
|
Alias: (*Alias)(t),
|
|
|
|
}
|
2019-12-06 16:14:56 +00:00
|
|
|
if err = lib.UnmarshalJSON(data, &aux); err != nil {
|
2019-10-29 18:13:36 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
if aux.EnableTagOverrideSnake {
|
|
|
|
t.EnableTagOverride = aux.EnableTagOverrideSnake
|
|
|
|
}
|
|
|
|
if len(t.TaggedAddresses) == 0 {
|
|
|
|
t.TaggedAddresses = aux.TaggedAddressesSnake
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
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,
|
2021-05-04 04:43:55 +00:00
|
|
|
SocketPath: s.SocketPath,
|
2018-09-07 14:30:47 +00:00
|
|
|
Weights: s.Weights,
|
2017-06-15 16:46:06 +00:00
|
|
|
EnableTagOverride: s.EnableTagOverride,
|
2019-12-10 02:26:41 +00:00
|
|
|
EnterpriseMeta: s.EnterpriseMeta,
|
2023-03-10 14:36:15 +00:00
|
|
|
Locality: s.Locality,
|
2017-06-15 16:46:06 +00:00
|
|
|
}
|
2020-02-06 15:52:25 +00:00
|
|
|
ns.EnterpriseMeta.Normalize()
|
|
|
|
|
2018-06-04 05:20:16 +00:00
|
|
|
if s.Connect != nil {
|
2018-06-05 17:51:05 +00:00
|
|
|
ns.Connect = *s.Connect
|
2018-06-04 05:20:16 +00:00
|
|
|
}
|
2018-09-12 16:07:47 +00:00
|
|
|
if s.Proxy != nil {
|
|
|
|
ns.Proxy = *s.Proxy
|
|
|
|
for i := range ns.Proxy.Upstreams {
|
2021-07-26 21:12:29 +00:00
|
|
|
// Ensure the Upstream type is defaulted
|
2018-09-12 16:07:47 +00:00
|
|
|
if ns.Proxy.Upstreams[i].DestinationType == "" {
|
|
|
|
ns.Proxy.Upstreams[i].DestinationType = UpstreamDestTypeService
|
|
|
|
}
|
2021-07-26 21:12:29 +00:00
|
|
|
|
2022-04-29 22:12:51 +00:00
|
|
|
// If a proxy's namespace and partition are not defined, inherit from the proxied service
|
2021-07-26 21:12:29 +00:00
|
|
|
// Applicable only to Consul Enterprise.
|
|
|
|
if ns.Proxy.Upstreams[i].DestinationNamespace == "" {
|
|
|
|
ns.Proxy.Upstreams[i].DestinationNamespace = ns.EnterpriseMeta.NamespaceOrEmpty()
|
|
|
|
}
|
2021-08-20 16:57:45 +00:00
|
|
|
if ns.Proxy.Upstreams[i].DestinationPartition == "" {
|
|
|
|
ns.Proxy.Upstreams[i].DestinationPartition = ns.EnterpriseMeta.PartitionOrEmpty()
|
|
|
|
}
|
2018-09-12 16:07:47 +00:00
|
|
|
}
|
2019-09-26 02:55:52 +00:00
|
|
|
ns.Proxy.Expose = s.Proxy.Expose
|
2018-09-12 16:07:47 +00:00
|
|
|
}
|
2017-06-15 16:46:06 +00:00
|
|
|
if ns.ID == "" && ns.Service != "" {
|
|
|
|
ns.ID = ns.Service
|
|
|
|
}
|
2019-06-17 14:51:50 +00:00
|
|
|
if len(s.TaggedAddresses) > 0 {
|
|
|
|
taggedAddrs := make(map[string]ServiceAddress)
|
|
|
|
for k, v := range s.TaggedAddresses {
|
|
|
|
taggedAddrs[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
ns.TaggedAddresses = taggedAddrs
|
|
|
|
}
|
2017-06-15 16:46:06 +00:00
|
|
|
return ns
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
|
// Validate the NodeService which covers a lot
|
|
|
|
if err := s.NodeService().Validate(); err != nil {
|
|
|
|
result = multierror.Append(result, err)
|
|
|
|
}
|
2021-09-14 16:47:52 +00:00
|
|
|
for _, c := range s.Checks {
|
|
|
|
if err := c.Validate(); err != nil {
|
|
|
|
return fmt.Errorf("check %q: %s", c.Name, err)
|
|
|
|
}
|
|
|
|
}
|
2018-05-04 21:10:03 +00:00
|
|
|
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
|
|
|
}
|