1
2
3
4 package task
5
6 import (
7 "testing"
8
9 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
10 "sigs.k8s.io/cli-utils/pkg/apply/cache"
11 "sigs.k8s.io/cli-utils/pkg/apply/event"
12 "sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
13 "sigs.k8s.io/cli-utils/pkg/common"
14 "sigs.k8s.io/cli-utils/pkg/inventory"
15 "sigs.k8s.io/cli-utils/pkg/object"
16 )
17
18 var namespace = "test-namespace"
19
20 var inventoryObj = &unstructured.Unstructured{
21 Object: map[string]interface{}{
22 "apiVersion": "v1",
23 "kind": "ConfigMap",
24 "metadata": map[string]interface{}{
25 "name": "test-inventory-obj",
26 "namespace": namespace,
27 "labels": map[string]interface{}{
28 common.InventoryLabel: "test-app-label",
29 },
30 },
31 },
32 }
33
34 var localInv = inventory.WrapInventoryInfoObj(inventoryObj)
35
36 var obj1 = &unstructured.Unstructured{
37 Object: map[string]interface{}{
38 "apiVersion": "v1",
39 "kind": "Pod",
40 "metadata": map[string]interface{}{
41 "name": "obj1",
42 "namespace": namespace,
43 },
44 },
45 }
46
47 var obj2 = &unstructured.Unstructured{
48 Object: map[string]interface{}{
49 "apiVersion": "batch/v1",
50 "kind": "Job",
51 "metadata": map[string]interface{}{
52 "name": "obj2",
53 "namespace": namespace,
54 },
55 },
56 }
57
58 var obj3 = &unstructured.Unstructured{
59 Object: map[string]interface{}{
60 "apiVersion": "apps/v1",
61 "kind": "Deployment",
62 "metadata": map[string]interface{}{
63 "name": "obj3",
64 "namespace": "different-namespace",
65 },
66 },
67 }
68
69 const taskName = "test-inventory-task"
70
71 func TestInvAddTask(t *testing.T) {
72 id1 := object.UnstructuredToObjMetadata(obj1)
73 id2 := object.UnstructuredToObjMetadata(obj2)
74 id3 := object.UnstructuredToObjMetadata(obj3)
75
76 tests := map[string]struct {
77 initialObjs object.ObjMetadataSet
78 applyObjs []*unstructured.Unstructured
79 expectedObjs object.ObjMetadataSet
80 }{
81 "no initial inventory and no apply objects; no merged inventory": {
82 initialObjs: object.ObjMetadataSet{},
83 applyObjs: []*unstructured.Unstructured{},
84 expectedObjs: object.ObjMetadataSet{},
85 },
86 "no initial inventory, one apply object; one merged inventory": {
87 initialObjs: object.ObjMetadataSet{},
88 applyObjs: []*unstructured.Unstructured{obj1},
89 expectedObjs: object.ObjMetadataSet{id1},
90 },
91 "one initial inventory, no apply object; one merged inventory": {
92 initialObjs: object.ObjMetadataSet{id2},
93 applyObjs: []*unstructured.Unstructured{},
94 expectedObjs: object.ObjMetadataSet{id2},
95 },
96 "one initial inventory, one apply object; one merged inventory": {
97 initialObjs: object.ObjMetadataSet{id3},
98 applyObjs: []*unstructured.Unstructured{obj3},
99 expectedObjs: object.ObjMetadataSet{id3},
100 },
101 "three initial inventory, two same objects; three merged inventory": {
102 initialObjs: object.ObjMetadataSet{id1, id2, id3},
103 applyObjs: []*unstructured.Unstructured{obj2, obj3},
104 expectedObjs: object.ObjMetadataSet{id1, id2, id3},
105 },
106 }
107
108 for name, tc := range tests {
109 t.Run(name, func(t *testing.T) {
110 client := inventory.NewFakeClient(tc.initialObjs)
111 eventChannel := make(chan event.Event)
112 resourceCache := cache.NewResourceCacheMap()
113 context := taskrunner.NewTaskContext(eventChannel, resourceCache)
114
115 task := InvAddTask{
116 TaskName: taskName,
117 InvClient: client,
118 InvInfo: nil,
119 Objects: tc.applyObjs,
120 }
121 if taskName != task.Name() {
122 t.Errorf("expected task name (%s), got (%s)", taskName, task.Name())
123 }
124 applyIds := object.UnstructuredSetToObjMetadataSet(tc.applyObjs)
125 if !task.Identifiers().Equal(applyIds) {
126 t.Errorf("expected task ids (%s), got (%s)", applyIds, task.Identifiers())
127 }
128 task.Start(context)
129 result := <-context.TaskChannel()
130 if result.Err != nil {
131 t.Errorf("unexpected error running InvAddTask: %s", result.Err)
132 }
133 actual, _ := client.GetClusterObjs(nil)
134 if !tc.expectedObjs.Equal(actual) {
135 t.Errorf("expected merged inventory (%s), got (%s)", tc.expectedObjs, actual)
136 }
137 })
138 }
139 }
140
141 func TestInventoryNamespaceInSet(t *testing.T) {
142 inventoryNamespace := createNamespace(namespace)
143
144 tests := map[string]struct {
145 inv inventory.Info
146 objects []*unstructured.Unstructured
147 namespace *unstructured.Unstructured
148 }{
149 "Nil inventory object, no resources returns nil namespace": {
150 inv: nil,
151 objects: []*unstructured.Unstructured{},
152 namespace: nil,
153 },
154 "Inventory object, but no resources returns nil namespace": {
155 inv: localInv,
156 objects: []*unstructured.Unstructured{},
157 namespace: nil,
158 },
159 "Inventory object, resources with no namespace returns nil namespace": {
160 inv: localInv,
161 objects: []*unstructured.Unstructured{obj1, obj2},
162 namespace: nil,
163 },
164 "Inventory object, different namespace returns nil namespace": {
165 inv: localInv,
166 objects: []*unstructured.Unstructured{createNamespace("foo")},
167 namespace: nil,
168 },
169 "Inventory object, inventory namespace returns inventory namespace": {
170 inv: localInv,
171 objects: []*unstructured.Unstructured{obj1, inventoryNamespace, obj3},
172 namespace: inventoryNamespace,
173 },
174 }
175
176 for name, tc := range tests {
177 t.Run(name, func(t *testing.T) {
178 actualNamespace := inventoryNamespaceInSet(tc.inv, tc.objects)
179 if tc.namespace != actualNamespace {
180 t.Fatalf("expected namespace (%v), got (%v)", tc.namespace, actualNamespace)
181 }
182 })
183 }
184 }
185
186 func createNamespace(ns string) *unstructured.Unstructured {
187 return &unstructured.Unstructured{
188 Object: map[string]interface{}{
189 "apiVersion": "v1",
190 "kind": "Namespace",
191 "metadata": map[string]interface{}{
192 "name": ns,
193 },
194 },
195 }
196 }
197
View as plain text