...

Source file src/k8s.io/kubernetes/pkg/controller/namespace/deletion/status_condition_utils_test.go

Documentation: k8s.io/kubernetes/pkg/controller/namespace/deletion

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package deletion
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/runtime/schema"
    25  )
    26  
    27  func TestUpdateConditions(t *testing.T) {
    28  	tests := []struct {
    29  		name string
    30  
    31  		newConditions  []v1.NamespaceCondition
    32  		startingStatus *v1.NamespaceStatus
    33  
    34  		expecteds []v1.NamespaceCondition
    35  	}{
    36  		{
    37  			name: "leave unknown",
    38  
    39  			newConditions: []v1.NamespaceCondition{},
    40  			startingStatus: &v1.NamespaceStatus{
    41  				Conditions: []v1.NamespaceCondition{
    42  					{Type: "unknown", Status: v1.ConditionTrue},
    43  				},
    44  			},
    45  			expecteds: []v1.NamespaceCondition{
    46  				{Type: "unknown", Status: v1.ConditionTrue},
    47  				*newSuccessfulCondition(v1.NamespaceDeletionDiscoveryFailure),
    48  				*newSuccessfulCondition(v1.NamespaceDeletionGVParsingFailure),
    49  				*newSuccessfulCondition(v1.NamespaceDeletionContentFailure),
    50  				*newSuccessfulCondition(v1.NamespaceContentRemaining),
    51  				*newSuccessfulCondition(v1.NamespaceFinalizersRemaining),
    52  			},
    53  		},
    54  		{
    55  			name: "replace with success",
    56  
    57  			newConditions: []v1.NamespaceCondition{},
    58  			startingStatus: &v1.NamespaceStatus{
    59  				Conditions: []v1.NamespaceCondition{
    60  					{Type: v1.NamespaceDeletionDiscoveryFailure, Status: v1.ConditionTrue},
    61  				},
    62  			},
    63  			expecteds: []v1.NamespaceCondition{
    64  				*newSuccessfulCondition(v1.NamespaceDeletionDiscoveryFailure),
    65  				*newSuccessfulCondition(v1.NamespaceDeletionGVParsingFailure),
    66  				*newSuccessfulCondition(v1.NamespaceDeletionContentFailure),
    67  				*newSuccessfulCondition(v1.NamespaceContentRemaining),
    68  				*newSuccessfulCondition(v1.NamespaceFinalizersRemaining),
    69  			},
    70  		},
    71  		{
    72  			name: "leave different order",
    73  
    74  			newConditions: []v1.NamespaceCondition{},
    75  			startingStatus: &v1.NamespaceStatus{
    76  				Conditions: []v1.NamespaceCondition{
    77  					{Type: v1.NamespaceDeletionGVParsingFailure, Status: v1.ConditionTrue},
    78  					{Type: v1.NamespaceDeletionDiscoveryFailure, Status: v1.ConditionTrue},
    79  				},
    80  			},
    81  			expecteds: []v1.NamespaceCondition{
    82  				*newSuccessfulCondition(v1.NamespaceDeletionGVParsingFailure),
    83  				*newSuccessfulCondition(v1.NamespaceDeletionDiscoveryFailure),
    84  				*newSuccessfulCondition(v1.NamespaceDeletionContentFailure),
    85  				*newSuccessfulCondition(v1.NamespaceContentRemaining),
    86  				*newSuccessfulCondition(v1.NamespaceFinalizersRemaining),
    87  			},
    88  		},
    89  		{
    90  			name: "overwrite with failure",
    91  
    92  			newConditions: []v1.NamespaceCondition{
    93  				{Type: v1.NamespaceDeletionGVParsingFailure, Status: v1.ConditionTrue, Reason: "foo", Message: "bar"},
    94  			},
    95  			startingStatus: &v1.NamespaceStatus{
    96  				Conditions: []v1.NamespaceCondition{
    97  					{Type: v1.NamespaceDeletionGVParsingFailure, Status: v1.ConditionFalse},
    98  					{Type: v1.NamespaceDeletionDiscoveryFailure, Status: v1.ConditionTrue},
    99  				},
   100  			},
   101  			expecteds: []v1.NamespaceCondition{
   102  				{Type: v1.NamespaceDeletionGVParsingFailure, Status: v1.ConditionTrue, Reason: "foo", Message: "bar"},
   103  				*newSuccessfulCondition(v1.NamespaceDeletionDiscoveryFailure),
   104  				*newSuccessfulCondition(v1.NamespaceDeletionContentFailure),
   105  				*newSuccessfulCondition(v1.NamespaceContentRemaining),
   106  				*newSuccessfulCondition(v1.NamespaceFinalizersRemaining),
   107  			},
   108  		},
   109  		{
   110  			name: "write new failure",
   111  
   112  			newConditions: []v1.NamespaceCondition{
   113  				{Type: v1.NamespaceDeletionGVParsingFailure, Status: v1.ConditionTrue, Reason: "foo", Message: "bar"},
   114  			},
   115  			startingStatus: &v1.NamespaceStatus{
   116  				Conditions: []v1.NamespaceCondition{
   117  					{Type: v1.NamespaceDeletionDiscoveryFailure, Status: v1.ConditionTrue},
   118  				},
   119  			},
   120  			expecteds: []v1.NamespaceCondition{
   121  				*newSuccessfulCondition(v1.NamespaceDeletionDiscoveryFailure),
   122  				{Type: v1.NamespaceDeletionGVParsingFailure, Status: v1.ConditionTrue, Reason: "foo", Message: "bar"},
   123  				*newSuccessfulCondition(v1.NamespaceDeletionContentFailure),
   124  				*newSuccessfulCondition(v1.NamespaceContentRemaining),
   125  				*newSuccessfulCondition(v1.NamespaceFinalizersRemaining),
   126  			},
   127  		},
   128  	}
   129  
   130  	for _, test := range tests {
   131  		t.Run(test.name, func(t *testing.T) {
   132  			updateConditions(test.startingStatus, test.newConditions)
   133  
   134  			actuals := test.startingStatus.Conditions
   135  			if len(actuals) != len(test.expecteds) {
   136  				t.Fatal(actuals)
   137  			}
   138  			for i := range actuals {
   139  				actual := actuals[i]
   140  				expected := test.expecteds[i]
   141  				expected.LastTransitionTime = actual.LastTransitionTime
   142  				if !reflect.DeepEqual(expected, actual) {
   143  					t.Error(actual)
   144  				}
   145  			}
   146  		})
   147  	}
   148  }
   149  
   150  func TestProcessContentTotals(t *testing.T) {
   151  	tests := []struct {
   152  		name string
   153  
   154  		contentTotals allGVRDeletionMetadata
   155  		expecteds     []v1.NamespaceCondition
   156  	}{
   157  		{
   158  			name: "nothing",
   159  
   160  			contentTotals: allGVRDeletionMetadata{
   161  				gvrToNumRemaining:        map[schema.GroupVersionResource]int{},
   162  				finalizersToNumRemaining: map[string]int{},
   163  			},
   164  			expecteds: []v1.NamespaceCondition{},
   165  		},
   166  		{
   167  			name: "just remaining",
   168  
   169  			contentTotals: allGVRDeletionMetadata{
   170  				gvrToNumRemaining: map[schema.GroupVersionResource]int{
   171  					{Group: "apps.k8s.io", Resource: "daemonsets"}:  5,
   172  					{Group: "apps.k8s.io", Resource: "deployments"}: 5,
   173  				},
   174  				finalizersToNumRemaining: map[string]int{},
   175  			},
   176  			expecteds: []v1.NamespaceCondition{
   177  				{Type: v1.NamespaceContentRemaining, Status: v1.ConditionTrue, Reason: "SomeResourcesRemain", Message: `Some resources are remaining: daemonsets.apps.k8s.io has 5 resource instances, deployments.apps.k8s.io has 5 resource instances`},
   178  			},
   179  		},
   180  		{
   181  			name: "just finalizers", // this shouldn't happen
   182  
   183  			contentTotals: allGVRDeletionMetadata{
   184  				gvrToNumRemaining: map[schema.GroupVersionResource]int{},
   185  				finalizersToNumRemaining: map[string]int{
   186  					"service-catalog": 6,
   187  					"kubedb":          5,
   188  				},
   189  			},
   190  			expecteds: []v1.NamespaceCondition{
   191  				{Type: v1.NamespaceFinalizersRemaining, Status: v1.ConditionTrue, Reason: "SomeFinalizersRemain", Message: `Some content in the namespace has finalizers remaining: kubedb in 5 resource instances, service-catalog in 6 resource instances`},
   192  			},
   193  		},
   194  		{
   195  			name: "both",
   196  
   197  			contentTotals: allGVRDeletionMetadata{
   198  				gvrToNumRemaining: map[schema.GroupVersionResource]int{
   199  					{Group: "apps.k8s.io", Resource: "daemonsets"}:  5,
   200  					{Group: "apps.k8s.io", Resource: "deployments"}: 5,
   201  				},
   202  				finalizersToNumRemaining: map[string]int{
   203  					"service-catalog": 6,
   204  					"kubedb":          5,
   205  				},
   206  			},
   207  			expecteds: []v1.NamespaceCondition{
   208  				{Type: v1.NamespaceContentRemaining, Status: v1.ConditionTrue, Reason: "SomeResourcesRemain", Message: `Some resources are remaining: daemonsets.apps.k8s.io has 5 resource instances, deployments.apps.k8s.io has 5 resource instances`},
   209  				{Type: v1.NamespaceFinalizersRemaining, Status: v1.ConditionTrue, Reason: "SomeFinalizersRemain", Message: `Some content in the namespace has finalizers remaining: kubedb in 5 resource instances, service-catalog in 6 resource instances`},
   210  			},
   211  		},
   212  	}
   213  
   214  	for _, test := range tests {
   215  		t.Run(test.name, func(t *testing.T) {
   216  			u := namespaceConditionUpdater{}
   217  
   218  			u.ProcessContentTotals(test.contentTotals)
   219  
   220  			actuals := u.newConditions
   221  			if len(actuals) != len(test.expecteds) {
   222  				t.Fatal(actuals)
   223  			}
   224  			for i := range actuals {
   225  				actual := actuals[i]
   226  				expected := test.expecteds[i]
   227  				expected.LastTransitionTime = actual.LastTransitionTime
   228  				if !reflect.DeepEqual(expected, actual) {
   229  					t.Error(actual)
   230  				}
   231  			}
   232  		})
   233  	}
   234  }
   235  

View as plain text