Compare commits

...

7 Commits

Author SHA1 Message Date
Dmitri Dolguikh
d8e7f2e9e6 a couple of fixes
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-24 15:40:44 +02:00
Dmitri Dolguikh
1205641b44 fixed test
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-24 15:17:41 +02:00
Dmitri Dolguikh
56e8215ebe updated 'resource-routing-bridge/router-peer-change refreshes policy sources' test to expect router peer among changed peer ids
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-24 14:29:23 +02:00
Dmitri Dolguikh
9b768d1773 fixed a bug in collectFromPolicies
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-24 14:10:37 +02:00
Dmitri Dolguikh
33954ea15e fixing tests + adding tests
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-24 13:07:53 +02:00
Dmitri Dolguikh
4c4434a871 fixed a few tests
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-24 09:48:45 +02:00
Dmitri Dolguikh
7873f337df when collecting group and peer IDs from policies, do so directionally
Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-06-23 18:39:53 +02:00
4 changed files with 325 additions and 67 deletions

View File

@@ -41,7 +41,7 @@ func TestAffectedPeers_DependencyCoverageMatrix(t *testing.T) {
_, err := s.manager.SavePolicy(ctx, s.accountID, userID, peerToResourcePolicyByGroup(s.sourceGroupID, s.resourceGroupID), true)
require.NoError(t, err)
return affectedpeers.Change{ChangedPeerIDs: []string{s.routerPeerID}},
[]string{s.sourcePeerID}, []string{s.unrelatedPeerID}
[]string{s.sourcePeerID, s.routerPeerID}, []string{s.unrelatedPeerID}
},
},
{
@@ -106,12 +106,8 @@ func TestAffectedPeers_DependencyCoverageMatrix(t *testing.T) {
change, mustContain, mustExclude := r.build(t, s, ctx)
affected := resolveAffected(t, s.manager.Store, s.accountID, change)
for _, id := range mustContain {
assert.Contains(t, affected, id, "expected peer to be affected")
}
for _, id := range mustExclude {
assert.NotContains(t, affected, id, "peer must not be affected")
}
assert.ElementsMatch(t, affected, mustContain, "expected peer to be affected")
assert.NotContains(t, affected, mustExclude, "peer must not be affected")
})
}
}

View File

