...

Source file src/sigs.k8s.io/cli-utils/pkg/apply/task/inv_add_task_test.go

Documentation: sigs.k8s.io/cli-utils/pkg/apply/task

     1  // Copyright 2021 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     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