mirror of https://github.com/hashicorp/consul
Add default resolvers to disco chains based on the default sameness group (#16837)
parent
8d40cf9858
commit
a6d69adcf5
|
@ -18,6 +18,7 @@ type DiscoveryChainSet struct {
|
||||||
Resolvers map[structs.ServiceID]*structs.ServiceResolverConfigEntry
|
Resolvers map[structs.ServiceID]*structs.ServiceResolverConfigEntry
|
||||||
Services map[structs.ServiceID]*structs.ServiceConfigEntry
|
Services map[structs.ServiceID]*structs.ServiceConfigEntry
|
||||||
Peers map[string]*pbpeering.Peering
|
Peers map[string]*pbpeering.Peering
|
||||||
|
DefaultSamenessGroup *structs.SamenessGroupConfigEntry
|
||||||
SamenessGroups map[string]*structs.SamenessGroupConfigEntry
|
SamenessGroups map[string]*structs.SamenessGroupConfigEntry
|
||||||
ProxyDefaults map[string]*structs.ProxyConfigEntry
|
ProxyDefaults map[string]*structs.ProxyConfigEntry
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,10 @@ func (e *DiscoveryChainSet) GetSamenessGroup(name string) *structs.SamenessGroup
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *DiscoveryChainSet) GetDefaultSamenessGroup() *structs.SamenessGroupConfigEntry {
|
||||||
|
return e.DefaultSamenessGroup
|
||||||
|
}
|
||||||
|
|
||||||
func (e *DiscoveryChainSet) GetProxyDefaults(partition string) *structs.ProxyConfigEntry {
|
func (e *DiscoveryChainSet) GetProxyDefaults(partition string) *structs.ProxyConfigEntry {
|
||||||
if e.ProxyDefaults != nil {
|
if e.ProxyDefaults != nil {
|
||||||
return e.ProxyDefaults[partition]
|
return e.ProxyDefaults[partition]
|
||||||
|
@ -116,9 +121,9 @@ func (e *DiscoveryChainSet) AddServices(entries ...*structs.ServiceConfigEntry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSamenessGroup adds service configs. Convenience function for testing.
|
// AddSamenessGroup adds a sameness group. Convenience function for testing.
|
||||||
func (e *DiscoveryChainSet) AddSamenessGroup(entries ...*structs.SamenessGroupConfigEntry) {
|
func (e *DiscoveryChainSet) AddSamenessGroup(entries ...*structs.SamenessGroupConfigEntry) {
|
||||||
if e.Services == nil {
|
if e.SamenessGroups == nil {
|
||||||
e.SamenessGroups = make(map[string]*structs.SamenessGroupConfigEntry)
|
e.SamenessGroups = make(map[string]*structs.SamenessGroupConfigEntry)
|
||||||
}
|
}
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
|
@ -126,6 +131,20 @@ func (e *DiscoveryChainSet) AddSamenessGroup(entries ...*structs.SamenessGroupCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDefaultSamenessGroup sets the default sameness group. Convenience function for testing.
|
||||||
|
func (e *DiscoveryChainSet) SetDefaultSamenessGroup(entry *structs.SamenessGroupConfigEntry) {
|
||||||
|
if e.SamenessGroups == nil {
|
||||||
|
e.SamenessGroups = make(map[string]*structs.SamenessGroupConfigEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.SamenessGroups[entry.Name] = entry
|
||||||
|
e.DefaultSamenessGroup = entry
|
||||||
|
}
|
||||||
|
|
||||||
// AddProxyDefaults adds proxy-defaults configs. Convenience function for testing.
|
// AddProxyDefaults adds proxy-defaults configs. Convenience function for testing.
|
||||||
func (e *DiscoveryChainSet) AddProxyDefaults(entries ...*structs.ProxyConfigEntry) {
|
func (e *DiscoveryChainSet) AddProxyDefaults(entries ...*structs.ProxyConfigEntry) {
|
||||||
if e.ProxyDefaults == nil {
|
if e.ProxyDefaults == nil {
|
||||||
|
@ -149,23 +168,26 @@ func (e *DiscoveryChainSet) AddPeers(entries ...*pbpeering.Peering) {
|
||||||
// AddEntries adds generic configs. Convenience function for testing. Panics on
|
// AddEntries adds generic configs. Convenience function for testing. Panics on
|
||||||
// operator error.
|
// operator error.
|
||||||
func (e *DiscoveryChainSet) AddEntries(entries ...structs.ConfigEntry) {
|
func (e *DiscoveryChainSet) AddEntries(entries ...structs.ConfigEntry) {
|
||||||
for _, entry := range entries {
|
for _, rawEntry := range entries {
|
||||||
switch entry.GetKind() {
|
switch entry := rawEntry.(type) {
|
||||||
case structs.ServiceRouter:
|
case *structs.ServiceRouterConfigEntry:
|
||||||
e.AddRouters(entry.(*structs.ServiceRouterConfigEntry))
|
e.AddRouters(entry)
|
||||||
case structs.ServiceSplitter:
|
case *structs.ServiceSplitterConfigEntry:
|
||||||
e.AddSplitters(entry.(*structs.ServiceSplitterConfigEntry))
|
e.AddSplitters(entry)
|
||||||
case structs.ServiceResolver:
|
case *structs.ServiceResolverConfigEntry:
|
||||||
e.AddResolvers(entry.(*structs.ServiceResolverConfigEntry))
|
e.AddResolvers(entry)
|
||||||
case structs.ServiceDefaults:
|
case *structs.ServiceConfigEntry:
|
||||||
e.AddServices(entry.(*structs.ServiceConfigEntry))
|
e.AddServices(entry)
|
||||||
case structs.SamenessGroup:
|
case *structs.SamenessGroupConfigEntry:
|
||||||
e.AddSamenessGroup(entry.(*structs.SamenessGroupConfigEntry))
|
if entry.DefaultForFailover {
|
||||||
case structs.ProxyDefaults:
|
e.DefaultSamenessGroup = entry
|
||||||
|
}
|
||||||
|
e.AddSamenessGroup(entry)
|
||||||
|
case *structs.ProxyConfigEntry:
|
||||||
if entry.GetName() != structs.ProxyConfigGlobal {
|
if entry.GetName() != structs.ProxyConfigGlobal {
|
||||||
panic("the only supported proxy-defaults name is '" + structs.ProxyConfigGlobal + "'")
|
panic("the only supported proxy-defaults name is '" + structs.ProxyConfigGlobal + "'")
|
||||||
}
|
}
|
||||||
e.AddProxyDefaults(entry.(*structs.ProxyConfigEntry))
|
e.AddProxyDefaults(entry)
|
||||||
default:
|
default:
|
||||||
panic("unhandled config entry kind: " + entry.GetKind())
|
panic("unhandled config entry kind: " + entry.GetKind())
|
||||||
}
|
}
|
||||||
|
@ -182,5 +204,5 @@ func (e *DiscoveryChainSet) IsEmpty() bool {
|
||||||
// service-splitters, or service-resolvers that are present. These config
|
// service-splitters, or service-resolvers that are present. These config
|
||||||
// entries are the primary parts of the discovery chain.
|
// entries are the primary parts of the discovery chain.
|
||||||
func (e *DiscoveryChainSet) IsChainEmpty() bool {
|
func (e *DiscoveryChainSet) IsChainEmpty() bool {
|
||||||
return len(e.Routers) == 0 && len(e.Splitters) == 0 && len(e.Resolvers) == 0
|
return len(e.Routers) == 0 && len(e.Splitters) == 0 && len(e.Resolvers) == 0 && e.DefaultSamenessGroup == nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -582,7 +582,7 @@ func (c *compiler) assembleChain() error {
|
||||||
// Check for short circuit path.
|
// Check for short circuit path.
|
||||||
if len(c.resolvers) == 0 && c.entries.IsChainEmpty() {
|
if len(c.resolvers) == 0 && c.entries.IsChainEmpty() {
|
||||||
// Materialize defaults and cache.
|
// Materialize defaults and cache.
|
||||||
c.resolvers[sid] = newDefaultServiceResolver(sid)
|
c.resolvers[sid] = c.newDefaultServiceResolver(sid, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// The only router we consult is the one for the service name at the top of
|
// The only router we consult is the one for the service name at the top of
|
||||||
|
@ -923,7 +923,7 @@ RESOLVE_AGAIN:
|
||||||
resolver, ok := c.resolvers[targetID]
|
resolver, ok := c.resolvers[targetID]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Materialize defaults and cache.
|
// Materialize defaults and cache.
|
||||||
resolver = newDefaultServiceResolver(targetID)
|
resolver = c.newDefaultServiceResolver(targetID, target.Peer)
|
||||||
c.resolvers[targetID] = resolver
|
c.resolvers[targetID] = resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,7 +1095,8 @@ RESOLVE_AGAIN:
|
||||||
}
|
}
|
||||||
|
|
||||||
if resolver.Redirect != nil && resolver.Redirect.SamenessGroup != "" {
|
if resolver.Redirect != nil && resolver.Redirect.SamenessGroup != "" {
|
||||||
opts := resolver.Redirect.ToDiscoveryTargetOpts()
|
opts := structs.MergeDiscoveryTargetOpts(resolver.ToSamenessDiscoveryTargetOpts(),
|
||||||
|
resolver.Redirect.ToDiscoveryTargetOpts())
|
||||||
failoverTargets, err = c.makeSamenessGroupFailover(target, opts, resolver.Redirect.SamenessGroup)
|
failoverTargets, err = c.makeSamenessGroupFailover(target, opts, resolver.Redirect.SamenessGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1138,7 +1139,9 @@ RESOLVE_AGAIN:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if failover.SamenessGroup != "" {
|
} else if failover.SamenessGroup != "" {
|
||||||
failoverTargets, err = c.makeSamenessGroupFailover(target, failover.ToDiscoveryTargetOpts(), failover.SamenessGroup)
|
opts := structs.MergeDiscoveryTargetOpts(resolver.ToSamenessDiscoveryTargetOpts(),
|
||||||
|
failover.ToDiscoveryTargetOpts())
|
||||||
|
failoverTargets, err = c.makeSamenessGroupFailover(target, opts, failover.SamenessGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1199,7 +1202,23 @@ func (c *compiler) makeSamenessGroupFailover(target *structs.DiscoveryTarget, op
|
||||||
return failoverTargets, nil
|
return failoverTargets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDefaultServiceResolver(sid structs.ServiceID) *structs.ServiceResolverConfigEntry {
|
func (c *compiler) newDefaultServiceResolver(sid structs.ServiceID, peer string) *structs.ServiceResolverConfigEntry {
|
||||||
|
sg := c.entries.GetDefaultSamenessGroup()
|
||||||
|
entMeta := c.GetEnterpriseMeta()
|
||||||
|
if sg != nil && peer == "" && (entMeta == nil || sid.PartitionOrDefault() == entMeta.PartitionOrDefault()) {
|
||||||
|
return &structs.ServiceResolverConfigEntry{
|
||||||
|
Kind: structs.ServiceResolver,
|
||||||
|
Name: sid.ID,
|
||||||
|
EnterpriseMeta: sid.EnterpriseMeta,
|
||||||
|
// This needs to be a redirect rather than failover because failovers
|
||||||
|
// implicitly include the local service. This isn't the behavior we want
|
||||||
|
// for services on sameness groups the local partition isn't a member of.
|
||||||
|
Redirect: &structs.ServiceResolverRedirect{
|
||||||
|
SamenessGroup: sg.Name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &structs.ServiceResolverConfigEntry{
|
return &structs.ServiceResolverConfigEntry{
|
||||||
Kind: structs.ServiceResolver,
|
Kind: structs.ServiceResolver,
|
||||||
Name: sid.ID,
|
Name: sid.ID,
|
||||||
|
|
|
@ -751,14 +751,70 @@ func validateProposedConfigEntryInServiceGraph(
|
||||||
|
|
||||||
case structs.SamenessGroup:
|
case structs.SamenessGroup:
|
||||||
// Any service resolver could reference a sameness group.
|
// Any service resolver could reference a sameness group.
|
||||||
_, entries, err := configEntriesByKindTxn(tx, nil, structs.ServiceResolver, wildcardEntMeta)
|
_, resolverEntries, err := configEntriesByKindTxn(tx, nil, structs.ServiceResolver, wildcardEntMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, entry := range entries {
|
for _, entry := range resolverEntries {
|
||||||
checkChains[structs.NewServiceID(entry.GetName(), entry.GetEnterpriseMeta())] = struct{}{}
|
checkChains[structs.NewServiceID(entry.GetName(), entry.GetEnterpriseMeta())] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the case for deleting a config entry
|
||||||
|
if newEntry == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := newEntry.(*structs.SamenessGroupConfigEntry)
|
||||||
|
|
||||||
|
_, samenessGroupEntries, err := configEntriesByKindTxn(tx, nil, structs.SamenessGroup, wildcardEntMeta)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the existing sameness group if one exists.
|
||||||
|
var exists bool
|
||||||
|
for i := range samenessGroupEntries {
|
||||||
|
sg := samenessGroupEntries[i]
|
||||||
|
if sg.GetName() == entry.Name {
|
||||||
|
samenessGroupEntries[i] = entry
|
||||||
|
exists = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this sameness group doesn't currently exist, add it.
|
||||||
|
if !exists {
|
||||||
|
samenessGroupEntries = append(samenessGroupEntries, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
existingPartitions := make(map[string]string)
|
||||||
|
existingPeers := make(map[string]string)
|
||||||
|
for _, e := range samenessGroupEntries {
|
||||||
|
sg, ok := e.(*structs.SamenessGroupConfigEntry)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("type %T is not a sameness group config entry", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range sg.AllMembers() {
|
||||||
|
if m.Peer != "" {
|
||||||
|
if prev, ok := existingPeers[m.Peer]; ok {
|
||||||
|
return fmt.Errorf("members can only belong to a single sameness group, but cluster peer %q is shared between groups %q and %q",
|
||||||
|
m.Peer, prev, sg.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
existingPeers[m.Peer] = sg.Name
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev, ok := existingPartitions[m.Partition]; ok {
|
||||||
|
return fmt.Errorf("members can only belong to a single sameness group, but partition %q is shared between groups %q and %q",
|
||||||
|
m.Partition, prev, sg.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
existingPartitions[m.Partition] = sg.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case structs.ProxyDefaults:
|
case structs.ProxyDefaults:
|
||||||
// Check anything that has a discovery chain entry. In the future we could
|
// Check anything that has a discovery chain entry. In the future we could
|
||||||
// somehow omit the ones that have a default protocol configured.
|
// somehow omit the ones that have a default protocol configured.
|
||||||
|
@ -1499,14 +1555,29 @@ func readDiscoveryChainConfigEntriesTxn(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, e := range entry.Members {
|
for _, peer := range entry.RelatedPeers() {
|
||||||
if e.Peer != "" {
|
todoPeers[peer] = struct{}{}
|
||||||
todoPeers[e.Peer] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res.SamenessGroups[sg] = entry
|
res.SamenessGroups[sg] = entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r := res.Resolvers[sid]; r == nil {
|
||||||
|
idx, sg, err := getDefaultSamenessGroup(tx, ws, sid.PartitionOrDefault())
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
if idx > maxIdx {
|
||||||
|
maxIdx = idx
|
||||||
|
}
|
||||||
|
if sg != nil {
|
||||||
|
res.DefaultSamenessGroup = sg
|
||||||
|
res.SamenessGroups[sg.Name] = sg
|
||||||
|
for _, peer := range sg.RelatedPeers() {
|
||||||
|
todoPeers[peer] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for peerName := range todoPeers {
|
for peerName := range todoPeers {
|
||||||
q := Query{
|
q := Query{
|
||||||
Value: peerName,
|
Value: peerName,
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SamnessGroupDefaultIndex is a placeholder for OSS. Sameness-groups are enterprise only.
|
// SamenessGroupDefaultIndex is a placeholder for OSS. Sameness-groups are enterprise only.
|
||||||
type SamenessGroupDefaultIndex struct{}
|
type SamenessGroupDefaultIndex struct{}
|
||||||
|
|
||||||
var _ memdb.Indexer = (*SamenessGroupDefaultIndex)(nil)
|
var _ memdb.Indexer = (*SamenessGroupDefaultIndex)(nil)
|
||||||
|
@ -47,3 +47,7 @@ func getSamenessGroupConfigEntryTxn(
|
||||||
) (uint64, *structs.SamenessGroupConfigEntry, error) {
|
) (uint64, *structs.SamenessGroupConfigEntry, error) {
|
||||||
return 0, nil, nil
|
return 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDefaultSamenessGroup(tx ReadTxn, ws memdb.WatchSet, partition string) (uint64, *structs.SamenessGroupConfigEntry, error) {
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ const (
|
||||||
indexLink = "link"
|
indexLink = "link"
|
||||||
indexIntentionLegacyID = "intention-legacy-id"
|
indexIntentionLegacyID = "intention-legacy-id"
|
||||||
indexSource = "intention-source"
|
indexSource = "intention-source"
|
||||||
indexSamenessGroupDefault = "sameness-group-default"
|
indexSamenessGroupDefault = "sameness-group-default-for-failover"
|
||||||
)
|
)
|
||||||
|
|
||||||
// configTableSchema returns a new table schema used to store global
|
// configTableSchema returns a new table schema used to store global
|
||||||
|
|
|
@ -61,7 +61,8 @@ func setupTestVariationConfigEntriesAndSnapshot(
|
||||||
}
|
}
|
||||||
dbChainID := structs.ChainID(dbOpts)
|
dbChainID := structs.ChainID(dbOpts)
|
||||||
makeChainID := func(opts structs.DiscoveryTargetOpts) string {
|
makeChainID := func(opts structs.DiscoveryTargetOpts) string {
|
||||||
return structs.ChainID(structs.MergeDiscoveryTargetOpts(dbOpts, opts))
|
finalOpts := structs.MergeDiscoveryTargetOpts(dbOpts, opts)
|
||||||
|
return structs.ChainID(finalOpts)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch variation {
|
switch variation {
|
||||||
|
|
|
@ -1367,6 +1367,16 @@ type ServiceResolverRedirect struct {
|
||||||
SamenessGroup string `json:",omitempty"`
|
SamenessGroup string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToSamenessDiscoveryTargetOpts returns the options required for sameness failover and redirects.
|
||||||
|
// These operations should preserve the service name and namespace.
|
||||||
|
func (r *ServiceResolverConfigEntry) ToSamenessDiscoveryTargetOpts() DiscoveryTargetOpts {
|
||||||
|
return DiscoveryTargetOpts{
|
||||||
|
Service: r.Name,
|
||||||
|
Namespace: r.NamespaceOrDefault(),
|
||||||
|
Partition: r.PartitionOrDefault(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ServiceResolverRedirect) ToDiscoveryTargetOpts() DiscoveryTargetOpts {
|
func (r *ServiceResolverRedirect) ToDiscoveryTargetOpts() DiscoveryTargetOpts {
|
||||||
return DiscoveryTargetOpts{
|
return DiscoveryTargetOpts{
|
||||||
Service: r.Service,
|
Service: r.Service,
|
||||||
|
|
|
@ -12,7 +12,8 @@ import (
|
||||||
|
|
||||||
type SamenessGroupConfigEntry struct {
|
type SamenessGroupConfigEntry struct {
|
||||||
Name string
|
Name string
|
||||||
IsDefault bool `json:",omitempty" alias:"is_default"`
|
DefaultForFailover bool `json:",omitempty" alias:"default_for_failover"`
|
||||||
|
IncludeLocal bool `json:",omitempty" alias:"include_local"`
|
||||||
Members []SamenessGroupMember
|
Members []SamenessGroupMember
|
||||||
Meta map[string]string `json:",omitempty"`
|
Meta map[string]string `json:",omitempty"`
|
||||||
acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
|
acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
|
||||||
|
@ -73,20 +74,3 @@ type SamenessGroupMember struct {
|
||||||
Partition string
|
Partition string
|
||||||
Peer string
|
Peer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SamenessGroupConfigEntry) ToFailoverTargets() []ServiceResolverFailoverTarget {
|
|
||||||
if s == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var targets []ServiceResolverFailoverTarget
|
|
||||||
|
|
||||||
for _, m := range s.Members {
|
|
||||||
targets = append(targets, ServiceResolverFailoverTarget{
|
|
||||||
Peer: m.Peer,
|
|
||||||
Partition: m.Partition,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return targets
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,3 +11,17 @@ import "fmt"
|
||||||
func (s *SamenessGroupConfigEntry) Validate() error {
|
func (s *SamenessGroupConfigEntry) Validate() error {
|
||||||
return fmt.Errorf("sameness-groups are an enterprise-only feature")
|
return fmt.Errorf("sameness-groups are an enterprise-only feature")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RelatedPeers returns all peers that are members of a sameness group config entry.
|
||||||
|
func (s *SamenessGroupConfigEntry) RelatedPeers() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllMembers adds the local partition to Members when it is set.
|
||||||
|
func (s *SamenessGroupConfigEntry) AllMembers() []SamenessGroupMember {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SamenessGroupConfigEntry) ToFailoverTargets() []ServiceResolverFailoverTarget {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -266,32 +266,37 @@ type DiscoveryTargetOpts struct {
|
||||||
Peer string
|
Peer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func MergeDiscoveryTargetOpts(o1 DiscoveryTargetOpts, o2 DiscoveryTargetOpts) DiscoveryTargetOpts {
|
func MergeDiscoveryTargetOpts(opts ...DiscoveryTargetOpts) DiscoveryTargetOpts {
|
||||||
if o2.Service != "" {
|
var final DiscoveryTargetOpts
|
||||||
o1.Service = o2.Service
|
for _, o := range opts {
|
||||||
|
if o.Service != "" {
|
||||||
|
final.Service = o.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
if o2.ServiceSubset != "" {
|
if o.ServiceSubset != "" {
|
||||||
o1.ServiceSubset = o2.ServiceSubset
|
final.ServiceSubset = o.ServiceSubset
|
||||||
}
|
}
|
||||||
|
|
||||||
if o2.Namespace != "" {
|
// default should override the existing value
|
||||||
o1.Namespace = o2.Namespace
|
if o.Namespace != "" {
|
||||||
|
final.Namespace = o.Namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
if o2.Partition != "" {
|
// default should override the existing value
|
||||||
o1.Partition = o2.Partition
|
if o.Partition != "" {
|
||||||
|
final.Partition = o.Partition
|
||||||
}
|
}
|
||||||
|
|
||||||
if o2.Datacenter != "" {
|
if o.Datacenter != "" {
|
||||||
o1.Datacenter = o2.Datacenter
|
final.Datacenter = o.Datacenter
|
||||||
}
|
}
|
||||||
|
|
||||||
if o2.Peer != "" {
|
if o.Peer != "" {
|
||||||
o1.Peer = o2.Peer
|
final.Peer = o.Peer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return o1
|
return final
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDiscoveryTarget(opts DiscoveryTargetOpts) *DiscoveryTarget {
|
func NewDiscoveryTarget(opts DiscoveryTargetOpts) *DiscoveryTarget {
|
||||||
|
|
|
@ -7,7 +7,8 @@ type SamenessGroupConfigEntry struct {
|
||||||
Kind string
|
Kind string
|
||||||
Name string
|
Name string
|
||||||
Partition string `json:",omitempty"`
|
Partition string `json:",omitempty"`
|
||||||
IsDefault bool `json:",omitempty" alias:"is_default"`
|
DefaultForFailover bool `json:",omitempty" alias:"default_for_failover"`
|
||||||
|
IncludeLocal bool `json:",omitempty" alias:"include_local"`
|
||||||
Members []SamenessGroupMember
|
Members []SamenessGroupMember
|
||||||
Meta map[string]string `json:",omitempty"`
|
Meta map[string]string `json:",omitempty"`
|
||||||
CreateIndex uint64
|
CreateIndex uint64
|
Loading…
Reference in New Issue