1
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",
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