cli-utils/pkg/apply/task/inv_add_task_test.go

197 lines
5.6 KiB
Go

// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package task
import (
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/cli-utils/pkg/apply/cache"
"sigs.k8s.io/cli-utils/pkg/apply/event"
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
"sigs.k8s.io/cli-utils/pkg/common"
"sigs.k8s.io/cli-utils/pkg/inventory"
"sigs.k8s.io/cli-utils/pkg/object"
)
var namespace = "test-namespace"
var inventoryObj = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "test-inventory-obj",
"namespace": namespace,
"labels": map[string]interface{}{
common.InventoryLabel: "test-app-label",
},
},
},
}
var localInv = inventory.WrapInventoryInfoObj(inventoryObj)
var obj1 = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Pod",
"metadata": map[string]interface{}{
"name": "obj1",
"namespace": namespace,
},
},
}
var obj2 = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": map[string]interface{}{
"name": "obj2",
"namespace": namespace,
},
},
}
var obj3 = &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "obj3",
"namespace": "different-namespace",
},
},
}
const taskName = "test-inventory-task"
func TestInvAddTask(t *testing.T) {
id1 := object.UnstructuredToObjMetadata(obj1)
id2 := object.UnstructuredToObjMetadata(obj2)
id3 := object.UnstructuredToObjMetadata(obj3)
tests := map[string]struct {
initialObjs object.ObjMetadataSet
applyObjs []*unstructured.Unstructured
expectedObjs object.ObjMetadataSet
}{
"no initial inventory and no apply objects; no merged inventory": {
initialObjs: object.ObjMetadataSet{},
applyObjs: []*unstructured.Unstructured{},
expectedObjs: object.ObjMetadataSet{},
},
"no initial inventory, one apply object; one merged inventory": {
initialObjs: object.ObjMetadataSet{},
applyObjs: []*unstructured.Unstructured{obj1},
expectedObjs: object.ObjMetadataSet{id1},
},
"one initial inventory, no apply object; one merged inventory": {
initialObjs: object.ObjMetadataSet{id2},
applyObjs: []*unstructured.Unstructured{},
expectedObjs: object.ObjMetadataSet{id2},
},
"one initial inventory, one apply object; one merged inventory": {
initialObjs: object.ObjMetadataSet{id3},
applyObjs: []*unstructured.Unstructured{obj3},
expectedObjs: object.ObjMetadataSet{id3},
},
"three initial inventory, two same objects; three merged inventory": {
initialObjs: object.ObjMetadataSet{id1, id2, id3},
applyObjs: []*unstructured.Unstructured{obj2, obj3},
expectedObjs: object.ObjMetadataSet{id1, id2, id3},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
client := inventory.NewFakeInventoryClient(tc.initialObjs)
eventChannel := make(chan event.Event)
resourceCache := cache.NewResourceCacheMap()
context := taskrunner.NewTaskContext(eventChannel, resourceCache)
task := InvAddTask{
TaskName: taskName,
InvClient: client,
InvInfo: nil,
Objects: tc.applyObjs,
}
if taskName != task.Name() {
t.Errorf("expected task name (%s), got (%s)", taskName, task.Name())
}
applyIds := object.UnstructuredSetToObjMetadataSet(tc.applyObjs)
if !task.Identifiers().Equal(applyIds) {
t.Errorf("expected task ids (%s), got (%s)", applyIds, task.Identifiers())
}
task.Start(context)
result := <-context.TaskChannel()
if result.Err != nil {
t.Errorf("unexpected error running InvAddTask: %s", result.Err)
}
actual, _ := client.GetClusterObjs(nil)
if !tc.expectedObjs.Equal(actual) {
t.Errorf("expected merged inventory (%s), got (%s)", tc.expectedObjs, actual)
}
})
}
}
func TestInventoryNamespaceInSet(t *testing.T) {
inventoryNamespace := createNamespace(namespace)
tests := map[string]struct {
inv inventory.InventoryInfo
objects []*unstructured.Unstructured
namespace *unstructured.Unstructured
}{
"Nil inventory object, no resources returns nil namespace": {
inv: nil,
objects: []*unstructured.Unstructured{},
namespace: nil,
},
"Inventory object, but no resources returns nil namespace": {
inv: localInv,
objects: []*unstructured.Unstructured{},
namespace: nil,
},
"Inventory object, resources with no namespace returns nil namespace": {
inv: localInv,
objects: []*unstructured.Unstructured{obj1, obj2},
namespace: nil,
},
"Inventory object, different namespace returns nil namespace": {
inv: localInv,
objects: []*unstructured.Unstructured{createNamespace("foo")},
namespace: nil,
},
"Inventory object, inventory namespace returns inventory namespace": {
inv: localInv,
objects: []*unstructured.Unstructured{obj1, inventoryNamespace, obj3},
namespace: inventoryNamespace,
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
actualNamespace := inventoryNamespaceInSet(tc.inv, tc.objects)
if tc.namespace != actualNamespace {
t.Fatalf("expected namespace (%v), got (%v)", tc.namespace, actualNamespace)
}
})
}
}
func createNamespace(ns string) *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": ns,
},
},
}
}