...

Source file src/sigs.k8s.io/cli-utils/pkg/apply/task/inv_set_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/inventory"
    14  	"sigs.k8s.io/cli-utils/pkg/object"
    15  	"sigs.k8s.io/cli-utils/pkg/testutil"
    16  )
    17  
    18  var objInvalid = &unstructured.Unstructured{
    19  	Object: map[string]interface{}{
    20  		"apiVersion": "apps/v1",
    21  		"kind":       "Deployment",
    22  	},
    23  }
    24  
    25  func TestInvSetTask(t *testing.T) {
    26  	id1 := object.UnstructuredToObjMetadata(obj1)
    27  	id2 := object.UnstructuredToObjMetadata(obj2)
    28  	id3 := object.UnstructuredToObjMetadata(obj3)
    29  	idInvalid := object.UnstructuredToObjMetadata(objInvalid)
    30  
    31  	tests := map[string]struct {
    32  		prevInventory  object.ObjMetadataSet
    33  		appliedObjs    object.ObjMetadataSet
    34  		failedApplies  object.ObjMetadataSet
    35  		failedDeletes  object.ObjMetadataSet
    36  		skippedApplies object.ObjMetadataSet
    37  		skippedDeletes object.ObjMetadataSet
    38  		abandonedObjs  object.ObjMetadataSet
    39  		invalidObjs    object.ObjMetadataSet
    40  		expectedObjs   object.ObjMetadataSet
    41  	}{
    42  		"no apply objs, no prune failures; no inventory": {
    43  			expectedObjs: object.ObjMetadataSet{},
    44  		},
    45  		"one apply objs, no prune failures; one inventory": {
    46  			appliedObjs:  object.ObjMetadataSet{id1},
    47  			expectedObjs: object.ObjMetadataSet{id1},
    48  		},
    49  		"no apply objs, one prune failure, in prev inventory; one inventory": {
    50  			prevInventory: object.ObjMetadataSet{id1},
    51  			failedDeletes: object.ObjMetadataSet{id1},
    52  			expectedObjs:  object.ObjMetadataSet{id1},
    53  		},
    54  		"no apply objs, one prune failure, not in prev inventory; no inventory": {
    55  			// aritifical use case: prunes come from the inventory
    56  			failedDeletes: object.ObjMetadataSet{id1},
    57  			expectedObjs:  object.ObjMetadataSet{},
    58  		},
    59  		"one apply objs, one prune failures; one inventory": {
    60  			// aritifical use case: applies and prunes are mutually exclusive.
    61  			// Delete failure overwrites apply success in object status.
    62  			appliedObjs:   object.ObjMetadataSet{id3},
    63  			failedDeletes: object.ObjMetadataSet{id3},
    64  			expectedObjs:  object.ObjMetadataSet{},
    65  		},
    66  		"two apply objs, two prune failures; three inventory": {
    67  			// aritifical use case: applies and prunes are mutually exclusive
    68  			prevInventory: object.ObjMetadataSet{id2, id3},
    69  			appliedObjs:   object.ObjMetadataSet{id1, id2},
    70  			failedDeletes: object.ObjMetadataSet{id2, id3},
    71  			expectedObjs:  object.ObjMetadataSet{id1, id2, id3},
    72  		},
    73  		"no apply objs, no apply failures, no prune failures; no inventory": {
    74  			failedApplies: object.ObjMetadataSet{id3},
    75  			expectedObjs:  object.ObjMetadataSet{},
    76  		},
    77  		"one apply failure not in prev inventory; no inventory": {
    78  			failedApplies: object.ObjMetadataSet{id3},
    79  			expectedObjs:  object.ObjMetadataSet{},
    80  		},
    81  		"one apply obj, one apply failure not in prev inventory; one inventory": {
    82  			appliedObjs:   object.ObjMetadataSet{id2},
    83  			failedApplies: object.ObjMetadataSet{id3},
    84  			expectedObjs:  object.ObjMetadataSet{id2},
    85  		},
    86  		"one apply obj, one apply failure in prev inventory; one inventory": {
    87  			appliedObjs:   object.ObjMetadataSet{id2},
    88  			failedApplies: object.ObjMetadataSet{id3},
    89  			prevInventory: object.ObjMetadataSet{id3},
    90  			expectedObjs:  object.ObjMetadataSet{id2, id3},
    91  		},
    92  		"one apply obj, two apply failures with one in prev inventory; two inventory": {
    93  			appliedObjs:   object.ObjMetadataSet{id2},
    94  			failedApplies: object.ObjMetadataSet{id1, id3},
    95  			prevInventory: object.ObjMetadataSet{id3},
    96  			expectedObjs:  object.ObjMetadataSet{id2, id3},
    97  		},
    98  		"three apply failures with two in prev inventory; two inventory": {
    99  			failedApplies: object.ObjMetadataSet{id1, id2, id3},
   100  			prevInventory: object.ObjMetadataSet{id2, id3},
   101  			expectedObjs:  object.ObjMetadataSet{id2, id3},
   102  		},
   103  		"three apply failures with three in prev inventory; three inventory": {
   104  			failedApplies: object.ObjMetadataSet{id1, id2, id3},
   105  			prevInventory: object.ObjMetadataSet{id2, id3, id1},
   106  			expectedObjs:  object.ObjMetadataSet{id2, id1, id3},
   107  		},
   108  		"one skipped apply from prev inventory; one inventory": {
   109  			prevInventory:  object.ObjMetadataSet{id1},
   110  			skippedApplies: object.ObjMetadataSet{id1},
   111  			expectedObjs:   object.ObjMetadataSet{id1},
   112  		},
   113  		"one skipped apply, no prev inventory; no inventory": {
   114  			skippedApplies: object.ObjMetadataSet{id1},
   115  			expectedObjs:   object.ObjMetadataSet{},
   116  		},
   117  		"one apply obj, one skipped apply, two prev inventory; two inventory": {
   118  			prevInventory:  object.ObjMetadataSet{id1, id2},
   119  			appliedObjs:    object.ObjMetadataSet{id2},
   120  			skippedApplies: object.ObjMetadataSet{id1},
   121  			expectedObjs:   object.ObjMetadataSet{id1, id2},
   122  		},
   123  		"one skipped delete from prev inventory; one inventory": {
   124  			prevInventory:  object.ObjMetadataSet{id1},
   125  			skippedDeletes: object.ObjMetadataSet{id1},
   126  			expectedObjs:   object.ObjMetadataSet{id1},
   127  		},
   128  		"one apply obj, one skipped delete, two prev inventory; two inventory": {
   129  			prevInventory:  object.ObjMetadataSet{id1, id2},
   130  			appliedObjs:    object.ObjMetadataSet{id2},
   131  			skippedDeletes: object.ObjMetadataSet{id1},
   132  			expectedObjs:   object.ObjMetadataSet{id1, id2},
   133  		},
   134  		"two apply obj, one abandoned, three in prev inventory; two inventory": {
   135  			prevInventory: object.ObjMetadataSet{id1, id2, id3},
   136  			appliedObjs:   object.ObjMetadataSet{id1, id2},
   137  			abandonedObjs: object.ObjMetadataSet{id3},
   138  			expectedObjs:  object.ObjMetadataSet{id1, id2},
   139  		},
   140  		"two abandoned, two in prev inventory; no inventory": {
   141  			prevInventory: object.ObjMetadataSet{id2, id3},
   142  			abandonedObjs: object.ObjMetadataSet{id2, id3},
   143  			expectedObjs:  object.ObjMetadataSet{},
   144  		},
   145  		"same obj skipped delete and abandoned, one in prev inventory; no inventory": {
   146  			prevInventory:  object.ObjMetadataSet{id3},
   147  			skippedDeletes: object.ObjMetadataSet{id3},
   148  			abandonedObjs:  object.ObjMetadataSet{id3},
   149  			expectedObjs:   object.ObjMetadataSet{},
   150  		},
   151  		"preserve invalid objects in the inventory": {
   152  			prevInventory: object.ObjMetadataSet{id3, idInvalid},
   153  			appliedObjs:   object.ObjMetadataSet{id3},
   154  			invalidObjs:   object.ObjMetadataSet{idInvalid},
   155  			expectedObjs:  object.ObjMetadataSet{id3, idInvalid},
   156  		},
   157  		"ignore invalid objects not in the inventory": {
   158  			prevInventory: object.ObjMetadataSet{id3},
   159  			appliedObjs:   object.ObjMetadataSet{id3},
   160  			invalidObjs:   object.ObjMetadataSet{idInvalid},
   161  			expectedObjs:  object.ObjMetadataSet{id3},
   162  		},
   163  	}
   164  
   165  	for name, tc := range tests {
   166  		t.Run(name, func(t *testing.T) {
   167  			client := inventory.NewFakeClient(object.ObjMetadataSet{})
   168  			eventChannel := make(chan event.Event)
   169  			resourceCache := cache.NewResourceCacheMap()
   170  			context := taskrunner.NewTaskContext(eventChannel, resourceCache)
   171  
   172  			task := InvSetTask{
   173  				TaskName:      taskName,
   174  				InvClient:     client,
   175  				InvInfo:       nil,
   176  				PrevInventory: tc.prevInventory,
   177  			}
   178  			im := context.InventoryManager()
   179  			for _, applyObj := range tc.appliedObjs {
   180  				im.AddSuccessfulApply(applyObj, "unusued-uid", int64(0))
   181  			}
   182  			for _, applyFailure := range tc.failedApplies {
   183  				im.AddFailedApply(applyFailure)
   184  			}
   185  			for _, pruneObj := range tc.failedDeletes {
   186  				im.AddFailedDelete(pruneObj)
   187  			}
   188  			for _, skippedApply := range tc.skippedApplies {
   189  				im.AddSkippedApply(skippedApply)
   190  			}
   191  			for _, skippedDelete := range tc.skippedDeletes {
   192  				im.AddSkippedDelete(skippedDelete)
   193  			}
   194  			for _, abandonedObj := range tc.abandonedObjs {
   195  				context.AddAbandonedObject(abandonedObj)
   196  			}
   197  			for _, invalidObj := range tc.invalidObjs {
   198  				context.AddInvalidObject(invalidObj)
   199  			}
   200  			if taskName != task.Name() {
   201  				t.Errorf("expected task name (%s), got (%s)", taskName, task.Name())
   202  			}
   203  			task.Start(context)
   204  			result := <-context.TaskChannel()
   205  			if result.Err != nil {
   206  				t.Errorf("unexpected error running InvAddTask: %s", result.Err)
   207  			}
   208  			actual, _ := client.GetClusterObjs(nil)
   209  			testutil.AssertEqual(t, tc.expectedObjs, actual,
   210  				"Actual cluster objects (%d) do not match expected cluster objects (%d)",
   211  				len(actual), len(tc.expectedObjs))
   212  		})
   213  	}
   214  }
   215  

View as plain text