1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-02 20:35:25 +02:00

chore(code): reduce the code duplication EE-7278 (#11969)

This commit is contained in:
andres-portainer 2024-06-26 18:14:22 -03:00 committed by GitHub
parent 39bdfa4512
commit 9ee092aa5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
85 changed files with 520 additions and 618 deletions

76
api/tag/tag.go Normal file
View file

@ -0,0 +1,76 @@
package tag
import portainer "github.com/portainer/portainer/api"
type tagSet map[portainer.TagID]bool
// Set converts an array of ids to a set
func Set(tagIDs []portainer.TagID) tagSet {
set := map[portainer.TagID]bool{}
for _, tagID := range tagIDs {
set[tagID] = true
}
return set
}
// Intersection returns a set intersection of the provided sets
func Intersection(sets ...tagSet) tagSet {
intersection := tagSet{}
if len(sets) == 0 {
return intersection
}
setA := sets[0]
for tag := range setA {
inAll := true
for _, setB := range sets {
if !setB[tag] {
inAll = false
break
}
}
if inAll {
intersection[tag] = true
}
}
return intersection
}
// Union returns a set union of provided sets
func Union(sets ...tagSet) tagSet {
union := tagSet{}
for _, set := range sets {
for tag := range set {
union[tag] = true
}
}
return union
}
// Contains return true if setA contains setB
func Contains(setA tagSet, setB tagSet) bool {
if len(setA) == 0 || len(setB) == 0 {
return false
}
for tag := range setB {
if !setA[tag] {
return false
}
}
return true
}
// Difference returns the set difference tagsA - tagsB
func Difference(setA tagSet, setB tagSet) tagSet {
set := tagSet{}
for tag := range setA {
if !setB[tag] {
set[tag] = true
}
}
return set
}

11
api/tag/tag_match.go Normal file
View file

@ -0,0 +1,11 @@
package tag
// FullMatch returns true if environment tags matches all edge group tags
func FullMatch(edgeGroupTags tagSet, environmentTags tagSet) bool {
return Contains(environmentTags, edgeGroupTags)
}
// PartialMatch returns true if environment tags matches at least one edge group tag
func PartialMatch(edgeGroupTags tagSet, environmentTags tagSet) bool {
return len(Intersection(edgeGroupTags, environmentTags)) != 0
}

135
api/tag/tag_match_test.go Normal file
View file

@ -0,0 +1,135 @@
package tag
import (
"testing"
portainer "github.com/portainer/portainer/api"
)
func TestFullMatch(t *testing.T) {
cases := []struct {
name string
edgeGroupTags tagSet
environmentTag tagSet
expected bool
}{
{
name: "environment tag partially match edge group tags",
edgeGroupTags: Set([]portainer.TagID{1, 2, 3}),
environmentTag: Set([]portainer.TagID{1, 2}),
expected: false,
},
{
name: "edge group tags equal to environment tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{1, 2}),
expected: true,
},
{
name: "environment tags fully match edge group tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{1, 2, 3}),
expected: true,
},
{
name: "environment tags do not match edge group tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{3, 4}),
expected: false,
},
{
name: "edge group has no tags and environment has tags",
edgeGroupTags: Set([]portainer.TagID{}),
environmentTag: Set([]portainer.TagID{1, 2}),
expected: false,
},
{
name: "edge group has tags and environment has no tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{}),
expected: false,
},
{
name: "both edge group and environment have no tags",
edgeGroupTags: Set([]portainer.TagID{}),
environmentTag: Set([]portainer.TagID{}),
expected: false,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := FullMatch(tc.edgeGroupTags, tc.environmentTag)
if result != tc.expected {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}
func TestPartialMatch(t *testing.T) {
cases := []struct {
name string
edgeGroupTags tagSet
environmentTag tagSet
expected bool
}{
{
name: "environment tags partially match edge group tags 1",
edgeGroupTags: Set([]portainer.TagID{1, 2, 3}),
environmentTag: Set([]portainer.TagID{1, 2}),
expected: true,
},
{
name: "environment tags partially match edge group tags 2",
edgeGroupTags: Set([]portainer.TagID{1, 2, 3}),
environmentTag: Set([]portainer.TagID{1, 4, 5}),
expected: true,
},
{
name: "edge group tags equal to environment tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{1, 2}),
expected: true,
},
{
name: "environment tags fully match edge group tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{1, 2, 3}),
expected: true,
},
{
name: "environment tags do not match edge group tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{3, 4}),
expected: false,
},
{
name: "edge group has no tags and environment has tags",
edgeGroupTags: Set([]portainer.TagID{}),
environmentTag: Set([]portainer.TagID{1, 2}),
expected: false,
},
{
name: "edge group has tags and environment has no tags",
edgeGroupTags: Set([]portainer.TagID{1, 2}),
environmentTag: Set([]portainer.TagID{}),
expected: false,
},
{
name: "both edge group and environment have no tags",
edgeGroupTags: Set([]portainer.TagID{}),
environmentTag: Set([]portainer.TagID{}),
expected: false,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := PartialMatch(tc.edgeGroupTags, tc.environmentTag)
if result != tc.expected {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}

204
api/tag/tag_test.go Normal file
View file

@ -0,0 +1,204 @@
package tag
import (
"reflect"
"testing"
portainer "github.com/portainer/portainer/api"
)
func TestIntersection(t *testing.T) {
cases := []struct {
name string
setA tagSet
setB tagSet
expected tagSet
}{
{
name: "positive numbers set intersection",
setA: Set([]portainer.TagID{1, 2, 3, 4, 5}),
setB: Set([]portainer.TagID{4, 5, 6, 7}),
expected: Set([]portainer.TagID{4, 5}),
},
{
name: "empty setA intersection",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{}),
expected: Set([]portainer.TagID{}),
},
{
name: "empty setB intersection",
setA: Set([]portainer.TagID{}),
setB: Set([]portainer.TagID{1, 2, 3}),
expected: Set([]portainer.TagID{}),
},
{
name: "no common elements sets intersection",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{4, 5, 6}),
expected: Set([]portainer.TagID{}),
},
{
name: "equal sets intersection",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{1, 2, 3}),
expected: Set([]portainer.TagID{1, 2, 3}),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := Intersection(tc.setA, tc.setB)
if !reflect.DeepEqual(result, tc.expected) {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}
func TestUnion(t *testing.T) {
cases := []struct {
name string
setA tagSet
setB tagSet
expected tagSet
}{
{
name: "non-duplicate set union",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{4, 5, 6}),
expected: Set([]portainer.TagID{1, 2, 3, 4, 5, 6}),
},
{
name: "empty setA union",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{}),
expected: Set([]portainer.TagID{1, 2, 3}),
},
{
name: "empty setB union",
setA: Set([]portainer.TagID{}),
setB: Set([]portainer.TagID{1, 2, 3}),
expected: Set([]portainer.TagID{1, 2, 3}),
},
{
name: "duplicate elements in set union",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{3, 4, 5}),
expected: Set([]portainer.TagID{1, 2, 3, 4, 5}),
},
{
name: "equal sets union",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{1, 2, 3}),
expected: Set([]portainer.TagID{1, 2, 3}),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := Union(tc.setA, tc.setB)
if !reflect.DeepEqual(result, tc.expected) {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}
func TestContains(t *testing.T) {
cases := []struct {
name string
setA tagSet
setB tagSet
expected bool
}{
{
name: "setA contains setB",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{1, 2}),
expected: true,
},
{
name: "setA equals to setB",
setA: Set([]portainer.TagID{1, 2}),
setB: Set([]portainer.TagID{1, 2}),
expected: true,
},
{
name: "setA contains parts of setB",
setA: Set([]portainer.TagID{1, 2}),
setB: Set([]portainer.TagID{1, 2, 3}),
expected: false,
},
{
name: "setA does not contain setB",
setA: Set([]portainer.TagID{1, 2}),
setB: Set([]portainer.TagID{3, 4}),
expected: false,
},
{
name: "setA is empty and setB is not empty",
setA: Set([]portainer.TagID{}),
setB: Set([]portainer.TagID{1, 2}),
expected: false,
},
{
name: "setA is not empty and setB is empty",
setA: Set([]portainer.TagID{1, 2}),
setB: Set([]portainer.TagID{}),
expected: false,
},
{
name: "setA is empty and setB is empty",
setA: Set([]portainer.TagID{}),
setB: Set([]portainer.TagID{}),
expected: false,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := Contains(tc.setA, tc.setB)
if result != tc.expected {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}
func TestDifference(t *testing.T) {
cases := []struct {
name string
setA tagSet
setB tagSet
expected tagSet
}{
{
name: "positive numbers set difference",
setA: Set([]portainer.TagID{1, 2, 3, 4, 5}),
setB: Set([]portainer.TagID{4, 5, 6, 7}),
expected: Set([]portainer.TagID{1, 2, 3}),
},
{
name: "empty set difference",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{}),
expected: Set([]portainer.TagID{1, 2, 3}),
},
{
name: "equal sets difference",
setA: Set([]portainer.TagID{1, 2, 3}),
setB: Set([]portainer.TagID{1, 2, 3}),
expected: Set([]portainer.TagID{}),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result := Difference(tc.setA, tc.setB)
if !reflect.DeepEqual(result, tc.expected) {
t.Errorf("Expected %v, got %v", tc.expected, result)
}
})
}
}