@@ -96,33 +96,54 @@ func affectedGroupID(i int) string { return fmt.Sprintf("affected-grp-%d", i)
func affectedGroupName(i int) string { return fmt.Sprintf("AffectedGroup%d", i) }
func TestCollectGroupChange_PolicyLinked(t *testing.T) {
manager, s, accountID, _, groupIDs := setupAffectedPeersTest(t)
manager, s, accountID, peerIDs, groupIDs := setupAffectedPeersTest(t)
ctx := context.Background()
_, err := manager.SavePolicy(ctx, accountID, userID, &types.Policy{
Enabled: true,
Rules: []*types.PolicyRule{
{
Enabled: true,
Sources: []string{groupIDs[0]},
Destinations: []string{groupIDs[1]},
Bidirectional: true,
Action: types.PolicyTrafficActionAccept,
Enabled: true,
Sources: []string{groupIDs[0]},
Destinations: []string{groupIDs[1]},
SourceResource: types.Resource{ID: peerIDs[0], Type: types.ResourceTypePeer},
DestinationResource: types.Resource{ID: peerIDs[1], Type: types.ResourceTypePeer},
Bidirectional: true,
Action: types.PolicyTrafficActionAccept,
},
{
Enabled: true,
Sources: []string{groupIDs[0]},
Destinations: []string{groupIDs[1]},
SourceResource: types.Resource{ID: peerIDs[2], Type: types.ResourceTypeHost},
DestinationResource: types.Resource{ID: peerIDs[3], Type: types.ResourceTypeHost},
Bidirectional: true,
Action: types.PolicyTrafficActionAccept,
},
{
Enabled: true,
Sources: []string{groupIDs[0]},
Destinations: []string{groupIDs[1]},
SourceResource: types.Resource{ID: "", Type: types.ResourceTypePeer},
DestinationResource: types.Resource{ID: "", Type: types.ResourceTypePeer},
Bidirectional: true,
Action: types.PolicyTrafficActionAccept,
},
},
}, true)
require.NoError(t, err)
groups, _ := collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[0]})
assert.Contains(t, groups, groupIDs[0])
assert.Contains(t, groups, groupIDs[1])
groups, directPeers := collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[0]})
assert.ElementsMatch(t, groups, []string{groupIDs[0], groupIDs[1]})
assert.ElementsMatch(t, directPeers, []string{peerIDs[1]})
groups, _ = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[1]})
assert.Contains(t, groups, groupIDs[0])
assert.Contains(t, groups, groupIDs[1])
groups, directPeers = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[1]})
assert.ElementsMatch(t, groups, []string{groupIDs[0], groupIDs[1]})
assert.ElementsMatch(t, directPeers, []string{peerIDs[0]})
groups, _ = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[2]})
groups, directPeers = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[2]})
assert.Empty(t, groups)
assert.Empty(t, directPeers)
}
func TestCollectGroupChange_PolicyWithDirectPeerResource(t *testing.T) {
@@ -133,20 +154,44 @@ func TestCollectGroupChange_PolicyWithDirectPeerResource(t *testing.T) {
Enabled: true,
Rules: []*types.PolicyRule{
{
Enabled: true,
Sources: []string{groupIDs[0]},
SourceResource: types.Resource{ID: peerIDs[3], Type: types.ResourceTypePeer},
Destinations: []string{groupIDs[1]},
Action: types.PolicyTrafficActionAccept,
Enabled: true,
Sources: []string{groupIDs[0]},
SourceResource: types.Resource{ID: peerIDs[3], Type: types.ResourceTypePeer},
DestinationResource: types.Resource{ID: peerIDs[4], Type: types.ResourceTypePeer},
Destinations: []string{groupIDs[1]},
Action: types.PolicyTrafficActionAccept,
},
{
Enabled: true,
Sources: []string{groupIDs[0]},
SourceResource: types.Resource{ID: peerIDs[1], Type: types.ResourceTypeHost},
DestinationResource: types.Resource{ID: peerIDs[2], Type: types.ResourceTypeHost},
Destinations: []string{groupIDs[1]},
Action: types.PolicyTrafficActionAccept,
},
{
Enabled: true,
Sources: []string{groupIDs[0]},
SourceResource: types.Resource{ID: "", Type: types.ResourceTypePeer},
DestinationResource: types.Resource{ID: "", Type: types.ResourceTypePeer},
Destinations: []string{groupIDs[1]},
Action: types.PolicyTrafficActionAccept,
},
},
}, true)
require.NoError(t, err)
groups, directPeers := collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[0]})
assert.Contains(t, groups, groupIDs[0])
assert.Contains(t, groups, groupIDs[1])
assert.Contains(t, directPeers, peerIDs[3])
assert.ElementsMatch(t, groups, []string{groupIDs[0], groupIDs[1]})
assert.ElementsMatch(t, directPeers, []string{peerIDs[4]})
groups, directPeers = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[1]})
assert.ElementsMatch(t, groups, []string{groupIDs[0], groupIDs[1]})
assert.ElementsMatch(t, directPeers, []string{peerIDs[3]})
groups, directPeers = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[2]})
assert.Empty(t, groups)
assert.Empty(t, directPeers)
}
func TestCollectGroupChange_PolicyWithNonPeerResource_NoDirectPeers(t *testing.T) {
@@ -168,8 +213,7 @@ func TestCollectGroupChange_PolicyWithNonPeerResource_NoDirectPeers(t *testing.T
require.NoError(t, err)
groups, directPeers := collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[0]})
assert.Contains(t, groups, groupIDs[0])
assert.Contains(t, groups, groupIDs[1])
assert.ElementsMatch(t, groups, []string{groupIDs[0], groupIDs[1]})
assert.Empty(t, directPeers, "non-peer resources should not produce direct peer IDs")
}
@@ -373,17 +417,11 @@ func TestCollectGroupChange_MultipleEntities(t *testing.T) {
require.NoError(t, err)
groups, directPeers := collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[0]})
assert.Contains(t, groups, groupIDs[0])
assert.Contains(t, groups, groupIDs[1])
assert.NotContains(t, groups, groupIDs[2])
assert.NotContains(t, groups, groupIDs[3])
assert.ElementsMatch(t, groups, []string{groupIDs[0], groupIDs[1]})
assert.Empty(t, directPeers)
groups, directPeers = collectGroupChangeAffectedGroups(ctx, s, accountID, []string{groupIDs[3]})
assert.Contains(t, groups, groupIDs[2])
assert.Contains(t, groups, groupIDs[3])
assert.NotContains(t, groups, groupIDs[0])
assert.NotContains(t, groups, groupIDs[1])
assert.ElementsMatch(t, groups, []string{groupIDs[2], groupIDs[3]})
assert.Empty(t, directPeers)
}
@@ -474,7 +512,7 @@ func TestResolveAffectedPeers_PolicyThreeGroups(t *testing.T) {
require.NoError(t, err)
result := manager.resolveAffectedPeersForPeerChanges(ctx, s, accountID, []string{peerIDs[0]})
assert.ElementsMatch(t, []string{peerIDs[0], peerIDs[1], peerIDs[2]}, result)
assert.ElementsMatch(t, []string{peerIDs[0], peerIDs[2]}, result)
}
func TestResolveAffectedPeers_RoutePeerGroups(t *testing.T) {
@@ -697,7 +735,7 @@ func TestResolveAffectedPeers_MultipleChangedPeers(t *testing.T) {
require.NoError(t, err)
result := manager.resolveAffectedPeersForPeerChanges(ctx, s, accountID, []string{peerIDs[0], peerIDs[2]})
assert.ElementsMatch(t, []string{peerIDs[0], peerIDs[1], peerIDs[2], peerIDs[3]}, result)
assert.ElementsMatch(t, []string{peerIDs[0], peerIDs[2], peerIDs[1], peerIDs[3]}, result)
}
func TestResolveAffectedPeers_SharedGroupAcrossPolicyAndRoute(t *testing.T) {

View File

@@ -11,6 +11,8 @@ package affectedpeers
import (
"context"
"maps"
"slices"
log "github.com/sirupsen/logrus"
@@ -447,15 +449,24 @@ func (r *resolver) collectFromPostureChecks(postureCheckIDs []string) {
func (r *resolver) collectFromPolicies() {
for _, policy := range r.policies() {
matchedByGroup := policyReferencesGroups(policy, r.changedGroupSet)
matchedByPeer := len(r.changedPeerSet) > 0 && policyReferencesDirectPeers(policy, r.changedPeerSet)
if !matchedByGroup && !matchedByPeer {
// changed peer IDs have been mapped to changedGroupSet on resolver creation (see seedChangedGroupsFromPeers)
// there's no change to the groupSet if the same policies have been changed directly
peerIdsViaGroups, groupIdsViaGroups := getGroupsAndPeersFromPolicyViaGroups(policy, r.changedGroupSet)
addAll(r.groupSet, groupIdsViaGroups)
addAll(r.peerSet, peerIdsViaGroups)
peerIdsViaPeers, groupIdsViaPeers := getGroupsAndPeersFromPolicyViaPeers(policy, r.changedPeerSet)
addAll(r.groupSet, groupIdsViaPeers)
addAll(r.peerSet, peerIdsViaPeers)
hasGroupChanges := len(groupIdsViaPeers) > 0 || len(groupIdsViaGroups) > 0
hasPeerChanges := len(peerIdsViaPeers) > 0 || len(peerIdsViaGroups) > 0
if !hasGroupChanges && !hasPeerChanges {
continue
}
log.WithContext(r.ctx).Tracef("collectFromPolicies: policy %s (%s) matched (byGroup=%t byPeer=%t) -> folding rule groups %v + direct peers",
policy.ID, policy.Name, matchedByGroup, matchedByPeer, policy.RuleGroups())
addAll(r.groupSet, policy.RuleGroups())
collectPolicyDirectPeers(policy, r.peerSet)
policy.ID, policy.Name, hasGroupChanges, hasPeerChanges, policy.RuleGroups())
r.matchedPolicies = append(r.matchedPolicies, policy)
}
}
@@ -734,22 +745,60 @@ func collectPolicySources(policy *types.Policy, groupSet, peerSet map[string]str
}
}
func policyReferencesGroups(policy *types.Policy, groupSet map[string]struct{}) bool {
// returns group and peer IDs on the opposite side of the policy:
// i.e. if a group is present in the policy rule sources, return destination group IDs and the destinationResource from the rule
// and vice-versa
func getGroupsAndPeersFromPolicyViaGroups(policy *types.Policy, groupSet map[string]struct{}) ([]string, []string) {
var groupIds, peerIds []string
if len(groupSet) == 0 {
return peerIds, groupIds
}
for _, rule := range policy.Rules {
if anyInSet(rule.Sources, groupSet) || anyInSet(rule.Destinations, groupSet) {
return true
if matchedIds, ok := allInSet(rule.Sources, groupSet); ok {
groupIds = append(groupIds, matchedIds...)
groupIds = append(groupIds, rule.Destinations...)
if rule.DestinationResource.Type == types.ResourceTypePeer && rule.DestinationResource.ID != "" {
peerIds = append(peerIds, rule.DestinationResource.ID)
}
}
if matchedIds, ok := allInSet(rule.Destinations, groupSet); ok {
groupIds = append(groupIds, matchedIds...)
groupIds = append(groupIds, rule.Sources...)
if rule.SourceResource.Type == types.ResourceTypePeer && rule.SourceResource.ID != "" {
peerIds = append(peerIds, rule.SourceResource.ID)
}
}
}
return false
return peerIds, groupIds
}
func policyReferencesDirectPeers(policy *types.Policy, changedSet map[string]struct{}) bool {
// returns group and peer IDs on the opposite side of the policy:
// i.e. if a peer is present in the policy rule sourceResources, return destination group IDs and the destinationResource from the rule
// and vice-versa
func getGroupsAndPeersFromPolicyViaPeers(policy *types.Policy, changedSet map[string]struct{}) ([]string, []string) {
peerIds := make(map[string]struct{})
var groupIds []string
if len(changedSet) == 0 {
return []string{}, groupIds
}
for _, rule := range policy.Rules {
if isDirectPeerInSet(rule.SourceResource, changedSet) || isDirectPeerInSet(rule.DestinationResource, changedSet) {
return true
if isDirectPeerInSet(rule.SourceResource, changedSet) {
groupIds = append(groupIds, rule.Destinations...)
peerIds[rule.SourceResource.ID] = struct{}{}
if rule.DestinationResource.Type == types.ResourceTypePeer && rule.DestinationResource.ID != "" {
peerIds[rule.DestinationResource.ID] = struct{}{}
}
}
// it's possible that the changeSet contains peer ids of both source and destination resources
if isDirectPeerInSet(rule.DestinationResource, changedSet) {
groupIds = append(groupIds, rule.Sources...)
peerIds[rule.DestinationResource.ID] = struct{}{}
if rule.SourceResource.Type == types.ResourceTypePeer && rule.SourceResource.ID != "" {
peerIds[rule.SourceResource.ID] = struct{}{}
}
}
}
return false
return slices.Collect(maps.Keys(peerIds)), groupIds
}
func policyReferencesPostureChecks(policy *types.Policy, ids map[string]struct{}) bool {
@@ -795,6 +844,16 @@ func anyInSet(ids []string, set map[string]struct{}) bool {
return false
}
func allInSet(ids []string, set map[string]struct{}) ([]string, bool) {
var matchedIds []string
for _, id := range ids {
if _, ok := set[id]; ok {
matchedIds = append(matchedIds, id)
}
}
return matchedIds, len(matchedIds) > 0
}
func isInSet(id string, set map[string]struct{}) bool {
_, ok := set[id]
return ok

View File

@@ -80,24 +80,189 @@ func TestChangeIsEmpty(t *testing.T) {
assert.False(t, Change{PostureCheckIDs: []string{"pc"}}.isEmpty())
}
func TestPolicyReferencesGroups(t *testing.T) {
policy := &types.Policy{Rules: []*types.PolicyRule{{Sources: []string{"g1", "g2"}, Destinations: []string{"g3"}}}}
func TestGroupsFromPolicyDirectionally(t *testing.T) {
policy := &types.Policy{Rules: []*types.PolicyRule{
{Sources: []string{"g1", "g2"}, Destinations: []string{"g3"}},
{Sources: []string{"g4"}, Destinations: []string{"g5", "g6"}},
{Sources: []string{"g7"}, Destinations: []string{"g8"},
SourceResource: types.Resource{ID: "r7", Type: types.ResourceTypePeer},
DestinationResource: types.Resource{ID: "r8", Type: types.ResourceTypePeer}},
{Sources: []string{"g9"}, Destinations: []string{"g10"},
SourceResource: types.Resource{ID: "", Type: types.ResourceTypePeer},
DestinationResource: types.Resource{ID: "", Type: types.ResourceTypePeer}},
{Sources: []string{"g11"}, Destinations: []string{"g12"},
SourceResource: types.Resource{ID: "r11", Type: types.ResourceTypeHost},
DestinationResource: types.Resource{ID: "r12", Type: types.ResourceTypeHost}},
}}
assert.True(t, policyReferencesGroups(policy, map[string]struct{}{"g1": {}}))
assert.True(t, policyReferencesGroups(policy, map[string]struct{}{"g3": {}}))
assert.False(t, policyReferencesGroups(policy, map[string]struct{}{"g4": {}}))
assert.False(t, policyReferencesGroups(policy, map[string]struct{}{}))
var tests = []struct {
name string
inGroups map[string]struct{}
expectedPeerIds []string
expectedGroupIds []string
}{
{
name: "match sources",
inGroups: map[string]struct{}{"g1": {}, "g4": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{"g1", "g4", "g3", "g5", "g6"},
},
{
name: "match destinations",
inGroups: map[string]struct{}{"g3": {}, "g6": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{"g1", "g2", "g4", "g3", "g6"},
},
{
name: "should return destinations and destination resource",
inGroups: map[string]struct{}{"g7": {}},
expectedPeerIds: []string{"r8"},
expectedGroupIds: []string{"g7", "g8"},
},
{
name: "should return sources and source resource",
inGroups: map[string]struct{}{"g8": {}},
expectedPeerIds: []string{"r7"},
expectedGroupIds: []string{"g7", "g8"},
},
{
name: "should not return source resource (empty id)",
inGroups: map[string]struct{}{"g10": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{"g9", "g10"},
},
{
name: "should not return destination resource (empty id)",
inGroups: map[string]struct{}{"g9": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{"g9", "g10"},
},
{
name: "should not return source resource (non-peer type)",
inGroups: map[string]struct{}{"g12": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{"g11", "g12"},
},
{
name: "should not return destination resource (non-peer type)",
inGroups: map[string]struct{}{"g12": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{"g11", "g12"},
},
{
name: "non-existing group",
inGroups: map[string]struct{}{"g33": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{},
},
{
name: "empty groupset",
inGroups: map[string]struct{}{},
expectedPeerIds: []string{},
expectedGroupIds: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
peerIds, groupIds := getGroupsAndPeersFromPolicyViaGroups(policy, tt.inGroups)
assert.ElementsMatch(t, peerIds, tt.expectedPeerIds)
assert.ElementsMatch(t, groupIds, tt.expectedGroupIds)
})
}
}
func TestPolicyReferencesDirectPeers(t *testing.T) {
policy := &types.Policy{Rules: []*types.PolicyRule{{
SourceResource: types.Resource{Type: types.ResourceTypePeer, ID: "p1"},
DestinationResource: types.Resource{Type: types.ResourceTypeHost, ID: "r1"},
}}}
policy := &types.Policy{Rules: []*types.PolicyRule{
{
SourceResource: types.Resource{Type: types.ResourceTypePeer, ID: "p1"},
DestinationResource: types.Resource{Type: types.ResourceTypePeer, ID: "r1"},
Sources: []string{"sg1"},
Destinations: []string{"dg1"},
},
{
SourceResource: types.Resource{Type: types.ResourceTypePeer, ID: "p2"},
DestinationResource: types.Resource{Type: types.ResourceTypePeer, ID: "r2"},
Sources: []string{"sg2"},
Destinations: []string{"dg2"},
},
{
SourceResource: types.Resource{Type: types.ResourceTypePeer, ID: "p3"},
DestinationResource: types.Resource{Type: types.ResourceTypeHost, ID: "r3"},
Sources: []string{"sg3"},
Destinations: []string{"dg3"},
},
{
SourceResource: types.Resource{Type: types.ResourceTypeHost, ID: "p4"},
DestinationResource: types.Resource{Type: types.ResourceTypePeer, ID: "r4"},
Sources: []string{"sg4"},
Destinations: []string{"dg4"},
},
{
SourceResource: types.Resource{Type: types.ResourceTypeHost, ID: "p5"},
DestinationResource: types.Resource{Type: types.ResourceTypePeer, ID: "r5"},
Sources: []string{"sg5"},
Destinations: []string{"dg5"},
},
{
SourceResource: types.Resource{Type: types.ResourceTypePeer, ID: "p6"},
DestinationResource: types.Resource{Type: types.ResourceTypeHost, ID: "r6"},
Sources: []string{"sg6"},
Destinations: []string{"dg6"},
},
{
SourceResource: types.Resource{Type: types.ResourceTypePeer, ID: "p7"},
DestinationResource: types.Resource{Type: types.ResourceTypePeer, ID: "r7"},
Sources: []string{"sg7"},
Destinations: []string{"dg7"},
},
}}
assert.True(t, policyReferencesDirectPeers(policy, map[string]struct{}{"p1": {}}))
assert.False(t, policyReferencesDirectPeers(policy, map[string]struct{}{"r1": {}}))
assert.False(t, policyReferencesDirectPeers(policy, map[string]struct{}{"p2": {}}))
var tests = []struct {
name string
changedPeerIds map[string]struct{}
expectedPeerIds []string
expectedGroupIds []string
}{
{
name: "match sources",
changedPeerIds: map[string]struct{}{"p1": {}, "p2": {}},
expectedPeerIds: []string{"p1", "p2", "r1", "r2"},
expectedGroupIds: []string{"dg1", "dg2"},
},
{
name: "match destinations",
changedPeerIds: map[string]struct{}{"r1": {}, "r2": {}},
expectedPeerIds: []string{"r1", "r2", "p1", "p2"},
expectedGroupIds: []string{"sg1", "sg2"},
},
{
name: "wrong opposing peer types, only changed peer ids and groups on the opposing end of the rule",
changedPeerIds: map[string]struct{}{"p3": {}, "r4": {}},
expectedPeerIds: []string{"p3", "r4"},
expectedGroupIds: []string{"dg3", "sg4"},
},
{
name: "wrong peer type, no matching peer ids",
changedPeerIds: map[string]struct{}{"p5": {}, "r6": {}},
expectedPeerIds: []string{},
expectedGroupIds: []string{},
},
{
name: "changed peers on both sides of the policy",
changedPeerIds: map[string]struct{}{"p7": {}, "r7": {}},
expectedPeerIds: []string{"p7", "r7"},
expectedGroupIds: []string{"sg7", "dg7"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
peerIds, groupIds := getGroupsAndPeersFromPolicyViaPeers(policy, tt.changedPeerIds)
assert.ElementsMatch(t, peerIds, tt.expectedPeerIds)
assert.ElementsMatch(t, groupIds, tt.expectedGroupIds)
})
}
}
func TestPolicyReferencesPostureChecks(t *testing.T) {