istio.io/istio@v0.0.0-20240520182934-d79c90f27776/istioctl/pkg/checkinject/checkinject_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 checkinject 16 17 import ( 18 "os" 19 "testing" 20 21 admitv1 "k8s.io/api/admissionregistration/v1" 22 corev1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "sigs.k8s.io/yaml" 25 26 "istio.io/api/annotation" 27 "istio.io/api/label" 28 "istio.io/istio/pkg/test/util/assert" 29 ) 30 31 func Test_analyzeRunningWebhooks(t *testing.T) { 32 cases := []struct { 33 name string 34 pod *corev1.Pod 35 ns *corev1.Namespace 36 expectedMessages []webhookAnalysis 37 }{ 38 { 39 name: "no inj because of no match labels", 40 pod: podTestObject("test1", "test1", "", ""), 41 ns: nsTestObject("test1", "", ""), 42 expectedMessages: []webhookAnalysis{ 43 { 44 Name: "istio-sidecar-injector", 45 Revision: "default", 46 Reason: "No matching namespace labels (istio.io/rev=default, istio-injection=enabled) " + 47 "or pod labels (istio.io/rev=default, sidecar.istio.io/inject=true)", 48 }, 49 { 50 Name: "istio-sidecar-injector-1-16", 51 Revision: "1-16", 52 Reason: "No matching namespace labels (istio.io/rev=1-16) or pod labels (istio.io/rev=1-16)", 53 }, 54 { 55 Name: "istio-sidecar-injector-deactivated", 56 Revision: "default", 57 Reason: "The injection webhook is deactivated, and will never match labels.", 58 }, 59 }, 60 }, 61 { 62 name: "default ns injection", 63 pod: podTestObject("test1", "test1", "", ""), 64 ns: nsTestObject("test1", "enabled", ""), 65 expectedMessages: []webhookAnalysis{ 66 { 67 Name: "istio-sidecar-injector", 68 Revision: "default", 69 Injected: true, 70 Reason: "Namespace label istio-injection=enabled matches", 71 }, 72 { 73 Name: "istio-sidecar-injector-1-16", 74 Revision: "1-16", 75 Reason: "No matching namespace labels (istio.io/rev=1-16) or pod labels (istio.io/rev=1-16)", 76 }, 77 { 78 Name: "istio-sidecar-injector-deactivated", 79 Revision: "default", 80 Reason: "The injection webhook is deactivated, and will never match labels.", 81 }, 82 }, 83 }, 84 { 85 name: "rev ns injection", 86 pod: podTestObject("test1", "test1", "", ""), 87 ns: nsTestObject("test1", "", "1-16"), 88 expectedMessages: []webhookAnalysis{ 89 { 90 Name: "istio-sidecar-injector", 91 Revision: "default", 92 Reason: "No matching namespace labels (istio.io/rev=default, istio-injection=enabled) " + 93 "or pod labels (istio.io/rev=default, sidecar.istio.io/inject=true)", 94 }, 95 { 96 Name: "istio-sidecar-injector-1-16", 97 Revision: "1-16", 98 Injected: true, 99 Reason: "Namespace label istio.io/rev=1-16 matches", 100 }, 101 { 102 Name: "istio-sidecar-injector-deactivated", 103 Revision: "default", 104 Reason: "The injection webhook is deactivated, and will never match labels.", 105 }, 106 }, 107 }, 108 { 109 name: "rev po label injection", 110 pod: podTestObject("test1", "test1", "", "1-16"), 111 ns: nsTestObject("test1", "", ""), 112 expectedMessages: []webhookAnalysis{ 113 { 114 Name: "istio-sidecar-injector", 115 Revision: "default", 116 Reason: "Pod has istio.io/rev=1-16 label, preventing injection", 117 }, 118 { 119 Name: "istio-sidecar-injector-1-16", 120 Revision: "1-16", 121 Injected: true, 122 Reason: "Pod label istio.io/rev=1-16 matches", 123 }, 124 { 125 Name: "istio-sidecar-injector-deactivated", 126 Revision: "default", 127 Reason: "The injection webhook is deactivated, and will never match labels.", 128 }, 129 }, 130 }, 131 { 132 name: "default pod label injection", 133 pod: podTestObject("test1", "test1", "true", ""), 134 ns: nsTestObject("test1", "", ""), 135 expectedMessages: []webhookAnalysis{ 136 { 137 Name: "istio-sidecar-injector", 138 Revision: "default", 139 Injected: true, 140 Reason: "Pod label sidecar.istio.io/inject=true matches", 141 }, 142 { 143 Name: "istio-sidecar-injector-1-16", 144 Revision: "1-16", 145 Reason: "No matching namespace labels (istio.io/rev=1-16) or pod labels (istio.io/rev=1-16)", 146 }, 147 { 148 Name: "istio-sidecar-injector-deactivated", 149 Revision: "default", 150 Reason: "The injection webhook is deactivated, and will never match labels.", 151 }, 152 }, 153 }, 154 { 155 name: "both default label injection", 156 pod: podTestObject("test1", "test1", "true", ""), 157 ns: nsTestObject("test1", "enabled", ""), 158 expectedMessages: []webhookAnalysis{ 159 { 160 Name: "istio-sidecar-injector", 161 Revision: "default", 162 Injected: true, 163 Reason: "Namespace label istio-injection=enabled matches, and pod label sidecar.istio.io/inject=true matches", 164 }, 165 { 166 Name: "istio-sidecar-injector-1-16", 167 Revision: "1-16", 168 Reason: "No matching namespace labels (istio.io/rev=1-16) or pod labels (istio.io/rev=1-16)", 169 }, 170 { 171 Name: "istio-sidecar-injector-deactivated", 172 Revision: "default", 173 Reason: "The injection webhook is deactivated, and will never match labels.", 174 }, 175 }, 176 }, 177 { 178 name: "both rev label injection", 179 pod: podTestObject("test1", "test1", "", "1-16"), 180 ns: nsTestObject("test1", "", "1-16"), 181 expectedMessages: []webhookAnalysis{ 182 { 183 Name: "istio-sidecar-injector", 184 Revision: "default", 185 Reason: "No matching namespace labels (istio.io/rev=default, istio-injection=enabled) " + 186 "or pod labels (istio.io/rev=default, sidecar.istio.io/inject=true)", 187 }, 188 { 189 Name: "istio-sidecar-injector-1-16", 190 Revision: "1-16", 191 Injected: true, 192 Reason: "Namespace label istio.io/rev=1-16 matches", 193 }, 194 { 195 Name: "istio-sidecar-injector-deactivated", 196 Revision: "default", 197 Reason: "The injection webhook is deactivated, and will never match labels.", 198 }, 199 }, 200 }, 201 { 202 name: "disable ns label and rev po label", 203 pod: podTestObject("test1", "test1", "", "1-16"), 204 ns: nsTestObject("test1", "disabled", ""), 205 expectedMessages: []webhookAnalysis{ 206 { 207 Name: "istio-sidecar-injector", 208 Revision: "default", 209 Reason: "Namespace has istio-injection=disabled label, preventing injection", 210 }, 211 { 212 Name: "istio-sidecar-injector-1-16", 213 Revision: "1-16", 214 Injected: false, 215 Reason: "Namespace has istio-injection=disabled label, preventing injection", 216 }, 217 { 218 Name: "istio-sidecar-injector-deactivated", 219 Revision: "default", 220 Reason: "The injection webhook is deactivated, and will never match labels.", 221 }, 222 }, 223 }, 224 { 225 name: "ns and rev pod label", 226 pod: podTestObject("test1", "test1", "", "1-16"), 227 ns: nsTestObject("test1", "enabled", ""), 228 expectedMessages: []webhookAnalysis{ 229 { 230 Name: "istio-sidecar-injector", 231 Revision: "default", 232 Injected: true, 233 Reason: "Namespace label istio-injection=enabled matches", 234 }, 235 { 236 Name: "istio-sidecar-injector-1-16", 237 Revision: "1-16", 238 Injected: false, 239 Reason: "No matching namespace labels (istio.io/rev=1-16) or pod labels (istio.io/rev=1-16)", 240 }, 241 { 242 Name: "istio-sidecar-injector-deactivated", 243 Revision: "default", 244 Reason: "The injection webhook is deactivated, and will never match labels.", 245 }, 246 }, 247 }, 248 { 249 name: "pod label with not inject", 250 pod: podTestObject("test1", "test1", "false", ""), 251 ns: nsTestObject("test1", "enabled", ""), 252 expectedMessages: []webhookAnalysis{ 253 { 254 Name: "istio-sidecar-injector", 255 Revision: "default", 256 Injected: false, 257 Reason: "Pod has sidecar.istio.io/inject=false label, preventing injection", 258 }, 259 { 260 Name: "istio-sidecar-injector-1-16", 261 Revision: "1-16", 262 Injected: false, 263 Reason: "No matching namespace labels (istio.io/rev=1-16) or pod labels (istio.io/rev=1-16)", 264 }, 265 { 266 Name: "istio-sidecar-injector-deactivated", 267 Revision: "default", 268 Reason: "The injection webhook is deactivated, and will never match labels.", 269 }, 270 }, 271 }, 272 { 273 name: "pod not injectable for ns rev", 274 pod: podTestObject("test1", "test1", "false", ""), 275 ns: nsTestObject("test1", "", "1-16"), 276 expectedMessages: []webhookAnalysis{ 277 { 278 Name: "istio-sidecar-injector", 279 Revision: "default", 280 Injected: false, 281 Reason: "No matching namespace labels (istio.io/rev=default, istio-injection=enabled) " + 282 "or pod labels (istio.io/rev=default, sidecar.istio.io/inject=true)", 283 }, 284 { 285 Name: "istio-sidecar-injector-1-16", 286 Revision: "1-16", 287 Injected: false, 288 Reason: "Pod has sidecar.istio.io/inject=false label, preventing injection", 289 }, 290 { 291 Name: "istio-sidecar-injector-deactivated", 292 Revision: "default", 293 Reason: "The injection webhook is deactivated, and will never match labels.", 294 }, 295 }, 296 }, 297 } 298 whFiles := []string{ 299 "testdata/check-inject/default-injector.yaml", 300 "testdata/check-inject/rev-16-injector.yaml", 301 "testdata/check-inject/never-match-injector.yaml", 302 } 303 var whs []admitv1.MutatingWebhookConfiguration 304 for _, whName := range whFiles { 305 file, err := os.ReadFile(whName) 306 if err != nil { 307 t.Fatal(err) 308 } 309 var wh *admitv1.MutatingWebhookConfiguration 310 if err := yaml.Unmarshal(file, &wh); err != nil { 311 t.Fatal(err) 312 } 313 whs = append(whs, *wh) 314 } 315 for _, c := range cases { 316 t.Run(c.name, func(t *testing.T) { 317 checkResults := analyzeRunningWebhooks(whs, 318 c.pod.Labels, c.ns.Labels) 319 assert.Equal(t, c.expectedMessages, checkResults) 320 }) 321 } 322 } 323 324 var nsTestObject = func(namespace, injLabelValue, revLabelValue string) *corev1.Namespace { 325 labels := map[string]string{} 326 if injLabelValue != "" { 327 labels["istio-injection"] = injLabelValue 328 } 329 if revLabelValue != "" { 330 labels[label.IoIstioRev.Name] = revLabelValue 331 } 332 return &corev1.Namespace{ 333 ObjectMeta: metav1.ObjectMeta{ 334 Name: namespace, 335 Labels: labels, 336 }, 337 } 338 } 339 340 var podTestObject = func(name, namespace, injLabelValue, revLabelValue string) *corev1.Pod { 341 labels := map[string]string{} 342 if injLabelValue != "" { 343 labels[annotation.SidecarInject.Name] = injLabelValue 344 } 345 if revLabelValue != "" { 346 labels[label.IoIstioRev.Name] = revLabelValue 347 } 348 return &corev1.Pod{ 349 ObjectMeta: metav1.ObjectMeta{ 350 Name: name, 351 Namespace: namespace, 352 Labels: labels, 353 }, 354 } 355 }