mirror of https://github.com/status-im/consul.git
Add sameness-group to exported-services config entries (#16836)
This PR adds the sameness-group field to exported-service config entries, which allows for services to be exported to multiple destination partitions / peers easily.
This commit is contained in:
parent
bf64a33caa
commit
8d40cf9858
|
@ -730,7 +730,9 @@ func validateProposedConfigEntryInServiceGraph(
|
||||||
|
|
||||||
entry := newEntry.(*structs.ExportedServicesConfigEntry)
|
entry := newEntry.(*structs.ExportedServicesConfigEntry)
|
||||||
|
|
||||||
_, serviceList, err := listServicesExportedToAnyPeerByConfigEntry(nil, tx, entry, nil)
|
_, serviceList, err := listServicesExportedToAnyPeerByConfigEntry(nil, tx, entry.EnterpriseMeta, map[configentry.KindName]structs.ConfigEntry{
|
||||||
|
configentry.NewKindNameForEntry(entry): entry,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1486,7 +1488,7 @@ func readDiscoveryChainConfigEntriesTxn(
|
||||||
|
|
||||||
peerEntMeta := structs.DefaultEnterpriseMetaInPartition(entMeta.PartitionOrDefault())
|
peerEntMeta := structs.DefaultEnterpriseMetaInPartition(entMeta.PartitionOrDefault())
|
||||||
for sg := range todoSamenessGroups {
|
for sg := range todoSamenessGroups {
|
||||||
idx, entry, err := getSamenessGroupConfigEntryTxn(tx, ws, sg, overrides, peerEntMeta)
|
idx, entry, err := getSamenessGroupConfigEntryTxn(tx, ws, sg, overrides, peerEntMeta.PartitionOrDefault())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1720,32 +1722,6 @@ func getServiceIntentionsConfigEntryTxn(
|
||||||
return idx, ixn, nil
|
return idx, ixn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getExportedServicesConfigEntryTxn is a convenience method for fetching a
|
|
||||||
// exported-services kind of config entry.
|
|
||||||
//
|
|
||||||
// If an override KEY is present for the requested config entry, the index
|
|
||||||
// returned will be 0. Any override VALUE (nil or otherwise) will be returned
|
|
||||||
// if there is a KEY match.
|
|
||||||
func getExportedServicesConfigEntryTxn(
|
|
||||||
tx ReadTxn,
|
|
||||||
ws memdb.WatchSet,
|
|
||||||
overrides map[configentry.KindName]structs.ConfigEntry,
|
|
||||||
entMeta *acl.EnterpriseMeta,
|
|
||||||
) (uint64, *structs.ExportedServicesConfigEntry, error) {
|
|
||||||
idx, entry, err := configEntryWithOverridesTxn(tx, ws, structs.ExportedServices, entMeta.PartitionOrDefault(), overrides, entMeta)
|
|
||||||
if err != nil {
|
|
||||||
return 0, nil, err
|
|
||||||
} else if entry == nil {
|
|
||||||
return idx, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
export, ok := entry.(*structs.ExportedServicesConfigEntry)
|
|
||||||
if !ok {
|
|
||||||
return 0, nil, fmt.Errorf("invalid service config type %T", entry)
|
|
||||||
}
|
|
||||||
return idx, export, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func configEntryWithOverridesTxn(
|
func configEntryWithOverridesTxn(
|
||||||
tx ReadTxn,
|
tx ReadTxn,
|
||||||
ws memdb.WatchSet,
|
ws memdb.WatchSet,
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/acl"
|
||||||
|
"github.com/hashicorp/consul/agent/configentry"
|
||||||
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/hashicorp/go-memdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SimplifiedExportedServices contains a version of the exported-services that has
|
||||||
|
// been flattened by removing all of the sameness group references and replacing
|
||||||
|
// them with corresponding partition / peer entries.
|
||||||
|
type SimplifiedExportedServices structs.ExportedServicesConfigEntry
|
||||||
|
|
||||||
|
// ToPartitionMap is only used by the partition exporting logic.
|
||||||
|
// It returns a map[namespace][service] => []consuming_partitions
|
||||||
|
func (e *SimplifiedExportedServices) ToPartitionMap() map[string]map[string][]string {
|
||||||
|
resp := make(map[string]map[string][]string)
|
||||||
|
for _, svc := range e.Services {
|
||||||
|
if _, ok := resp[svc.Namespace]; !ok {
|
||||||
|
resp[svc.Namespace] = make(map[string][]string)
|
||||||
|
}
|
||||||
|
if _, ok := resp[svc.Namespace][svc.Name]; !ok {
|
||||||
|
consumers := make([]string, 0, len(svc.Consumers))
|
||||||
|
for _, c := range svc.Consumers {
|
||||||
|
if c.Partition != "" {
|
||||||
|
consumers = append(consumers, c.Partition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp[svc.Namespace][svc.Name] = consumers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// getExportedServicesConfigEntryTxn is a convenience method for fetching a
|
||||||
|
// exported-services kind of config entry.
|
||||||
|
//
|
||||||
|
// If an override KEY is present for the requested config entry, the index
|
||||||
|
// returned will be 0. Any override VALUE (nil or otherwise) will be returned
|
||||||
|
// if there is a KEY match.
|
||||||
|
func getExportedServicesConfigEntryTxn(
|
||||||
|
tx ReadTxn,
|
||||||
|
ws memdb.WatchSet,
|
||||||
|
overrides map[configentry.KindName]structs.ConfigEntry,
|
||||||
|
entMeta *acl.EnterpriseMeta,
|
||||||
|
) (uint64, *structs.ExportedServicesConfigEntry, error) {
|
||||||
|
idx, entry, err := configEntryWithOverridesTxn(tx, ws, structs.ExportedServices, entMeta.PartitionOrDefault(), overrides, entMeta)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
} else if entry == nil {
|
||||||
|
return idx, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
export, ok := entry.(*structs.ExportedServicesConfigEntry)
|
||||||
|
if !ok {
|
||||||
|
return 0, nil, fmt.Errorf("invalid service config type %T", entry)
|
||||||
|
}
|
||||||
|
return idx, export, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
//go:build !consulent
|
||||||
|
// +build !consulent
|
||||||
|
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/consul/acl"
|
||||||
|
"github.com/hashicorp/consul/agent/configentry"
|
||||||
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/hashicorp/go-memdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getSimplifiedExportedServices(
|
||||||
|
tx ReadTxn,
|
||||||
|
ws memdb.WatchSet,
|
||||||
|
overrides map[configentry.KindName]structs.ConfigEntry,
|
||||||
|
entMeta acl.EnterpriseMeta,
|
||||||
|
) (uint64, *SimplifiedExportedServices, error) {
|
||||||
|
idx, exports, err := getExportedServicesConfigEntryTxn(tx, ws, overrides, &entMeta)
|
||||||
|
if exports == nil {
|
||||||
|
return idx, nil, err
|
||||||
|
}
|
||||||
|
simple := SimplifiedExportedServices(*exports)
|
||||||
|
return idx, &simple, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetSimplifiedExportedServices(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, *SimplifiedExportedServices, error) {
|
||||||
|
tx := s.db.Txn(false)
|
||||||
|
defer tx.Abort()
|
||||||
|
return getSimplifiedExportedServices(tx, ws, nil, entMeta)
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ package state
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/configentry"
|
"github.com/hashicorp/consul/agent/configentry"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
|
@ -44,7 +43,7 @@ func getSamenessGroupConfigEntryTxn(
|
||||||
ws memdb.WatchSet,
|
ws memdb.WatchSet,
|
||||||
name string,
|
name string,
|
||||||
overrides map[configentry.KindName]structs.ConfigEntry,
|
overrides map[configentry.KindName]structs.ConfigEntry,
|
||||||
entMeta *acl.EnterpriseMeta,
|
partition string,
|
||||||
) (uint64, *structs.SamenessGroupConfigEntry, error) {
|
) (uint64, *structs.SamenessGroupConfigEntry, error) {
|
||||||
return 0, nil, nil
|
return 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -774,9 +774,9 @@ func exportedServicesForPeerTxn(
|
||||||
maxIdx := peering.ModifyIndex
|
maxIdx := peering.ModifyIndex
|
||||||
|
|
||||||
entMeta := structs.NodeEnterpriseMetaInPartition(peering.Partition)
|
entMeta := structs.NodeEnterpriseMetaInPartition(peering.Partition)
|
||||||
idx, exportConf, err := getExportedServicesConfigEntryTxn(tx, ws, nil, entMeta)
|
idx, exportConf, err := getSimplifiedExportedServices(tx, ws, nil, *entMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("failed to fetch exported-services config entry: %w", err)
|
return 0, nil, fmt.Errorf("failed to fetch simplified exported-services config entry: %w", err)
|
||||||
}
|
}
|
||||||
if idx > maxIdx {
|
if idx > maxIdx {
|
||||||
maxIdx = idx
|
maxIdx = idx
|
||||||
|
@ -1019,17 +1019,8 @@ func listAllExportedServices(
|
||||||
overrides map[configentry.KindName]structs.ConfigEntry,
|
overrides map[configentry.KindName]structs.ConfigEntry,
|
||||||
entMeta acl.EnterpriseMeta,
|
entMeta acl.EnterpriseMeta,
|
||||||
) (uint64, map[structs.ServiceName]struct{}, error) {
|
) (uint64, map[structs.ServiceName]struct{}, error) {
|
||||||
idx, export, err := getExportedServicesConfigEntryTxn(tx, ws, overrides, &entMeta)
|
|
||||||
if err != nil {
|
|
||||||
return 0, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
found := make(map[structs.ServiceName]struct{})
|
found := make(map[structs.ServiceName]struct{})
|
||||||
if export == nil {
|
idx, services, err := listServicesExportedToAnyPeerByConfigEntry(ws, tx, entMeta, overrides)
|
||||||
return idx, found, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, services, err := listServicesExportedToAnyPeerByConfigEntry(ws, tx, export, overrides)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1044,16 +1035,25 @@ func listAllExportedServices(
|
||||||
func listServicesExportedToAnyPeerByConfigEntry(
|
func listServicesExportedToAnyPeerByConfigEntry(
|
||||||
ws memdb.WatchSet,
|
ws memdb.WatchSet,
|
||||||
tx ReadTxn,
|
tx ReadTxn,
|
||||||
conf *structs.ExportedServicesConfigEntry,
|
entMeta acl.EnterpriseMeta,
|
||||||
overrides map[configentry.KindName]structs.ConfigEntry,
|
overrides map[configentry.KindName]structs.ConfigEntry,
|
||||||
) (uint64, []structs.ServiceName, error) {
|
) (uint64, []structs.ServiceName, error) {
|
||||||
var (
|
var (
|
||||||
entMeta = conf.GetEnterpriseMeta()
|
|
||||||
found = make(map[structs.ServiceName]struct{})
|
found = make(map[structs.ServiceName]struct{})
|
||||||
maxIdx uint64
|
maxIdx uint64
|
||||||
)
|
)
|
||||||
|
idx, exports, err := getSimplifiedExportedServices(tx, ws, overrides, entMeta)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
if idx > maxIdx {
|
||||||
|
maxIdx = idx
|
||||||
|
}
|
||||||
|
if exports == nil {
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
for _, svc := range conf.Services {
|
for _, svc := range exports.Services {
|
||||||
svcMeta := acl.NewEnterpriseMetaWithPartition(entMeta.PartitionOrDefault(), svc.Namespace)
|
svcMeta := acl.NewEnterpriseMetaWithPartition(entMeta.PartitionOrDefault(), svc.Namespace)
|
||||||
|
|
||||||
sawPeer := false
|
sawPeer := false
|
||||||
|
@ -1412,17 +1412,12 @@ func peersForServiceTxn(
|
||||||
// Exported service config entries are scoped to partitions so they are in the default namespace.
|
// Exported service config entries are scoped to partitions so they are in the default namespace.
|
||||||
partitionMeta := structs.DefaultEnterpriseMetaInPartition(entMeta.PartitionOrDefault())
|
partitionMeta := structs.DefaultEnterpriseMetaInPartition(entMeta.PartitionOrDefault())
|
||||||
|
|
||||||
idx, rawEntry, err := configEntryTxn(tx, ws, structs.ExportedServices, partitionMeta.PartitionOrDefault(), partitionMeta)
|
idx, exportedServices, err := getSimplifiedExportedServices(tx, ws, nil, *partitionMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
if rawEntry == nil {
|
if exportedServices == nil {
|
||||||
return idx, nil, err
|
return idx, nil, nil
|
||||||
}
|
|
||||||
|
|
||||||
entry, ok := rawEntry.(*structs.ExportedServicesConfigEntry)
|
|
||||||
if !ok {
|
|
||||||
return 0, nil, fmt.Errorf("unexpected type %T for pbpeering.Peering index", rawEntry)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -1442,7 +1437,7 @@ func peersForServiceTxn(
|
||||||
// Namespace: *, Service: *
|
// Namespace: *, Service: *
|
||||||
// Namespace: Exact, Service: *
|
// Namespace: Exact, Service: *
|
||||||
// Namespace: Exact, Service: Exact
|
// Namespace: Exact, Service: Exact
|
||||||
for i, service := range entry.Services {
|
for i, service := range exportedServices.Services {
|
||||||
switch {
|
switch {
|
||||||
case service.Namespace == structs.WildcardSpecifier:
|
case service.Namespace == structs.WildcardSpecifier:
|
||||||
wildcardNamespaceIdx = i
|
wildcardNamespaceIdx = i
|
||||||
|
@ -1473,7 +1468,7 @@ func peersForServiceTxn(
|
||||||
return idx, results, nil
|
return idx, results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range entry.Services[targetIdx].Consumers {
|
for _, c := range exportedServices.Services[targetIdx].Consumers {
|
||||||
if c.Peer != "" {
|
if c.Peer != "" {
|
||||||
results = append(results, c.Peer)
|
results = append(results, c.Peer)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,43 +41,13 @@ type ExportedService struct {
|
||||||
// At most one of Partition or Peer must be specified.
|
// At most one of Partition or Peer must be specified.
|
||||||
type ServiceConsumer struct {
|
type ServiceConsumer struct {
|
||||||
// Partition is the admin partition to export the service to.
|
// Partition is the admin partition to export the service to.
|
||||||
// Deprecated: Peer should be used for both remote peers and local partitions.
|
|
||||||
Partition string `json:",omitempty"`
|
Partition string `json:",omitempty"`
|
||||||
|
|
||||||
// Peer is the name of the peer to export the service to.
|
// Peer is the name of the peer to export the service to.
|
||||||
Peer string `json:",omitempty" alias:"peer_name"`
|
Peer string `json:",omitempty" alias:"peer_name"`
|
||||||
}
|
|
||||||
|
|
||||||
func (e *ExportedServicesConfigEntry) ToMap() map[string]map[string][]string {
|
// SamenessGroup is the name of the sameness group to export the service to.
|
||||||
resp := make(map[string]map[string][]string)
|
SamenessGroup string `json:",omitempty" alias:"sameness_group"`
|
||||||
for _, svc := range e.Services {
|
|
||||||
if _, ok := resp[svc.Namespace]; !ok {
|
|
||||||
resp[svc.Namespace] = make(map[string][]string)
|
|
||||||
}
|
|
||||||
if _, ok := resp[svc.Namespace][svc.Name]; !ok {
|
|
||||||
consumers := make([]string, 0, len(svc.Consumers))
|
|
||||||
for _, c := range svc.Consumers {
|
|
||||||
consumers = append(consumers, c.Partition)
|
|
||||||
}
|
|
||||||
resp[svc.Namespace][svc.Name] = consumers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *ExportedServicesConfigEntry) Clone() *ExportedServicesConfigEntry {
|
|
||||||
e2 := *e
|
|
||||||
e2.Services = make([]ExportedService, len(e.Services))
|
|
||||||
for _, svc := range e.Services {
|
|
||||||
exportedSvc := svc
|
|
||||||
exportedSvc.Consumers = make([]ServiceConsumer, len(svc.Consumers))
|
|
||||||
for _, consumer := range svc.Consumers {
|
|
||||||
exportedSvc.Consumers = append(exportedSvc.Consumers, consumer)
|
|
||||||
}
|
|
||||||
e2.Services = append(e2.Services, exportedSvc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &e2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ExportedServicesConfigEntry) GetKind() string {
|
func (e *ExportedServicesConfigEntry) GetKind() string {
|
||||||
|
@ -122,6 +92,14 @@ func (e *ExportedServicesConfigEntry) Validate() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := e.validateServicesEnterprise(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.validateServices()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ExportedServicesConfigEntry) validateServices() error {
|
||||||
for i, svc := range e.Services {
|
for i, svc := range e.Services {
|
||||||
if svc.Name == "" {
|
if svc.Name == "" {
|
||||||
return fmt.Errorf("Services[%d]: service name cannot be empty", i)
|
return fmt.Errorf("Services[%d]: service name cannot be empty", i)
|
||||||
|
@ -133,8 +111,18 @@ func (e *ExportedServicesConfigEntry) Validate() error {
|
||||||
return fmt.Errorf("Services[%d]: must have at least one consumer", i)
|
return fmt.Errorf("Services[%d]: must have at least one consumer", i)
|
||||||
}
|
}
|
||||||
for j, consumer := range svc.Consumers {
|
for j, consumer := range svc.Consumers {
|
||||||
if consumer.Peer != "" && consumer.Partition != "" {
|
count := 0
|
||||||
return fmt.Errorf("Services[%d].Consumers[%d]: must define at most one of Peer or Partition", i, j)
|
if consumer.Peer != "" {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if consumer.Partition != "" {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if consumer.SamenessGroup != "" {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if count > 1 {
|
||||||
|
return fmt.Errorf("Services[%d].Consumers[%d]: must define at most one of Peer, Partition, or SamenessGroup", i, j)
|
||||||
}
|
}
|
||||||
if consumer.Partition == WildcardSpecifier {
|
if consumer.Partition == WildcardSpecifier {
|
||||||
return fmt.Errorf("Services[%d].Consumers[%d]: exporting to all partitions (wildcard) is not supported", i, j)
|
return fmt.Errorf("Services[%d].Consumers[%d]: exporting to all partitions (wildcard) is not supported", i, j)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
//go:build !consulent
|
||||||
|
// +build !consulent
|
||||||
|
|
||||||
|
package structs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/acl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *ExportedServicesConfigEntry) validateServicesEnterprise() error {
|
||||||
|
for i, svc := range e.Services {
|
||||||
|
for j, consumer := range svc.Consumers {
|
||||||
|
if !acl.IsDefaultPartition(consumer.Partition) {
|
||||||
|
return fmt.Errorf("Services[%d].Consumers[%d]: partitions are an enterprise-only feature", i, j)
|
||||||
|
}
|
||||||
|
if consumer.SamenessGroup != "" {
|
||||||
|
return fmt.Errorf("Services[%d].Consumers[%d]: sameness-groups are an enterprise-only feature", i, j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -59,6 +59,22 @@ func TestExportedServicesConfigEntry_OSS(t *testing.T) {
|
||||||
},
|
},
|
||||||
validateErr: `exported-services Name must be "default"`,
|
validateErr: `exported-services Name must be "default"`,
|
||||||
},
|
},
|
||||||
|
"validate: sameness groups are enterprise only": {
|
||||||
|
entry: &ExportedServicesConfigEntry{
|
||||||
|
Name: "default",
|
||||||
|
Services: []ExportedService{
|
||||||
|
{
|
||||||
|
Name: "web",
|
||||||
|
Consumers: []ServiceConsumer{
|
||||||
|
{
|
||||||
|
SamenessGroup: "sg",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validateErr: `Services[0].Consumers[0]: sameness-groups are an enterprise-only feature`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
testConfigEntryNormalizeAndValidate(t, cases)
|
testConfigEntryNormalizeAndValidate(t, cases)
|
|
@ -89,7 +89,7 @@ func TestExportedServicesConfigEntry(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validateErr: `Services[0].Consumers[0]: must define at most one of Peer or Partition`,
|
validateErr: `Services[0].Consumers[0]: must define at most one of Peer, Partition, or SamenessGroup`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ deep-copy \
|
||||||
-type DiscoveryRoute \
|
-type DiscoveryRoute \
|
||||||
-type DiscoverySplit \
|
-type DiscoverySplit \
|
||||||
-type ExposeConfig \
|
-type ExposeConfig \
|
||||||
|
-type ExportedServicesConfigEntry \
|
||||||
-type GatewayService \
|
-type GatewayService \
|
||||||
-type GatewayServiceTLSConfig \
|
-type GatewayServiceTLSConfig \
|
||||||
-type HTTPHeaderModifiers \
|
-type HTTPHeaderModifiers \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type APIGatewayListener -type BoundAPIGatewayListener -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HTTPRouteConfigEntry -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type InlineCertificateConfigEntry -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type TCPRouteConfigEntry -type Upstream -type UpstreamConfiguration -type Status -type BoundAPIGatewayConfigEntry ./; DO NOT EDIT.
|
// generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type APIGatewayListener -type BoundAPIGatewayListener -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type ExportedServicesConfigEntry -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HTTPRouteConfigEntry -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type InlineCertificateConfigEntry -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type TCPRouteConfigEntry -type Upstream -type UpstreamConfiguration -type Status -type BoundAPIGatewayConfigEntry ./; DO NOT EDIT.
|
||||||
|
|
||||||
package structs
|
package structs
|
||||||
|
|
||||||
|
@ -270,6 +270,28 @@ func (o *ExposeConfig) DeepCopy() *ExposeConfig {
|
||||||
return &cp
|
return &cp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopy generates a deep copy of *ExportedServicesConfigEntry
|
||||||
|
func (o *ExportedServicesConfigEntry) DeepCopy() *ExportedServicesConfigEntry {
|
||||||
|
var cp ExportedServicesConfigEntry = *o
|
||||||
|
if o.Services != nil {
|
||||||
|
cp.Services = make([]ExportedService, len(o.Services))
|
||||||
|
copy(cp.Services, o.Services)
|
||||||
|
for i2 := range o.Services {
|
||||||
|
if o.Services[i2].Consumers != nil {
|
||||||
|
cp.Services[i2].Consumers = make([]ServiceConsumer, len(o.Services[i2].Consumers))
|
||||||
|
copy(cp.Services[i2].Consumers, o.Services[i2].Consumers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if o.Meta != nil {
|
||||||
|
cp.Meta = make(map[string]string, len(o.Meta))
|
||||||
|
for k2, v2 := range o.Meta {
|
||||||
|
cp.Meta[k2] = v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &cp
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopy generates a deep copy of *GatewayService
|
// DeepCopy generates a deep copy of *GatewayService
|
||||||
func (o *GatewayService) DeepCopy() *GatewayService {
|
func (o *GatewayService) DeepCopy() *GatewayService {
|
||||||
var cp GatewayService = *o
|
var cp GatewayService = *o
|
||||||
|
|
Loading…
Reference in New Issue