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:
parent
39bdfa4512
commit
9ee092aa5e
85 changed files with 520 additions and 618 deletions
76
api/tag/tag.go
Normal file
76
api/tag/tag.go
Normal 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
11
api/tag/tag_match.go
Normal 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
135
api/tag/tag_match_test.go
Normal 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
204
api/tag/tag_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue