istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/serviceregistry/kube/controller/ambient/ambientindex_serviceentry_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 ambient 16 17 import ( 18 "net/netip" 19 "testing" 20 21 corev1 "k8s.io/api/core/v1" 22 23 "istio.io/istio/pilot/pkg/features" 24 "istio.io/istio/pilot/pkg/model" 25 "istio.io/istio/pkg/test" 26 "istio.io/istio/pkg/test/util/assert" 27 "istio.io/istio/pkg/workloadapi" 28 ) 29 30 func TestAmbientIndex_ServiceEntry(t *testing.T) { 31 s := newAmbientTestServer(t, testC, testNW) 32 33 // test code path where service entry creates a workload entry via `ServiceEntry.endpoints` 34 // and the inlined WE has a port override 35 s.addServiceEntry(t, "se.istio.io", []string{"240.240.23.45"}, "name1", testNS, nil, []string{"127.0.0.1"}) 36 s.assertEvent(t, s.seIPXdsName("name1", "127.0.0.1"), "ns1/se.istio.io") 37 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "name1") 38 assert.Equal(t, s.lookup(s.addrXdsName("127.0.0.1")), []model.AddressInfo{{ 39 Address: &workloadapi.Address{ 40 Type: &workloadapi.Address_Workload{ 41 Workload: &workloadapi.Workload{ 42 Uid: s.seIPXdsName("name1", "127.0.0.1"), 43 Name: "name1", 44 Namespace: testNS, 45 Addresses: [][]byte{parseIP("127.0.0.1")}, 46 Node: "", 47 Network: testNW, 48 CanonicalName: "name1", 49 CanonicalRevision: "latest", 50 WorkloadType: workloadapi.WorkloadType_POD, 51 WorkloadName: "name1", 52 Services: map[string]*workloadapi.PortList{ 53 "ns1/se.istio.io": { 54 Ports: []*workloadapi.Port{ 55 { 56 ServicePort: 80, 57 TargetPort: 8081, // port is overridden by inlined WE port 58 }, 59 }, 60 }, 61 }, 62 ClusterId: testC, 63 }, 64 }, 65 }, 66 }}) 67 68 s.deleteServiceEntry(t, "name1", testNS) 69 s.assertEvent(t, s.seIPXdsName("name1", "127.0.0.1"), "ns1/se.istio.io") 70 assert.Equal(t, s.lookup(s.addrXdsName("127.0.0.1")), nil) 71 s.clearEvents() 72 73 // workload entry that has an address of future pod will be dropped from result once pod is added 74 s.addWorkloadEntries(t, "140.140.0.10", "name0", "sa1", map[string]string{"app": "a"}) 75 s.assertEvent(t, s.wleXdsName("name0")) 76 // workload entry is included in the result until pod1 with the same address below is added 77 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "name0") 78 // lookup by address should return the workload entry's address info 79 assert.Equal(t, s.lookup(s.addrXdsName("140.140.0.10")), []model.AddressInfo{{ 80 Address: &workloadapi.Address{ 81 Type: &workloadapi.Address_Workload{ 82 Workload: &workloadapi.Workload{ 83 Uid: s.wleXdsName("name0"), 84 Name: "name0", 85 Namespace: testNS, 86 Addresses: [][]byte{parseIP("140.140.0.10")}, 87 Network: testNW, 88 CanonicalName: "a", 89 CanonicalRevision: "latest", 90 ServiceAccount: "sa1", 91 WorkloadType: workloadapi.WorkloadType_POD, 92 WorkloadName: "name0", 93 ClusterId: testC, 94 }, 95 }, 96 }, 97 }}) 98 99 // test code path where service entry selects workloads via `ServiceEntry.workloadSelector` 100 s.addPods(t, "140.140.0.10", "pod1", "sa1", map[string]string{"app": "a"}, nil, true, corev1.PodRunning) 101 s.assertEvent(t, s.podXdsName("pod1")) 102 103 // lookup by address should return the pod's address info (ignore the workload entry with similar address) 104 assert.Equal(t, s.lookup(s.addrXdsName("140.140.0.10")), []model.AddressInfo{{ 105 Address: &workloadapi.Address{ 106 Type: &workloadapi.Address_Workload{ 107 Workload: &workloadapi.Workload{ 108 Uid: s.podXdsName("pod1"), 109 Name: "pod1", 110 Namespace: testNS, 111 Addresses: [][]byte{parseIP("140.140.0.10")}, 112 Network: testNW, 113 ClusterId: testC, 114 Node: "node1", 115 CanonicalName: "a", 116 CanonicalRevision: "latest", 117 ServiceAccount: "sa1", 118 WorkloadType: workloadapi.WorkloadType_POD, 119 WorkloadName: "pod1", 120 }, 121 }, 122 }, 123 }}) 124 125 s.addPods(t, "140.140.0.11", "pod2", "sa1", map[string]string{"app": "other"}, nil, true, corev1.PodRunning) 126 s.assertEvent(t, s.podXdsName("pod2")) 127 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "pod1", "pod2") 128 s.addWorkloadEntries(t, "240.240.34.56", "name1", "sa1", map[string]string{"app": "a"}) 129 s.assertEvent(t, s.wleXdsName("name1")) 130 s.addWorkloadEntries(t, "240.240.34.57", "name2", "sa1", map[string]string{"app": "other"}) 131 s.assertEvent(t, s.wleXdsName("name2")) 132 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "pod1", "pod2", "name1", "name2") 133 134 s.addWorkloadEntries(t, "140.140.0.11", "name3", "sa1", map[string]string{"app": "other"}) 135 s.assertEvent(t, s.wleXdsName("name3")) 136 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "pod1", "pod2", "name1", "name2") 137 138 // a service entry should not be able to select across namespaces 139 s.addServiceEntry(t, "mismatched.istio.io", []string{"240.240.23.45"}, "name1", "mismatched-ns", map[string]string{"app": "a"}, nil) 140 s.assertEvent(t, "mismatched-ns/mismatched.istio.io") 141 assert.Equal(t, s.lookup(s.addrXdsName("140.140.0.10")), []model.AddressInfo{{ 142 Address: &workloadapi.Address{ 143 Type: &workloadapi.Address_Workload{ 144 Workload: &workloadapi.Workload{ 145 Uid: s.podXdsName("pod1"), 146 Name: "pod1", 147 Namespace: testNS, 148 Addresses: [][]byte{parseIP("140.140.0.10")}, 149 Node: "node1", 150 Network: testNW, 151 CanonicalName: "a", 152 CanonicalRevision: "latest", 153 ServiceAccount: "sa1", 154 WorkloadType: workloadapi.WorkloadType_POD, 155 WorkloadName: "pod1", 156 Services: nil, // should not be selected by the mismatched service entry 157 ClusterId: testC, 158 }, 159 }, 160 }, 161 }}) 162 assert.Equal(t, s.lookup(s.addrXdsName("240.240.34.56")), []model.AddressInfo{{ 163 Address: &workloadapi.Address{ 164 Type: &workloadapi.Address_Workload{ 165 Workload: &workloadapi.Workload{ 166 Uid: s.wleXdsName("name1"), 167 Name: "name1", 168 Namespace: testNS, 169 Addresses: [][]byte{parseIP("240.240.34.56")}, 170 Node: "", 171 Network: testNW, 172 CanonicalName: "a", 173 CanonicalRevision: "latest", 174 ServiceAccount: "sa1", 175 WorkloadType: workloadapi.WorkloadType_POD, 176 WorkloadName: "name1", 177 Services: nil, // should not be selected by the mismatched service entry 178 ClusterId: testC, 179 }, 180 }, 181 }, 182 }}) 183 184 s.addServiceEntry(t, "se.istio.io", []string{"240.240.23.45"}, "name1", testNS, map[string]string{"app": "a"}, nil) 185 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "pod1", "pod2", "name1", "name2") 186 // we should see an update for the workloads selected by the service entry 187 // do not expect event for pod2 since it is not selected by the service entry 188 s.assertEvent(t, s.podXdsName("pod1"), s.wleXdsName("name0"), s.wleXdsName("name1"), "ns1/se.istio.io") 189 190 assert.Equal(t, s.lookup(s.addrXdsName("140.140.0.10")), []model.AddressInfo{{ 191 Address: &workloadapi.Address{ 192 Type: &workloadapi.Address_Workload{ 193 Workload: &workloadapi.Workload{ 194 Uid: s.podXdsName("pod1"), 195 Name: "pod1", 196 Namespace: testNS, 197 Addresses: [][]byte{parseIP("140.140.0.10")}, 198 Node: "node1", 199 Network: testNW, 200 CanonicalName: "a", 201 CanonicalRevision: "latest", 202 ServiceAccount: "sa1", 203 WorkloadType: workloadapi.WorkloadType_POD, 204 WorkloadName: "pod1", 205 Services: map[string]*workloadapi.PortList{ 206 "ns1/se.istio.io": { 207 Ports: []*workloadapi.Port{ 208 { 209 ServicePort: 80, 210 TargetPort: 8080, 211 }, 212 }, 213 }, 214 }, 215 ClusterId: testC, 216 }, 217 }, 218 }, 219 }}) 220 221 assert.Equal(t, s.lookup(s.addrXdsName("140.140.0.11")), []model.AddressInfo{{ 222 Address: &workloadapi.Address{ 223 Type: &workloadapi.Address_Workload{ 224 Workload: &workloadapi.Workload{ 225 Uid: s.podXdsName("pod2"), 226 Name: "pod2", 227 Namespace: testNS, 228 Addresses: [][]byte{parseIP("140.140.0.11")}, 229 Node: "node1", 230 Network: testNW, 231 ClusterId: testC, 232 CanonicalName: "other", 233 CanonicalRevision: "latest", 234 ServiceAccount: "sa1", 235 WorkloadType: workloadapi.WorkloadType_POD, 236 WorkloadName: "pod2", 237 Services: nil, // labels don't match workloadSelector, this should be nil 238 }, 239 }, 240 }, 241 }}) 242 243 assert.Equal(t, s.lookup(s.addrXdsName("240.240.34.56")), []model.AddressInfo{{ 244 Address: &workloadapi.Address{ 245 Type: &workloadapi.Address_Workload{ 246 Workload: &workloadapi.Workload{ 247 Uid: s.wleXdsName("name1"), 248 Name: "name1", 249 Namespace: testNS, 250 Addresses: [][]byte{parseIP("240.240.34.56")}, 251 Node: "", 252 Network: testNW, 253 CanonicalName: "a", 254 CanonicalRevision: "latest", 255 ServiceAccount: "sa1", 256 WorkloadType: workloadapi.WorkloadType_POD, 257 WorkloadName: "name1", 258 Services: map[string]*workloadapi.PortList{ 259 "ns1/se.istio.io": { 260 Ports: []*workloadapi.Port{ 261 { 262 ServicePort: 80, 263 TargetPort: 8080, 264 }, 265 }, 266 }, 267 }, 268 ClusterId: testC, 269 }, 270 }, 271 }, 272 }}) 273 274 s.deleteServiceEntry(t, "name1", testNS) 275 s.assertWorkloads(t, "", workloadapi.WorkloadStatus_HEALTHY, "pod1", "pod2", "name1", "name2") 276 s.assertUniqueWorkloads(t) 277 // we should see an update for the workloads selected by the service entry 278 s.assertEvent(t, s.podXdsName("pod1"), s.wleXdsName("name0"), s.wleXdsName("name1"), "ns1/se.istio.io") 279 assert.Equal(t, s.lookup(s.addrXdsName("140.140.0.10")), []model.AddressInfo{{ 280 Address: &workloadapi.Address{ 281 Type: &workloadapi.Address_Workload{ 282 Workload: &workloadapi.Workload{ 283 Uid: s.podXdsName("pod1"), 284 Name: "pod1", 285 Namespace: testNS, 286 Addresses: [][]byte{parseIP("140.140.0.10")}, 287 Node: "node1", 288 Network: testNW, 289 ClusterId: testC, 290 CanonicalName: "a", 291 CanonicalRevision: "latest", 292 ServiceAccount: "sa1", 293 WorkloadType: workloadapi.WorkloadType_POD, 294 WorkloadName: "pod1", 295 Services: nil, // vips for pod1 should be gone now 296 }, 297 }, 298 }, 299 }}) 300 301 assert.Equal(t, s.lookup(s.addrXdsName("240.240.34.56")), []model.AddressInfo{{ 302 Address: &workloadapi.Address{ 303 Type: &workloadapi.Address_Workload{ 304 Workload: &workloadapi.Workload{ 305 Uid: s.wleXdsName("name1"), 306 Name: "name1", 307 Namespace: testNS, 308 Addresses: [][]byte{parseIP("240.240.34.56")}, 309 Node: "", 310 Network: testNW, 311 CanonicalName: "a", 312 CanonicalRevision: "latest", 313 ServiceAccount: "sa1", 314 WorkloadType: workloadapi.WorkloadType_POD, 315 WorkloadName: "name1", 316 Services: nil, // vips for workload entry 1 should be gone now 317 ClusterId: testC, 318 }, 319 }, 320 }, 321 }}) 322 } 323 324 func TestAmbientIndex_ServiceEntry_DisableK8SServiceSelectWorkloadEntries(t *testing.T) { 325 test.SetForTest(t, &features.EnableK8SServiceSelectWorkloadEntries, false) 326 s := newAmbientTestServer(t, testC, testNW) 327 328 s.addPods(t, "140.140.0.10", "pod1", "sa1", map[string]string{"app": "a"}, nil, true, corev1.PodRunning) 329 s.assertEvent(t, s.podXdsName("pod1")) 330 s.addPods(t, "140.140.0.11", "pod2", "sa1", map[string]string{"app": "other"}, nil, true, corev1.PodRunning) 331 s.assertEvent(t, s.podXdsName("pod2")) 332 s.addWorkloadEntries(t, "240.240.34.56", "name1", "sa1", map[string]string{"app": "a"}) 333 s.assertEvent(t, s.wleXdsName("name1")) 334 s.addWorkloadEntries(t, "240.240.34.57", "name2", "sa1", map[string]string{"app": "other"}) 335 s.assertEvent(t, s.wleXdsName("name2")) 336 s.addServiceEntry(t, "se.istio.io", []string{"240.240.23.45"}, "name1", testNS, map[string]string{"app": "a"}, nil) 337 s.assertEvent(t, s.podXdsName("pod1"), s.wleXdsName("name1"), "ns1/se.istio.io") 338 s.clearEvents() 339 340 // Setting the PILOT_ENABLE_K8S_SELECT_WORKLOAD_ENTRIES to false shouldn't affect the workloads selected by the service 341 // entry 342 s.assertWorkloads(t, s.addrXdsName("240.240.23.45"), workloadapi.WorkloadStatus_HEALTHY, "pod1", "name1") 343 } 344 345 func parseIP(ip string) []byte { 346 addr, err := netip.ParseAddr(ip) 347 if err != nil { 348 return nil 349 } 350 return addr.AsSlice() 351 }