cli-utils/pkg/object/dependson/annotation_test.go

201 lines
4.9 KiB
Go

// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
//
package dependson
import (
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
var u1 = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "unused",
"namespace": "unused",
"annotations": map[string]interface{}{
Annotation: "test-group/test-kind/cluster-obj",
},
},
},
}
var u2 = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "unused",
"namespace": "unused",
"annotations": map[string]interface{}{
Annotation: "test-group/namespaces/test-namespace/test-kind/namespaced-obj",
},
},
},
}
var multipleAnnotations = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "unused",
"namespace": "unused",
"annotations": map[string]interface{}{
Annotation: "test-group/namespaces/test-namespace/test-kind/namespaced-obj," +
"test-group/test-kind/cluster-obj",
},
},
},
}
var noAnnotations = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "unused",
"namespace": "unused",
},
},
}
var badAnnotation = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "unused",
"namespace": "unused",
"annotations": map[string]interface{}{
Annotation: "test-group:namespaces:test-namespace:test-kind:namespaced-obj",
},
},
},
}
func TestReadAnnotation(t *testing.T) {
testCases := map[string]struct {
obj *unstructured.Unstructured
expected DependencySet
isError bool
}{
"nil object is not found": {
obj: nil,
expected: DependencySet{},
},
"Object with no annotations returns not found": {
obj: noAnnotations,
expected: DependencySet{},
},
"Unparseable depends on annotation returns not found": {
obj: badAnnotation,
expected: DependencySet{},
isError: true,
},
"Cluster-scoped object depends on annotation": {
obj: u1,
expected: DependencySet{clusterScopedObj},
},
"Namespaced object depends on annotation": {
obj: u2,
expected: DependencySet{namespacedObj},
},
"Multiple objects specified in annotation": {
obj: multipleAnnotations,
expected: DependencySet{namespacedObj, clusterScopedObj},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
actual, err := ReadAnnotation(tc.obj)
if tc.isError {
if err == nil {
t.Fatalf("expected error not received")
}
} else {
if err != nil {
t.Fatalf("unexpected error received: %s", err)
}
if !actual.Equal(tc.expected) {
t.Errorf("expected (%s), got (%s)", tc.expected, actual)
}
}
})
}
}
// getDependsOnAnnotation wraps the depends-on annotation with a pointer.
// Returns nil if the annotation is missing.
func getDependsOnAnnotation(obj *unstructured.Unstructured) *string {
value, found := obj.GetAnnotations()[Annotation]
if !found {
return nil
}
return &value
}
func TestWriteAnnotation(t *testing.T) {
testCases := map[string]struct {
obj *unstructured.Unstructured
dependson DependencySet
expected *string
isError bool
}{
"nil object": {
obj: nil,
dependson: DependencySet{},
expected: nil,
isError: true,
},
"empty mutation": {
obj: &unstructured.Unstructured{},
dependson: DependencySet{},
expected: nil,
isError: true,
},
"Namespace-scoped object": {
obj: &unstructured.Unstructured{},
dependson: DependencySet{namespacedObj},
expected: getDependsOnAnnotation(u2),
},
"Cluster-scoped object": {
obj: &unstructured.Unstructured{},
dependson: DependencySet{clusterScopedObj},
expected: getDependsOnAnnotation(u1),
},
"Multiple objects": {
obj: &unstructured.Unstructured{},
dependson: DependencySet{namespacedObj, clusterScopedObj},
expected: getDependsOnAnnotation(multipleAnnotations),
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
err := WriteAnnotation(tc.obj, tc.dependson)
if tc.isError {
if err == nil {
t.Fatalf("expected error not received")
}
} else {
if err != nil {
t.Fatalf("unexpected error received: %s", err)
}
received := getDependsOnAnnotation(tc.obj)
if received != tc.expected && (received == nil || tc.expected == nil) {
t.Errorf("\nexpected:\t%#v\nreceived:\t%#v", tc.expected, received)
}
if *received != *tc.expected {
t.Errorf("\nexpected:\t%#v\nreceived:\t%#v", *tc.expected, *received)
}
}
})
}
}