Files

120 lines
3.4 KiB
Go

// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package resources
import (
"strings"
"testing"
corev1 "k8s.io/api/core/v1"
k8smeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
"github.com/projectcapsule/capsule/pkg/api/processor"
)
func TestCollectorAddToAccumulationClusterScopedObjects(t *testing.T) {
t.Parallel()
mapper := k8smeta.NewDefaultRESTMapper([]schema.GroupVersion{{Version: "v1"}})
mapper.Add(schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"}, k8smeta.RESTScopeNamespace)
mapper.Add(schema.GroupVersionKind{Version: "v1", Kind: "Namespace"}, k8smeta.RESTScopeRoot)
collector := NewCollector(nil, mapper)
t.Run("allows namespaced object", func(t *testing.T) {
t.Parallel()
acc := processor.Accumulator{}
obj := newUnstructured("v1", "ConfigMap", "default", "example")
if err := collector.AddToAccumulation(nil, nil, CollectorOptions{Accumulator: acc}, capsuleResourceSpec(), obj, "test", true); err != nil {
t.Fatalf("expected no error, got %v", err)
}
if len(acc) != 1 {
t.Fatalf("expected object to be accumulated, got %d items", len(acc))
}
})
t.Run("rejects cluster scoped object by default", func(t *testing.T) {
t.Parallel()
acc := processor.Accumulator{}
obj := newUnstructured("v1", "Namespace", "", "example")
err := collector.AddToAccumulation(nil, nil, CollectorOptions{Accumulator: acc}, capsuleResourceSpec(), obj, "test", true)
if err == nil {
t.Fatal("expected error, got nil")
}
if !strings.Contains(err.Error(), "cluster-scoped kind v1/Namespace is not allowed") {
t.Fatalf("expected cluster scoped error, got %v", err)
}
if len(acc) != 0 {
t.Fatalf("expected object not to be accumulated, got %d items", len(acc))
}
})
t.Run("allows cluster scoped object when configured", func(t *testing.T) {
t.Parallel()
acc := processor.Accumulator{}
obj := newUnstructured("v1", "Namespace", "", "example")
opts := CollectorOptions{
Accumulator: acc,
AllowClusterScopedObjects: true,
}
if err := collector.AddToAccumulation(nil, nil, opts, capsuleResourceSpec(), obj, "test", true); err != nil {
t.Fatalf("expected no error, got %v", err)
}
if len(acc) != 1 {
t.Fatalf("expected object to be accumulated, got %d items", len(acc))
}
})
t.Run("keeps allowing namespaced object targeting a namespace", func(t *testing.T) {
t.Parallel()
acc := processor.Accumulator{}
obj := newUnstructured("v1", "ConfigMap", "source", "example")
opts := CollectorOptions{
Accumulator: acc,
AllowClusterScopedObjects: true,
}
target := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "tenant-a"}}
if err := collector.AddToAccumulation(nil, target, opts, capsuleResourceSpec(), obj, "test", true); err != nil {
t.Fatalf("expected no error, got %v", err)
}
if len(acc) != 1 {
t.Fatalf("expected object to be accumulated, got %d items", len(acc))
}
})
}
func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured {
obj := &unstructured.Unstructured{}
obj.SetAPIVersion(apiVersion)
obj.SetKind(kind)
obj.SetNamespace(namespace)
obj.SetName(name)
return obj
}
func capsuleResourceSpec() capsulev1beta2.ResourceSpec {
return capsulev1beta2.ResourceSpec{}
}