consul/agent/consul/leader_intentions_oss_test.go

155 lines
4.1 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
//go:build !consulent
// +build !consulent
package consul
import (
"sort"
"testing"
"time"
"github.com/hashicorp/consul/agent/structs"
"github.com/stretchr/testify/require"
)
func testLeader_LegacyIntentionMigrationHookEnterprise(_ *testing.T, _ *Server, _ bool) {
}
func appendLegacyIntentionsForMigrationTestEnterprise(_ *testing.T, _ *Server, ixns []*structs.Intention) []*structs.Intention {
return ixns
}
func TestMigrateIntentionsToConfigEntries(t *testing.T) {
compare := func(t *testing.T, got structs.Intentions, expect [][]string) {
t.Helper()
var actual [][]string
for _, ixn := range got {
actual = append(actual, []string{
ixn.SourceNS,
ixn.SourceName,
ixn.DestinationNS,
ixn.DestinationName,
})
}
require.ElementsMatch(t, expect, actual)
}
type testCase struct {
insert [][]string
expect [][]string
}
cases := map[string]testCase{
"no change": {
insert: [][]string{
{"default", "foo", "default", "bar"},
{"default", "*", "default", "*"},
},
expect: [][]string{
{"default", "foo", "default", "bar"},
{"default", "*", "default", "*"},
},
},
"non-wildcard deletions": {
insert: [][]string{
{"default", "foo", "default", "bar"},
{"alpha", "*", "default", "bar"},
{"default", "foo", "beta", "*"},
{"alpha", "zoo", "beta", "bar"},
},
expect: [][]string{
{"default", "foo", "default", "bar"},
},
},
"updates with no deletions and no collisions": {
insert: [][]string{
{"default", "foo", "default", "bar"},
{"default", "foo", "*", "*"},
{"*", "*", "default", "bar"},
{"*", "*", "*", "*"},
},
expect: [][]string{
{"default", "foo", "default", "bar"},
{"default", "foo", "default", "*"},
{"default", "*", "default", "bar"},
{"default", "*", "default", "*"},
},
},
"updates with only collision deletions": {
insert: [][]string{
{"default", "foo", "default", "bar"},
{"default", "foo", "default", "*"},
{"default", "foo", "*", "*"},
{"default", "*", "default", "bar"},
{"*", "*", "default", "bar"},
{"default", "*", "default", "*"},
{"*", "*", "*", "*"},
},
expect: [][]string{
{"default", "foo", "default", "bar"},
{"default", "foo", "default", "*"},
{"default", "*", "default", "bar"},
{"default", "*", "default", "*"},
},
},
"a bit of everything": {
insert: [][]string{
{"default", "foo", "default", "bar"}, // retained
{"default", "foo", "*", "*"}, // upgrade
{"default", "*", "default", "bar"}, // retained in collision
{"*", "*", "default", "bar"}, // deleted in collision
{"default", "*", "default", "*"}, // retained in collision
{"*", "*", "*", "*"}, // deleted in collision
{"alpha", "*", "default", "bar"}, // deleted
{"default", "foo", "beta", "*"}, // deleted
{"alpha", "zoo", "beta", "bar"}, // deleted
},
expect: [][]string{
{"default", "foo", "default", "bar"},
{"default", "foo", "default", "*"},
{"default", "*", "default", "bar"},
{"default", "*", "default", "*"},
},
},
}
for name, tc := range cases {
tc := tc
t.Run(name, func(t *testing.T) {
// Do something super evil and directly reach into the FSM to seed it with "bad" data.
var ixns structs.Intentions
for _, elem := range tc.insert {
require.Len(t, elem, 4)
ixn := structs.TestIntention(t)
ixn.ID = generateUUID()
ixn.SourceNS = elem[0]
ixn.SourceName = elem[1]
ixn.DestinationNS = elem[2]
ixn.DestinationName = elem[3]
ixn.CreatedAt = time.Now().UTC()
ixn.UpdatedAt = ixn.CreatedAt
ixns = append(ixns, ixn)
}
// Sleep a bit so that the UpdatedAt field will definitely be different
time.Sleep(1 * time.Millisecond)
got := migrateIntentionsToConfigEntries(ixns)
// Convert them back to the line-item version.
var gotIxns structs.Intentions
for _, entry := range got {
gotIxns = append(gotIxns, entry.ToIntentions()...)
}
sort.Sort(structs.IntentionPrecedenceSorter(gotIxns))
compare(t, gotIxns, tc.expect)
})
}
}