mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-04-09 12:17:31 +00:00
* fix(controller): decode old object for delete requests Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: modernize golang Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: modernize golang Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: modernize golang Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * fix(config): remove usergroups default Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * fix(config): remove usergroups default Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * sec(ghsa-2ww6-hf35-mfjm): intercept namespace subresource Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * chore: conflicts Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> * feat(api): add rulestatus api Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> --------- Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>
114 lines
3.4 KiB
Go
114 lines
3.4 KiB
Go
// Copyright 2020-2026 Project Capsule Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package selectors_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/projectcapsule/capsule/pkg/runtime/selectors"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
)
|
|
|
|
func TestCombineSelectors(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("no selectors returns Everything (matches all)", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sel := selectors.CombineSelectors()
|
|
if !sel.Matches(labels.Set{}) {
|
|
t.Fatalf("expected combined selector to match empty label set")
|
|
}
|
|
// labels.NewSelector() string is typically "", which means "everything"
|
|
if got := sel.String(); got != "" {
|
|
t.Fatalf("expected empty selector string, got %q", got)
|
|
}
|
|
})
|
|
|
|
t.Run("nil selectors are ignored", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
base := labels.SelectorFromSet(labels.Set{"a": "1"})
|
|
sel := selectors.CombineSelectors(nil, base, nil)
|
|
|
|
if !sel.Matches(labels.Set{"a": "1"}) {
|
|
t.Fatalf("expected to match labels a=1")
|
|
}
|
|
if sel.Matches(labels.Set{"a": "2"}) {
|
|
t.Fatalf("expected not to match labels a=2")
|
|
}
|
|
})
|
|
|
|
t.Run("combines selectors with AND semantics", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
s1 := labels.SelectorFromSet(labels.Set{"a": "1"})
|
|
s2 := labels.SelectorFromSet(labels.Set{"b": "2"})
|
|
|
|
combined := selectors.CombineSelectors(s1, s2)
|
|
|
|
if !combined.Matches(labels.Set{"a": "1", "b": "2"}) {
|
|
t.Fatalf("expected to match when both requirements are satisfied")
|
|
}
|
|
if combined.Matches(labels.Set{"a": "1"}) {
|
|
t.Fatalf("expected not to match when b is missing")
|
|
}
|
|
if combined.Matches(labels.Set{"b": "2"}) {
|
|
t.Fatalf("expected not to match when a is missing")
|
|
}
|
|
if combined.Matches(labels.Set{"a": "1", "b": "3"}) {
|
|
t.Fatalf("expected not to match when b mismatches")
|
|
}
|
|
})
|
|
|
|
t.Run("conflicting selectors match nothing", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
s1 := labels.SelectorFromSet(labels.Set{"a": "1"})
|
|
s2 := labels.SelectorFromSet(labels.Set{"a": "2"})
|
|
|
|
combined := selectors.CombineSelectors(s1, s2)
|
|
|
|
if combined.Matches(labels.Set{"a": "1"}) {
|
|
t.Fatalf("expected not to match due to conflict (a=1 AND a=2)")
|
|
}
|
|
if combined.Matches(labels.Set{"a": "2"}) {
|
|
t.Fatalf("expected not to match due to conflict (a=1 AND a=2)")
|
|
}
|
|
})
|
|
|
|
t.Run("non-selectable selector returns Nothing", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// labels.Nothing() is not selectable (Requirements() => selectable=false).
|
|
combined := selectors.CombineSelectors(labels.SelectorFromSet(labels.Set{"a": "1"}), labels.Nothing())
|
|
|
|
if combined.String() != labels.Nothing().String() {
|
|
t.Fatalf("expected labels.Nothing() selector, got %q", combined.String())
|
|
}
|
|
if combined.Matches(labels.Set{"a": "1"}) {
|
|
t.Fatalf("expected Nothing selector to match nothing")
|
|
}
|
|
if combined.Matches(labels.Set{}) {
|
|
t.Fatalf("expected Nothing selector to match nothing (even empty set)")
|
|
}
|
|
})
|
|
|
|
t.Run("output selector is independent from input mutation patterns", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// This is a light regression guard: we depend on CombineSelectors turning input
|
|
// selectors into requirements, not keeping references to the original selector objects.
|
|
in := labels.SelectorFromSet(labels.Set{"a": "1"})
|
|
out := selectors.CombineSelectors(in)
|
|
|
|
if !out.Matches(labels.Set{"a": "1"}) {
|
|
t.Fatalf("expected out to match a=1")
|
|
}
|
|
if out.Matches(labels.Set{"a": "2"}) {
|
|
t.Fatalf("expected out not to match a=2")
|
|
}
|
|
})
|
|
}
|