mirror of https://github.com/status-im/consul.git
agent/consul: set precedence value on struct itself
This commit is contained in:
parent
1f5398e17c
commit
028aa78e83
|
@ -127,6 +127,9 @@ func (s *Intention) Apply(
|
||||||
// Validate. We do not validate on delete since it is valid to only
|
// Validate. We do not validate on delete since it is valid to only
|
||||||
// send an ID in that case.
|
// send an ID in that case.
|
||||||
if args.Op != structs.IntentionOpDelete {
|
if args.Op != structs.IntentionOpDelete {
|
||||||
|
// Set the precedence
|
||||||
|
args.Intention.UpdatePrecedence()
|
||||||
|
|
||||||
if err := args.Intention.Validate(); err != nil {
|
if err := args.Intention.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ func TestIntentionApply_new(t *testing.T) {
|
||||||
actual.CreateIndex, actual.ModifyIndex = 0, 0
|
actual.CreateIndex, actual.ModifyIndex = 0, 0
|
||||||
actual.CreatedAt = ixn.Intention.CreatedAt
|
actual.CreatedAt = ixn.Intention.CreatedAt
|
||||||
actual.UpdatedAt = ixn.Intention.UpdatedAt
|
actual.UpdatedAt = ixn.Intention.UpdatedAt
|
||||||
|
ixn.Intention.UpdatePrecedence()
|
||||||
assert.Equal(ixn.Intention, actual)
|
assert.Equal(ixn.Intention, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,7 +202,7 @@ func TestIntentionApply_updateGood(t *testing.T) {
|
||||||
// Update
|
// Update
|
||||||
ixn.Op = structs.IntentionOpUpdate
|
ixn.Op = structs.IntentionOpUpdate
|
||||||
ixn.Intention.ID = reply
|
ixn.Intention.ID = reply
|
||||||
ixn.Intention.SourceName = "bar"
|
ixn.Intention.SourceName = "*"
|
||||||
assert.Nil(msgpackrpc.CallWithCodec(codec, "Intention.Apply", &ixn, &reply))
|
assert.Nil(msgpackrpc.CallWithCodec(codec, "Intention.Apply", &ixn, &reply))
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
|
@ -221,6 +222,7 @@ func TestIntentionApply_updateGood(t *testing.T) {
|
||||||
actual.CreateIndex, actual.ModifyIndex = 0, 0
|
actual.CreateIndex, actual.ModifyIndex = 0, 0
|
||||||
actual.CreatedAt = ixn.Intention.CreatedAt
|
actual.CreatedAt = ixn.Intention.CreatedAt
|
||||||
actual.UpdatedAt = ixn.Intention.UpdatedAt
|
actual.UpdatedAt = ixn.Intention.UpdatedAt
|
||||||
|
ixn.Intention.UpdatePrecedence()
|
||||||
assert.Equal(ixn.Intention, actual)
|
assert.Equal(ixn.Intention, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,6 +380,7 @@ service "foo" {
|
||||||
actual.CreateIndex, actual.ModifyIndex = 0, 0
|
actual.CreateIndex, actual.ModifyIndex = 0, 0
|
||||||
actual.CreatedAt = ixn.Intention.CreatedAt
|
actual.CreatedAt = ixn.Intention.CreatedAt
|
||||||
actual.UpdatedAt = ixn.Intention.UpdatedAt
|
actual.UpdatedAt = ixn.Intention.UpdatedAt
|
||||||
|
ixn.Intention.UpdatePrecedence()
|
||||||
assert.Equal(ixn.Intention, actual)
|
assert.Equal(ixn.Intention, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,11 @@ type Intention struct {
|
||||||
// opaque to Consul but is served in API responses.
|
// opaque to Consul but is served in API responses.
|
||||||
Meta map[string]string
|
Meta map[string]string
|
||||||
|
|
||||||
|
// Precedence is the order that the intention will be applied, with
|
||||||
|
// larger numbers being applied first. This is a read-only field, on
|
||||||
|
// any intention update it is updated.
|
||||||
|
Precedence int
|
||||||
|
|
||||||
// CreatedAt and UpdatedAt keep track of when this record was created
|
// CreatedAt and UpdatedAt keep track of when this record was created
|
||||||
// or modified.
|
// or modified.
|
||||||
CreatedAt, UpdatedAt time.Time `mapstructure:"-"`
|
CreatedAt, UpdatedAt time.Time `mapstructure:"-"`
|
||||||
|
@ -160,6 +165,49 @@ func (x *Intention) Validate() error {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatePrecedence sets the Precedence value based on the fields of this
|
||||||
|
// structure.
|
||||||
|
func (x *Intention) UpdatePrecedence() {
|
||||||
|
// Max maintains the maximum value that the precedence can be depending
|
||||||
|
// on the number of exact values in the destination.
|
||||||
|
var max int
|
||||||
|
switch x.countExact(x.DestinationNS, x.DestinationName) {
|
||||||
|
case 2:
|
||||||
|
max = 9
|
||||||
|
case 1:
|
||||||
|
max = 6
|
||||||
|
case 0:
|
||||||
|
max = 3
|
||||||
|
default:
|
||||||
|
// This shouldn't be possible, just set it to zero
|
||||||
|
x.Precedence = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given the maximum, the exact value is determined based on the
|
||||||
|
// number of source exact values.
|
||||||
|
countSrc := x.countExact(x.SourceNS, x.SourceName)
|
||||||
|
x.Precedence = max - (2 - countSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// countExact counts the number of exact values (not wildcards) in
|
||||||
|
// the given namespace and name.
|
||||||
|
func (x *Intention) countExact(ns, n string) int {
|
||||||
|
// If NS is wildcard, it must be zero since wildcards only follow exact
|
||||||
|
if ns == IntentionWildcard {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same reasoning as above, a wildcard can only follow an exact value
|
||||||
|
// and an exact value cannot follow a wildcard, so if name is a wildcard
|
||||||
|
// we must have exactly one.
|
||||||
|
if n == IntentionWildcard {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
// GetACLPrefix returns the prefix to look up the ACL policy for this
|
// GetACLPrefix returns the prefix to look up the ACL policy for this
|
||||||
// intention, and a boolean noting whether the prefix is valid to check
|
// intention, and a boolean noting whether the prefix is valid to check
|
||||||
// or not. You must check the ok value before using the prefix.
|
// or not. You must check the ok value before using the prefix.
|
||||||
|
@ -354,20 +402,8 @@ func (s IntentionPrecedenceSorter) Swap(i, j int) {
|
||||||
|
|
||||||
func (s IntentionPrecedenceSorter) Less(i, j int) bool {
|
func (s IntentionPrecedenceSorter) Less(i, j int) bool {
|
||||||
a, b := s[i], s[j]
|
a, b := s[i], s[j]
|
||||||
|
if a.Precedence != b.Precedence {
|
||||||
// First test the # of exact values in destination, since precedence
|
return a.Precedence > b.Precedence
|
||||||
// is destination-oriented.
|
|
||||||
aExact := s.countExact(a.DestinationNS, a.DestinationName)
|
|
||||||
bExact := s.countExact(b.DestinationNS, b.DestinationName)
|
|
||||||
if aExact != bExact {
|
|
||||||
return aExact > bExact
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next test the # of exact values in source
|
|
||||||
aExact = s.countExact(a.SourceNS, a.SourceName)
|
|
||||||
bExact = s.countExact(b.SourceNS, b.SourceName)
|
|
||||||
if aExact != bExact {
|
|
||||||
return aExact > bExact
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tie break on lexicographic order of the 4-tuple in canonical form (SrcNS,
|
// Tie break on lexicographic order of the 4-tuple in canonical form (SrcNS,
|
||||||
|
@ -387,21 +423,3 @@ func (s IntentionPrecedenceSorter) Less(i, j int) bool {
|
||||||
}
|
}
|
||||||
return a.DestinationName < b.DestinationName
|
return a.DestinationName < b.DestinationName
|
||||||
}
|
}
|
||||||
|
|
||||||
// countExact counts the number of exact values (not wildcards) in
|
|
||||||
// the given namespace and name.
|
|
||||||
func (s IntentionPrecedenceSorter) countExact(ns, n string) int {
|
|
||||||
// If NS is wildcard, it must be zero since wildcards only follow exact
|
|
||||||
if ns == IntentionWildcard {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same reasoning as above, a wildcard can only follow an exact value
|
|
||||||
// and an exact value cannot follow a wildcard, so if name is a wildcard
|
|
||||||
// we must have exactly one.
|
|
||||||
if n == IntentionWildcard {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
|
@ -232,6 +232,11 @@ func TestIntentionPrecedenceSorter(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set all the precedence values
|
||||||
|
for _, ixn := range input {
|
||||||
|
ixn.UpdatePrecedence()
|
||||||
|
}
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
sort.Sort(IntentionPrecedenceSorter(input))
|
sort.Sort(IntentionPrecedenceSorter(input))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue