mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 20:46:42 +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: preserve ca-bundles injected from external providers Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: add metadata enforcement Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: add metadata enforcement Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * fix: add resourcepoolclaim validation Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * fix: add resourcepoolclaim validation Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * fix: add resourcepoolclaim validation Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: add resourcepoolclaim validation Signed-off-by: Oliver Baehler <oliver@sudo-i.net> --------- Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com> Signed-off-by: Oliver Baehler <oliver@sudo-i.net> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
851 lines
16 KiB
Go
851 lines
16 KiB
Go
// Copyright 2020-2026 Project Capsule Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package meta
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
func TestNewManagedMetadata(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("contains default managed labels", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := NewManagedMetadata(nil, nil)
|
|
|
|
for _, key := range []string{
|
|
ResourcesLabel,
|
|
TenantNameLabel,
|
|
TenantLabel,
|
|
NewTenantLabel,
|
|
ResourcePoolLabel,
|
|
FreezeLabel,
|
|
OwnerPromotionLabel,
|
|
ServiceAccountPromotionLabel,
|
|
CordonedLabel,
|
|
CapsuleNameLabel,
|
|
CreatedByCapsuleLabel,
|
|
CustomResourcesLabel,
|
|
NewManagedByCapsuleLabel,
|
|
ManagedByCapsuleLabel,
|
|
LimitRangeLabel,
|
|
NetworkPolicyLabel,
|
|
ResourceQuotaLabel,
|
|
RolebindingLabel,
|
|
} {
|
|
if !m.HasLabel(key) {
|
|
t.Fatalf("expected managed label %q", key)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("contains default managed annotations", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := NewManagedMetadata(nil, nil)
|
|
|
|
for _, key := range []string{
|
|
ReleaseAnnotation,
|
|
ReconcileAnnotation,
|
|
AvailableIngressClassesAnnotation,
|
|
AvailableIngressClassesRegexpAnnotation,
|
|
AvailableStorageClassesAnnotation,
|
|
AvailableStorageClassesRegexpAnnotation,
|
|
AllowedRegistriesAnnotation,
|
|
AllowedRegistriesRegexpAnnotation,
|
|
ForbiddenNamespaceLabelsAnnotation,
|
|
ForbiddenNamespaceLabelsRegexpAnnotation,
|
|
ForbiddenNamespaceAnnotationsAnnotation,
|
|
ForbiddenNamespaceAnnotationsRegexpAnnotation,
|
|
ProtectedTenantAnnotation,
|
|
} {
|
|
if !m.HasAnnotation(key) {
|
|
t.Fatalf("expected managed annotation %q", key)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("contains default managed annotation prefixes", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := NewManagedMetadata(nil, nil)
|
|
|
|
for _, key := range []string{
|
|
ResourceQuotaAnnotationPrefix + "cpu",
|
|
ResourceQuotaAnnotationPrefix + "memory",
|
|
ResourceUsedAnnotationPrefix + "cpu",
|
|
ResourceUsedAnnotationPrefix + "memory",
|
|
} {
|
|
if !m.HasAnnotation(key) {
|
|
t.Fatalf("expected managed annotation prefix match for %q", key)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("adds custom managed labels and annotations", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := NewManagedMetadata(
|
|
[]string{
|
|
"example.corp/label",
|
|
" example.corp/trimmed-label ",
|
|
"",
|
|
" ",
|
|
},
|
|
[]string{
|
|
"example.corp/annotation",
|
|
" example.corp/trimmed-annotation ",
|
|
"",
|
|
" ",
|
|
},
|
|
)
|
|
|
|
for _, key := range []string{
|
|
"example.corp/label",
|
|
"example.corp/trimmed-label",
|
|
} {
|
|
if !m.HasLabel(key) {
|
|
t.Fatalf("expected custom managed label %q", key)
|
|
}
|
|
}
|
|
|
|
for _, key := range []string{
|
|
"example.corp/annotation",
|
|
"example.corp/trimmed-annotation",
|
|
} {
|
|
if !m.HasAnnotation(key) {
|
|
t.Fatalf("expected custom managed annotation %q", key)
|
|
}
|
|
}
|
|
|
|
if m.HasLabel("") {
|
|
t.Fatalf("empty label must not be managed")
|
|
}
|
|
|
|
if m.HasAnnotation("") {
|
|
t.Fatalf("empty annotation must not be managed")
|
|
}
|
|
})
|
|
|
|
t.Run("matching is exact and case-sensitive", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := NewManagedMetadata(
|
|
[]string{
|
|
"example.corp/managed",
|
|
},
|
|
[]string{
|
|
"example.corp/managed",
|
|
},
|
|
)
|
|
|
|
if !m.HasLabel("example.corp/managed") {
|
|
t.Fatalf("expected exact label match")
|
|
}
|
|
|
|
if m.HasLabel("Example.Corp/managed") {
|
|
t.Fatalf("expected label lookup to be case-sensitive")
|
|
}
|
|
|
|
if m.HasLabel(" example.corp/managed ") {
|
|
t.Fatalf("expected label lookup not to trim lookup key")
|
|
}
|
|
|
|
if !m.HasAnnotation("example.corp/managed") {
|
|
t.Fatalf("expected exact annotation match")
|
|
}
|
|
|
|
if m.HasAnnotation("Example.Corp/managed") {
|
|
t.Fatalf("expected annotation lookup to be case-sensitive")
|
|
}
|
|
|
|
if m.HasAnnotation(" example.corp/managed ") {
|
|
t.Fatalf("expected annotation lookup not to trim lookup key")
|
|
}
|
|
})
|
|
|
|
t.Run("unknown metadata is not managed", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := NewManagedMetadata(nil, nil)
|
|
|
|
if m.HasLabel("example.corp/not-managed") {
|
|
t.Fatalf("unexpected managed label")
|
|
}
|
|
|
|
if m.HasAnnotation("example.corp/not-managed") {
|
|
t.Fatalf("unexpected managed annotation")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestStringSet(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
in []string
|
|
want map[string]struct{}
|
|
}{
|
|
{
|
|
name: "empty input returns nil",
|
|
in: nil,
|
|
want: nil,
|
|
},
|
|
{
|
|
name: "trims values skips blanks and deduplicates",
|
|
in: []string{
|
|
"alpha",
|
|
" alpha ",
|
|
"",
|
|
" ",
|
|
"beta",
|
|
},
|
|
want: map[string]struct{}{
|
|
"alpha": {},
|
|
"beta": {},
|
|
},
|
|
},
|
|
{
|
|
name: "case sensitive",
|
|
in: []string{
|
|
"alpha",
|
|
"Alpha",
|
|
},
|
|
want: map[string]struct{}{
|
|
"alpha": {},
|
|
"Alpha": {},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := stringSet(tt.in...)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Fatalf("expected %#v, got %#v", tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCompactStrings(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
in []string
|
|
want []string
|
|
}{
|
|
{
|
|
name: "empty input returns nil",
|
|
in: nil,
|
|
want: nil,
|
|
},
|
|
{
|
|
name: "trims values and skips blanks",
|
|
in: []string{
|
|
"alpha",
|
|
" alpha ",
|
|
"",
|
|
" ",
|
|
"beta",
|
|
},
|
|
want: []string{
|
|
"alpha",
|
|
"alpha",
|
|
"beta",
|
|
},
|
|
},
|
|
{
|
|
name: "does not deduplicate prefixes",
|
|
in: []string{
|
|
"alpha/",
|
|
"alpha/",
|
|
},
|
|
want: []string{
|
|
"alpha/",
|
|
"alpha/",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := compactStrings(tt.in...)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Fatalf("expected %#v, got %#v", tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAddStrings(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
set := map[string]struct{}{
|
|
"existing": {},
|
|
}
|
|
|
|
addStrings(
|
|
set,
|
|
"alpha",
|
|
" alpha ",
|
|
"",
|
|
" ",
|
|
"beta",
|
|
)
|
|
|
|
want := map[string]struct{}{
|
|
"existing": {},
|
|
"alpha": {},
|
|
"beta": {},
|
|
}
|
|
|
|
if !reflect.DeepEqual(set, want) {
|
|
t.Fatalf("expected %#v, got %#v", want, set)
|
|
}
|
|
}
|
|
|
|
func TestManagedMetadataAddMethods(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := ManagedMetadata{
|
|
labels: map[string]struct{}{},
|
|
annotations: map[string]struct{}{},
|
|
}
|
|
|
|
m.addLabels("example.corp/label", " example.corp/trimmed-label ", "")
|
|
m.addAnnotations("example.corp/annotation", " example.corp/trimmed-annotation ", "")
|
|
|
|
if !m.HasLabel("example.corp/label") {
|
|
t.Fatalf("expected added label")
|
|
}
|
|
|
|
if !m.HasLabel("example.corp/trimmed-label") {
|
|
t.Fatalf("expected trimmed added label")
|
|
}
|
|
|
|
if !m.HasAnnotation("example.corp/annotation") {
|
|
t.Fatalf("expected added annotation")
|
|
}
|
|
|
|
if !m.HasAnnotation("example.corp/trimmed-annotation") {
|
|
t.Fatalf("expected trimmed added annotation")
|
|
}
|
|
|
|
if m.HasLabel("") {
|
|
t.Fatalf("empty label must not be added")
|
|
}
|
|
|
|
if m.HasAnnotation("") {
|
|
t.Fatalf("empty annotation must not be added")
|
|
}
|
|
}
|
|
|
|
func TestManagedMetadataHasAnnotationPrefix(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := ManagedMetadata{
|
|
annotations: map[string]struct{}{
|
|
"example.corp/exact": {},
|
|
},
|
|
annotationPrefixes: []string{
|
|
"example.corp/prefix/",
|
|
},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "exact annotation",
|
|
key: "example.corp/exact",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "prefix annotation",
|
|
key: "example.corp/prefix/value",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "prefix itself also matches",
|
|
key: "example.corp/prefix/",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "similar prefix does not match",
|
|
key: "example.corp/prefix-other/value",
|
|
want: false,
|
|
},
|
|
{
|
|
name: "unknown annotation",
|
|
key: "example.corp/unknown",
|
|
want: false,
|
|
},
|
|
{
|
|
name: "case sensitive prefix",
|
|
key: "Example.Corp/prefix/value",
|
|
want: false,
|
|
},
|
|
{
|
|
name: "empty key",
|
|
key: "",
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := m.HasAnnotation(tt.key)
|
|
if got != tt.want {
|
|
t.Fatalf("expected %t, got %t", tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestObjectSkipRuleShouldSkip(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
rule ObjectSkipRule
|
|
labels map[string]string
|
|
annotations map[string]string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "empty rule does not skip",
|
|
rule: ObjectSkipRule{},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "matching label skips",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "missing label does not skip",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
labels: nil,
|
|
want: false,
|
|
},
|
|
{
|
|
name: "non matching label value does not skip",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "human",
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "label match is case-sensitive",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "Controller",
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "matching annotation skips",
|
|
rule: ObjectSkipRule{
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
},
|
|
annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "missing annotation does not skip",
|
|
rule: ObjectSkipRule{
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
},
|
|
annotations: nil,
|
|
want: false,
|
|
},
|
|
{
|
|
name: "non matching annotation value does not skip",
|
|
rule: ObjectSkipRule{
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
},
|
|
annotations: map[string]string{
|
|
"example.corp/skip": "false",
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "all labels must match",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
"owner": "capsule",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "controller",
|
|
"owner": "other",
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "all annotations must match",
|
|
rule: ObjectSkipRule{
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
"example.corp/owner": "capsule",
|
|
},
|
|
},
|
|
annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
"example.corp/owner": "other",
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "labels and annotations must both match",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "matching label but missing required annotation does not skip",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
annotations: nil,
|
|
want: false,
|
|
},
|
|
{
|
|
name: "missing key must not match empty expected value",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"empty": "",
|
|
},
|
|
},
|
|
labels: nil,
|
|
want: false,
|
|
},
|
|
{
|
|
name: "present empty value matches empty expected value",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"empty": "",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"empty": "",
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "extra labels and annotations do not prevent match",
|
|
rule: ObjectSkipRule{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
labels: map[string]string{
|
|
"managed-by": "controller",
|
|
"extra": "value",
|
|
},
|
|
annotations: map[string]string{
|
|
"extra": "value",
|
|
},
|
|
want: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := tt.rule.ShouldSkip(tt.labels, tt.annotations)
|
|
if got != tt.want {
|
|
t.Fatalf("expected %t, got %t", tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestObjectSkipRuleShouldSkipNilReceiver(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var rule *ObjectSkipRule
|
|
|
|
if rule.ShouldSkip(
|
|
map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
nil,
|
|
) {
|
|
t.Fatalf("nil rule must not skip")
|
|
}
|
|
}
|
|
|
|
func TestDefaultObjectSkipRules(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
rules := DefaultObjectSkipRules()
|
|
if len(rules) != 2 {
|
|
t.Fatalf("expected three default skip rules, got %d", len(rules))
|
|
}
|
|
|
|
if got := rules[0].Labels[NewManagedByCapsuleLabel]; got != ValueController {
|
|
t.Fatalf("expected default skip label %q=%q, got %q", NewManagedByCapsuleLabel, ValueController, got)
|
|
}
|
|
|
|
if got := rules[1].Labels[NewManagedByCapsuleLabel]; got != ValueControllerResources {
|
|
t.Fatalf("expected legacy default skip label %q=%q, got %q", NewManagedByCapsuleLabel, ValueControllerResources, got)
|
|
}
|
|
|
|
for _, rule := range rules {
|
|
if len(rule.Annotations) != 0 {
|
|
t.Fatalf("expected no default skip annotations, got %#v", rule.Annotations)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestShouldSkipObjectByRules(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
obj *metav1.PartialObjectMetadata
|
|
rules []ObjectSkipRule
|
|
want bool
|
|
}{
|
|
{
|
|
name: "nil object does not skip",
|
|
obj: nil,
|
|
rules: DefaultObjectSkipRules(),
|
|
want: false,
|
|
},
|
|
{
|
|
name: "nil rules do not skip",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
NewManagedByCapsuleLabel: ValueController,
|
|
},
|
|
nil,
|
|
),
|
|
rules: nil,
|
|
want: false,
|
|
},
|
|
{
|
|
name: "empty rules do not skip",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
NewManagedByCapsuleLabel: ValueController,
|
|
},
|
|
nil,
|
|
),
|
|
rules: []ObjectSkipRule{},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "default Capsule controller-managed object skips",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
NewManagedByCapsuleLabel: ValueController,
|
|
},
|
|
nil,
|
|
),
|
|
rules: DefaultObjectSkipRules(),
|
|
want: true,
|
|
},
|
|
{
|
|
name: "legacy Capsule resources object skips",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
NewManagedByCapsuleLabel: ValueControllerResources,
|
|
},
|
|
nil,
|
|
),
|
|
rules: DefaultObjectSkipRules(),
|
|
want: true,
|
|
},
|
|
{
|
|
name: "default skip is case-sensitive",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
NewManagedByCapsuleLabel: "Controller",
|
|
},
|
|
nil,
|
|
),
|
|
rules: DefaultObjectSkipRules(),
|
|
want: false,
|
|
},
|
|
{
|
|
name: "plain managed-by controller is not skipped by default",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
nil,
|
|
),
|
|
rules: DefaultObjectSkipRules(),
|
|
want: false,
|
|
},
|
|
{
|
|
name: "non matching object does not skip",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
NewManagedByCapsuleLabel: "human",
|
|
},
|
|
nil,
|
|
),
|
|
rules: DefaultObjectSkipRules(),
|
|
want: false,
|
|
},
|
|
{
|
|
name: "any matching rule skips",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
"app": "demo",
|
|
},
|
|
map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
),
|
|
rules: []ObjectSkipRule{
|
|
{
|
|
Labels: map[string]string{
|
|
"app": "other",
|
|
},
|
|
},
|
|
{
|
|
Annotations: map[string]string{
|
|
"example.corp/skip": "true",
|
|
},
|
|
},
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "object without labels and annotations does not skip",
|
|
obj: objectWithMetadata(nil, nil),
|
|
rules: []ObjectSkipRule{
|
|
{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "empty skip rule does not skip object",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
"app": "demo",
|
|
},
|
|
nil,
|
|
),
|
|
rules: []ObjectSkipRule{
|
|
{},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "custom plain managed-by rule skips",
|
|
obj: objectWithMetadata(
|
|
map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
nil,
|
|
),
|
|
rules: []ObjectSkipRule{
|
|
{
|
|
Labels: map[string]string{
|
|
"managed-by": "controller",
|
|
},
|
|
},
|
|
},
|
|
want: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := ShouldSkipObjectByRules(tt.obj, tt.rules)
|
|
if got != tt.want {
|
|
t.Fatalf("expected %t, got %t", tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func objectWithMetadata(
|
|
labels map[string]string,
|
|
annotations map[string]string,
|
|
) *metav1.PartialObjectMetadata {
|
|
return &metav1.PartialObjectMetadata{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: labels,
|
|
Annotations: annotations,
|
|
},
|
|
}
|
|
}
|