diff --git a/agent/consul/state/config_entry.go b/agent/consul/state/config_entry.go index 7feee58b8f..15faeaad14 100644 --- a/agent/consul/state/config_entry.go +++ b/agent/consul/state/config_entry.go @@ -173,8 +173,8 @@ func (s *Store) EnsureConfigEntry(idx uint64, conf structs.ConfigEntry) error { // ensureConfigEntryTxn upserts a config entry inside of a transaction. func ensureConfigEntryTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry) error { - // Check for existing configuration. - existing, err := tx.First(tableConfigEntries, indexID, newConfigEntryQuery(conf)) + q := newConfigEntryQuery(conf) + existing, err := tx.First(tableConfigEntries, indexID, q) if err != nil { return fmt.Errorf("failed configuration lookup: %s", err) } @@ -195,7 +195,7 @@ func ensureConfigEntryTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry) err } raftIndex.ModifyIndex = idx - err = validateProposedConfigEntryInGraph(tx, conf.GetKind(), conf.GetName(), conf, conf.GetEnterpriseMeta()) + err = validateProposedConfigEntryInGraph(tx, q, conf) if err != nil { return err // Err is already sufficiently decorated. } @@ -255,7 +255,8 @@ func (s *Store) DeleteConfigEntry(idx uint64, kind, name string, entMeta *struct // TODO: accept structs.ConfigEntry instead of individual fields func deleteConfigEntryTxn(tx WriteTxn, idx uint64, kind, name string, entMeta *structs.EnterpriseMeta) error { - existing, err := tx.First(tableConfigEntries, indexID, NewConfigEntryKindName(kind, name, entMeta)) + q := NewConfigEntryKindName(kind, name, entMeta) + existing, err := tx.First(tableConfigEntries, indexID, q) if err != nil { return fmt.Errorf("failed config entry lookup: %s", err) } @@ -285,7 +286,7 @@ func deleteConfigEntryTxn(tx WriteTxn, idx uint64, kind, name string, entMeta *s } } - err = validateProposedConfigEntryInGraph(tx, kind, name, nil, entMeta) + err = validateProposedConfigEntryInGraph(tx, q, nil) if err != nil { return err // Err is already sufficiently decorated. } @@ -334,53 +335,46 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry) // to the caller that they can correct. func validateProposedConfigEntryInGraph( tx ReadTxn, - kind, name string, - proposedEntry structs.ConfigEntry, - entMeta *structs.EnterpriseMeta, + kindName ConfigEntryKindName, + newEntry structs.ConfigEntry, ) error { - validateAllChains := false - - switch kind { + switch kindName.Kind { case structs.ProxyDefaults: - if name != structs.ProxyConfigGlobal { + // TODO: why handle an invalid case? + if kindName.Name != structs.ProxyConfigGlobal { return nil } - validateAllChains = true case structs.ServiceDefaults: case structs.ServiceRouter: case structs.ServiceSplitter: case structs.ServiceResolver: case structs.IngressGateway: - err := checkGatewayClash(tx, name, structs.IngressGateway, structs.TerminatingGateway, entMeta) + err := checkGatewayClash(tx, kindName, structs.TerminatingGateway) if err != nil { return err } case structs.TerminatingGateway: - err := checkGatewayClash(tx, name, structs.TerminatingGateway, structs.IngressGateway, entMeta) + err := checkGatewayClash(tx, kindName, structs.IngressGateway) if err != nil { return err } case structs.ServiceIntentions: case structs.MeshConfig: default: - return fmt.Errorf("unhandled kind %q during validation of %q", kind, name) + return fmt.Errorf("unhandled kind %q during validation of %q", kindName.Kind, kindName.Name) } - return validateProposedConfigEntryInServiceGraph(tx, kind, name, proposedEntry, validateAllChains, entMeta) + return validateProposedConfigEntryInServiceGraph(tx, kindName, newEntry) } -func checkGatewayClash( - tx ReadTxn, - name, selfKind, otherKind string, - entMeta *structs.EnterpriseMeta, -) error { - _, entry, err := configEntryTxn(tx, nil, otherKind, name, entMeta) +func checkGatewayClash(tx ReadTxn, kindName ConfigEntryKindName, otherKind string) error { + _, entry, err := configEntryTxn(tx, nil, otherKind, kindName.Name, &kindName.EnterpriseMeta) if err != nil { return err } if entry != nil { return fmt.Errorf("cannot create a %q config entry with name %q, "+ - "a %q config entry with that name already exists", selfKind, name, otherKind) + "a %q config entry with that name already exists", kindName.Kind, kindName.Name, otherKind) } return nil } @@ -483,10 +477,8 @@ func (s *Store) discoveryChainSourcesTxn(tx ReadTxn, ws memdb.WatchSet, dc strin func validateProposedConfigEntryInServiceGraph( tx ReadTxn, - kind, name string, - proposedEntry structs.ConfigEntry, - validateAllChains bool, - entMeta *structs.EnterpriseMeta, + kindName ConfigEntryKindName, + newEntry structs.ConfigEntry, ) error { // Collect all of the chains that could be affected by this change // including our own. @@ -497,9 +489,8 @@ func validateProposedConfigEntryInServiceGraph( enforceIngressProtocolsMatch bool ) - if validateAllChains { - // Must be proxy-defaults/global. - + switch kindName.Kind { + case structs.ProxyDefaults: // Check anything that has a discovery chain entry. In the future we could // somehow omit the ones that have a default protocol configured. @@ -537,31 +528,31 @@ func validateProposedConfigEntryInServiceGraph( checkIntentions = append(checkIntentions, ixn) } - } else if kind == structs.ServiceIntentions { + case structs.ServiceIntentions: // Check that the protocols match. // This is the case for deleting a config entry - if proposedEntry == nil { + if newEntry == nil { return nil } - ixn, ok := proposedEntry.(*structs.ServiceIntentionsConfigEntry) + ixn, ok := newEntry.(*structs.ServiceIntentionsConfigEntry) if !ok { - return fmt.Errorf("type %T is not a service intentions config entry", proposedEntry) + return fmt.Errorf("type %T is not a service intentions config entry", newEntry) } checkIntentions = append(checkIntentions, ixn) - } else if kind == structs.IngressGateway { + case structs.IngressGateway: // Checking an ingress pointing to multiple chains. // This is the case for deleting a config entry - if proposedEntry == nil { + if newEntry == nil { return nil } - ingress, ok := proposedEntry.(*structs.IngressGatewayConfigEntry) + ingress, ok := newEntry.(*structs.IngressGatewayConfigEntry) if !ok { - return fmt.Errorf("type %T is not an ingress gateway config entry", proposedEntry) + return fmt.Errorf("type %T is not an ingress gateway config entry", newEntry) } checkIngress = append(checkIngress, ingress) @@ -569,12 +560,12 @@ func validateProposedConfigEntryInServiceGraph( // validating the protocol equivalence. enforceIngressProtocolsMatch = true - } else { + default: // Must be a single chain. // Check to see if we should ensure L7 intentions have an L7 protocol. _, ixn, err := getServiceIntentionsConfigEntryTxn( - tx, nil, name, nil, entMeta, + tx, nil, kindName.Name, nil, &kindName.EnterpriseMeta, ) if err != nil { return err @@ -594,7 +585,7 @@ func validateProposedConfigEntryInServiceGraph( checkIntentions = append(checkIntentions, ixn) } - sid := structs.NewServiceID(name, entMeta) + sid := structs.NewServiceID(kindName.Name, &kindName.EnterpriseMeta) checkChains[sid] = struct{}{} iter, err := tx.Get(tableConfigEntries, indexLink, sid) @@ -630,7 +621,7 @@ func validateProposedConfigEntryInServiceGraph( } overrides := map[ConfigEntryKindName]structs.ConfigEntry{ - NewConfigEntryKindName(kind, name, entMeta): proposedEntry, + kindName: newEntry, } var (