istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/serviceregistry/kube/controller/util_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 controller 16 17 import ( 18 "reflect" 19 "testing" 20 21 v1 "k8s.io/api/core/v1" 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 "k8s.io/apimachinery/pkg/types" 24 25 "istio.io/istio/pilot/pkg/model" 26 "istio.io/istio/pkg/config/labels" 27 ) 28 29 func TestHasProxyIP(t *testing.T) { 30 tests := []struct { 31 name string 32 addresses []v1.EndpointAddress 33 proxyIP string 34 expected bool 35 }{ 36 { 37 "has proxy ip", 38 []v1.EndpointAddress{{IP: "172.17.0.1"}, {IP: "172.17.0.2"}}, 39 "172.17.0.1", 40 true, 41 }, 42 { 43 "has no proxy ip", 44 []v1.EndpointAddress{{IP: "172.17.0.1"}, {IP: "172.17.0.2"}}, 45 "172.17.0.100", 46 false, 47 }, 48 } 49 50 for _, test := range tests { 51 t.Run(test.name, func(t *testing.T) { 52 got := hasProxyIP(test.addresses, test.proxyIP) 53 if test.expected != got { 54 t.Errorf("Expected %v, but got %v", test.expected, got) 55 } 56 }) 57 } 58 } 59 60 func TestGetLabelValue(t *testing.T) { 61 tests := []struct { 62 name string 63 node *v1.Node 64 expectedLabelValue string 65 }{ 66 { 67 "Chooses beta label", 68 &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{NodeRegionLabel: "beta-region", NodeRegionLabelGA: "ga-region"}}}, 69 "beta-region", 70 }, 71 { 72 "Fallback no beta label defined", 73 &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{NodeRegionLabelGA: "ga-region"}}}, 74 "ga-region", 75 }, 76 { 77 "Only beta label specified", 78 &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{NodeRegionLabel: "beta-region"}}}, 79 "beta-region", 80 }, 81 { 82 "No label defined at all", 83 &v1.Node{}, 84 "", 85 }, 86 } 87 88 for _, test := range tests { 89 t.Run(test.name, func(t *testing.T) { 90 got := getLabelValue(test.node.ObjectMeta, NodeRegionLabel, NodeRegionLabelGA) 91 if test.expectedLabelValue != got { 92 t.Errorf("Expected %v, but got %v", test.expectedLabelValue, got) 93 } 94 }) 95 } 96 } 97 98 func TestPodKeyByProxy(t *testing.T) { 99 testCases := []struct { 100 name string 101 proxy *model.Proxy 102 expectedKey types.NamespacedName 103 }{ 104 { 105 name: "invalid id: bad format", 106 proxy: &model.Proxy{ 107 ID: "invalid", 108 Metadata: &model.NodeMetadata{ 109 Namespace: "default", 110 }, 111 }, 112 }, 113 { 114 name: "invalid id: namespace mismatch", 115 proxy: &model.Proxy{ 116 ID: "pod1.ns1", 117 Metadata: &model.NodeMetadata{ 118 Namespace: "default", 119 }, 120 }, 121 }, 122 { 123 name: "invalid id: namespace mismatch", 124 proxy: &model.Proxy{ 125 ID: "pod1.ns1", 126 Metadata: &model.NodeMetadata{ 127 Namespace: "ns1", 128 }, 129 }, 130 expectedKey: types.NamespacedName{Namespace: "ns1", Name: "pod1"}, 131 }, 132 } 133 134 for _, tc := range testCases { 135 t.Run(tc.name, func(t *testing.T) { 136 key := podKeyByProxy(tc.proxy) 137 if key != tc.expectedKey { 138 t.Errorf("expected key %s != %s", tc.expectedKey, key) 139 } 140 }) 141 } 142 } 143 144 func TestGetNodeSelectorsForService(t *testing.T) { 145 testCases := []struct { 146 name string 147 svc *v1.Service 148 expectedLabelSelector labels.Instance 149 }{ 150 { 151 name: "empty selector", 152 svc: makeFakeSvc(""), 153 expectedLabelSelector: nil, 154 }, 155 { 156 name: "invalid selector", 157 svc: makeFakeSvc("invalid value"), 158 expectedLabelSelector: nil, 159 }, 160 { 161 name: "wildcard match", 162 svc: makeFakeSvc("{}"), 163 expectedLabelSelector: labels.Instance{}, 164 }, 165 { 166 name: "specific match", 167 svc: makeFakeSvc(`{"kubernetes.io/hostname": "node1"}`), 168 expectedLabelSelector: labels.Instance{"kubernetes.io/hostname": "node1"}, 169 }, 170 } 171 172 for _, tc := range testCases { 173 t.Run(tc.name, func(t *testing.T) { 174 selector := getNodeSelectorsForService(tc.svc) 175 if !reflect.DeepEqual(selector, tc.expectedLabelSelector) { 176 t.Errorf("expected selector %v != %v", tc.expectedLabelSelector, selector) 177 } 178 }) 179 } 180 } 181 182 func makeFakeSvc(nodeSelector string) *v1.Service { 183 svc := &v1.Service{ 184 ObjectMeta: metav1.ObjectMeta{ 185 Name: "service", 186 Namespace: "ns", 187 }, 188 Spec: v1.ServiceSpec{ 189 Ports: []v1.ServicePort{{ 190 Name: "http", 191 Port: 80, 192 }}, 193 Selector: map[string]string{"app": "helloworld"}, 194 ClusterIP: "9.9.9.9", 195 }, 196 } 197 198 if nodeSelector != "" { 199 svc.Annotations = map[string]string{ 200 "traffic.istio.io/nodeSelector": nodeSelector, 201 } 202 } 203 return svc 204 } 205 206 func hasProxyIP(addresses []v1.EndpointAddress, proxyIP string) bool { 207 for _, addr := range addresses { 208 if addr.IP == proxyIP { 209 return true 210 } 211 } 212 return false 213 }