istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/kstatus/helper_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package kstatus 16 17 import ( 18 "reflect" 19 "testing" 20 "time" 21 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 k8s "sigs.k8s.io/gateway-api/apis/v1beta1" 24 ) 25 26 func TestUpdateConditionIfChanged(t *testing.T) { 27 original := metav1.Condition{ 28 Type: string(k8s.RouteConditionResolvedRefs), 29 Reason: string(k8s.RouteReasonResolvedRefs), 30 Status: StatusTrue, 31 Message: "All references resolved", 32 LastTransitionTime: metav1.Now(), 33 } 34 transitionTime := metav1.NewTime(original.LastTransitionTime.Add(1 * time.Second)) 35 statusChanged := metav1.Condition{ 36 Type: string(k8s.RouteConditionResolvedRefs), 37 Reason: string(k8s.RouteReasonResolvedRefs), 38 Status: StatusFalse, 39 Message: "invalid backend", 40 LastTransitionTime: transitionTime, 41 } 42 messageChanged := metav1.Condition{ 43 Type: string(k8s.RouteConditionResolvedRefs), 44 Reason: string(k8s.RouteReasonResolvedRefs), 45 Status: StatusTrue, 46 Message: "foo", 47 LastTransitionTime: transitionTime, 48 } 49 anotherType := metav1.Condition{ 50 Type: string(k8s.RouteConditionAccepted), 51 Reason: string(k8s.RouteReasonAccepted), 52 Status: StatusTrue, 53 Message: "Route was valid", 54 LastTransitionTime: transitionTime, 55 } 56 57 tests := []struct { 58 name string 59 conditions []metav1.Condition 60 condition metav1.Condition 61 want []metav1.Condition 62 }{ 63 { 64 name: "unchanged", 65 conditions: []metav1.Condition{original}, 66 condition: func() metav1.Condition { 67 c := original 68 c.LastTransitionTime = transitionTime 69 return c 70 }(), 71 want: []metav1.Condition{original}, 72 }, 73 { 74 name: "status changed", 75 conditions: []metav1.Condition{original}, 76 condition: statusChanged, 77 want: []metav1.Condition{statusChanged}, 78 }, 79 { 80 name: "message changed", 81 conditions: []metav1.Condition{original}, 82 condition: messageChanged, 83 want: []metav1.Condition{func() metav1.Condition { 84 c := messageChanged 85 c.LastTransitionTime = original.LastTransitionTime 86 return c 87 }()}, 88 }, 89 { 90 name: "another type", 91 conditions: []metav1.Condition{original}, 92 condition: anotherType, 93 want: []metav1.Condition{original, anotherType}, 94 }, 95 } 96 for _, tt := range tests { 97 t.Run(tt.name, func(t *testing.T) { 98 if got := UpdateConditionIfChanged(tt.conditions, tt.condition); !reflect.DeepEqual(got, tt.want) { 99 t.Errorf("UpdateConditionIfChanged got %v, want %v", got, tt.want) 100 } 101 }) 102 } 103 } 104 105 func TestGetCondition(t *testing.T) { 106 transitionTime := metav1.Now() 107 108 tests := []struct { 109 name string 110 conditions []metav1.Condition 111 condition string 112 want metav1.Condition 113 }{ 114 { 115 name: "ResolvedRefs condition", 116 conditions: []metav1.Condition{ 117 { 118 Type: string(k8s.RouteConditionAccepted), 119 Reason: string(k8s.RouteReasonAccepted), 120 Status: StatusFalse, 121 Message: "invalid backend", 122 LastTransitionTime: transitionTime, 123 }, 124 { 125 Type: string(k8s.RouteConditionResolvedRefs), 126 Reason: string(k8s.RouteReasonResolvedRefs), 127 Status: StatusTrue, 128 Message: "foo", 129 LastTransitionTime: transitionTime, 130 }, 131 }, 132 condition: string(k8s.RouteConditionResolvedRefs), 133 want: metav1.Condition{ 134 Type: string(k8s.RouteConditionResolvedRefs), 135 Reason: string(k8s.RouteReasonResolvedRefs), 136 Status: StatusTrue, 137 Message: "foo", 138 LastTransitionTime: transitionTime, 139 }, 140 }, 141 { 142 name: "Empty condition", 143 conditions: []metav1.Condition{ 144 { 145 Type: string(k8s.RouteConditionAccepted), 146 Reason: string(k8s.RouteReasonAccepted), 147 Status: StatusFalse, 148 Message: "invalid backend", 149 LastTransitionTime: transitionTime, 150 }, 151 }, 152 condition: "", 153 want: metav1.Condition{}, 154 }, 155 } 156 for _, tt := range tests { 157 t.Run(tt.name, func(t *testing.T) { 158 if got := GetCondition(tt.conditions, tt.condition); !reflect.DeepEqual(got, tt.want) { 159 t.Errorf("GetCondition got %v, want %v", got, tt.want) 160 } 161 }) 162 } 163 } 164 165 func TestCreateCondition(t *testing.T) { 166 transitionTime := metav1.Now() 167 tests := []struct { 168 name string 169 conditions []metav1.Condition 170 condition metav1.Condition 171 unsetReason string 172 want []metav1.Condition 173 }{ 174 { 175 name: "condition is set, reason is unsetReason", 176 conditions: []metav1.Condition{ 177 { 178 Type: string(k8s.RouteConditionAccepted), 179 Reason: string(k8s.RouteReasonAccepted), 180 Status: StatusFalse, 181 Message: "invalid backend", 182 LastTransitionTime: transitionTime, 183 }, 184 }, 185 condition: metav1.Condition{ 186 Type: string(k8s.RouteConditionAccepted), 187 Reason: string(k8s.RouteReasonAccepted), 188 Status: StatusTrue, 189 Message: "foo", 190 LastTransitionTime: transitionTime, 191 }, 192 unsetReason: string(k8s.RouteReasonAccepted), 193 want: []metav1.Condition{ 194 { 195 Type: string(k8s.RouteConditionAccepted), 196 Reason: string(k8s.RouteReasonAccepted), 197 Status: StatusTrue, 198 Message: "foo", 199 LastTransitionTime: transitionTime, 200 }, 201 }, 202 }, 203 { 204 name: "condition is set, reason is not unsetReason", 205 conditions: []metav1.Condition{ 206 { 207 Type: string(k8s.RouteConditionAccepted), 208 Reason: string(k8s.RouteReasonAccepted), 209 Status: StatusFalse, 210 Message: "invalid backend", 211 LastTransitionTime: transitionTime, 212 }, 213 }, 214 condition: metav1.Condition{ 215 Type: string(k8s.RouteConditionAccepted), 216 Reason: string(k8s.RouteReasonAccepted), 217 Status: StatusTrue, 218 Message: "foo", 219 LastTransitionTime: transitionTime, 220 }, 221 unsetReason: string(k8s.RouteReasonPending), 222 want: []metav1.Condition{ 223 { 224 Type: string(k8s.RouteConditionAccepted), 225 Reason: string(k8s.RouteReasonAccepted), 226 Status: StatusFalse, 227 Message: "invalid backend", 228 LastTransitionTime: transitionTime, 229 }, 230 }, 231 }, 232 { 233 name: "add a new condition", 234 conditions: []metav1.Condition{ 235 { 236 Type: string(k8s.RouteConditionAccepted), 237 Reason: string(k8s.RouteReasonAccepted), 238 Status: StatusFalse, 239 Message: "invalid backend", 240 LastTransitionTime: transitionTime, 241 }, 242 }, 243 condition: metav1.Condition{ 244 Type: string(k8s.RouteConditionResolvedRefs), 245 Reason: string(k8s.RouteReasonResolvedRefs), 246 Status: StatusTrue, 247 Message: "foo", 248 LastTransitionTime: transitionTime, 249 }, 250 unsetReason: string(k8s.RouteReasonNotAllowedByListeners), 251 want: []metav1.Condition{ 252 { 253 Type: string(k8s.RouteConditionAccepted), 254 Reason: string(k8s.RouteConditionAccepted), 255 Status: StatusFalse, 256 Message: "invalid backend", 257 LastTransitionTime: transitionTime, 258 }, 259 { 260 Type: string(k8s.RouteConditionResolvedRefs), 261 Reason: string(k8s.RouteReasonResolvedRefs), 262 Status: StatusTrue, 263 Message: "foo", 264 LastTransitionTime: transitionTime, 265 }, 266 }, 267 }, 268 } 269 for _, tt := range tests { 270 t.Run(tt.name, func(t *testing.T) { 271 if got := CreateCondition(tt.conditions, tt.condition, tt.unsetReason); !reflect.DeepEqual(got, tt.want) { 272 t.Errorf("CreateCondition got %v, want %v", got, tt.want) 273 } 274 }) 275 } 276 } 277 278 func TestInvertStatus(t *testing.T) { 279 tests := []struct { 280 name string 281 status metav1.ConditionStatus 282 want metav1.ConditionStatus 283 }{ 284 { 285 name: "return false", 286 status: metav1.ConditionTrue, 287 want: metav1.ConditionFalse, 288 }, 289 { 290 name: "return true", 291 status: metav1.ConditionFalse, 292 want: metav1.ConditionTrue, 293 }, 294 { 295 name: "default return false", 296 status: metav1.ConditionUnknown, 297 want: metav1.ConditionFalse, 298 }, 299 } 300 for _, tt := range tests { 301 t.Run(tt.name, func(t *testing.T) { 302 if got := InvertStatus(tt.status); !reflect.DeepEqual(got, tt.want) { 303 t.Errorf("InvertStatus got %v, want %v", got, tt.want) 304 } 305 }) 306 } 307 }