1// Copyright 2019 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 15package v2 16 17import ( 18 "fmt" 19 "reflect" 20 "strconv" 21 "testing" 22 23 model "istio.io/istio/pilot/pkg/model" 24 "istio.io/istio/pkg/config/schema/collections" 25 "istio.io/istio/pkg/config/schema/resource" 26) 27 28func TestProxyNeedsPush(t *testing.T) { 29 const ( 30 invalidKind = "INVALID_KIND" 31 svcName = "svc1.com" 32 drName = "dr1" 33 vsName = "vs1" 34 nsName = "ns1" 35 generalName = "name1" 36 37 invalidNameSuffix = "invalid" 38 ) 39 40 type Case struct { 41 name string 42 proxy *model.Proxy 43 configs map[model.ConfigKey]struct{} 44 want bool 45 } 46 47 sidecar := &model.Proxy{ 48 Type: model.SidecarProxy, IPAddresses: []string{"127.0.0.1"}, Metadata: &model.NodeMetadata{}, 49 SidecarScope: &model.SidecarScope{}} 50 gateway := &model.Proxy{Type: model.Router} 51 52 sidecarScopeKindNames := map[resource.GroupVersionKind]string{ 53 model.ServiceEntryKind: svcName, model.VirtualServiceKind: vsName, model.DestinationRuleKind: drName} 54 for kind, name := range sidecarScopeKindNames { 55 sidecar.SidecarScope.AddConfigDependencies(model.ConfigKey{Kind: kind, Name: name, Namespace: nsName}) 56 } 57 for kind, types := range configKindAffectedProxyTypes { 58 for _, nodeType := range types { 59 if nodeType == model.SidecarProxy { 60 sidecar.SidecarScope.AddConfigDependencies(model.ConfigKey{ 61 Kind: kind, 62 Name: generalName, 63 Namespace: nsName, 64 }) 65 } 66 } 67 } 68 69 cases := []Case{ 70 {"no namespace or configs", sidecar, nil, true}, 71 {"gateway config for sidecar", sidecar, map[model.ConfigKey]struct{}{ 72 { 73 Kind: collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), 74 Name: generalName, Namespace: nsName}: {}}, false}, 75 {"gateway config for gateway", gateway, map[model.ConfigKey]struct{}{ 76 { 77 Kind: collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), 78 Name: generalName, Namespace: nsName}: {}}, true}, 79 {"quotaspec config for sidecar", sidecar, map[model.ConfigKey]struct{}{ 80 { 81 Kind: collections.IstioMixerV1ConfigClientQuotaspecs.Resource().GroupVersionKind(), 82 Name: generalName, Namespace: nsName}: {}}, true}, 83 {"quotaspec config for gateway", gateway, map[model.ConfigKey]struct{}{ 84 { 85 Kind: collections.IstioMixerV1ConfigClientQuotaspecs.Resource().GroupVersionKind(), 86 Name: generalName, Namespace: nsName}: {}}, false}, 87 {"invalid config for sidecar", sidecar, map[model.ConfigKey]struct{}{ 88 { 89 Kind: resource.GroupVersionKind{Kind: invalidKind}, Name: generalName, Namespace: nsName}: {}}, 90 true}, 91 {"mixture matched and unmatched config for sidecar", sidecar, map[model.ConfigKey]struct{}{ 92 {Kind: model.DestinationRuleKind, Name: drName, Namespace: nsName}: {}, 93 {Kind: model.ServiceEntryKind, Name: svcName + invalidNameSuffix, Namespace: nsName}: {}, 94 }, true}, 95 {"mixture unmatched and unmatched config for sidecar", sidecar, map[model.ConfigKey]struct{}{ 96 {Kind: model.DestinationRuleKind, Name: drName + invalidNameSuffix, Namespace: nsName}: {}, 97 {Kind: model.ServiceEntryKind, Name: svcName + invalidNameSuffix, Namespace: nsName}: {}, 98 }, false}, 99 {"empty configsUpdated for sidecar", sidecar, nil, true}, 100 } 101 102 for kind, name := range sidecarScopeKindNames { 103 cases = append(cases, Case{ // valid name 104 name: fmt.Sprintf("%s config for sidecar", kind.Kind), 105 proxy: sidecar, 106 configs: map[model.ConfigKey]struct{}{{Kind: kind, Name: name, Namespace: nsName}: {}}, 107 want: true, 108 }, Case{ // invalid name 109 name: fmt.Sprintf("%s unmatched config for sidecar", kind.Kind), 110 proxy: sidecar, 111 configs: map[model.ConfigKey]struct{}{{Kind: kind, Name: name + invalidNameSuffix, Namespace: nsName}: {}}, 112 want: false, 113 }) 114 } 115 116 // tests for kind-affect-proxy. 117 for kind, types := range configKindAffectedProxyTypes { 118 for _, nodeType := range types { 119 proxy := gateway 120 if nodeType == model.SidecarProxy { 121 proxy = sidecar 122 } 123 cases = append(cases, Case{ 124 name: fmt.Sprintf("kind %s affect %s", kind, nodeType), 125 proxy: proxy, 126 configs: map[model.ConfigKey]struct{}{ 127 {Kind: kind, Name: generalName + invalidNameSuffix, Namespace: nsName}: {}}, 128 want: true, 129 }) 130 } 131 } 132 133 for _, tt := range cases { 134 t.Run(tt.name, func(t *testing.T) { 135 pushEv := &XdsEvent{configsUpdated: tt.configs} 136 got := ProxyNeedsPush(tt.proxy, pushEv) 137 if got != tt.want { 138 t.Fatalf("Got needs push = %v, expected %v", got, tt.want) 139 } 140 }) 141 } 142} 143 144func TestPushTypeFor(t *testing.T) { 145 t.Parallel() 146 147 sidecar := &model.Proxy{Type: model.SidecarProxy} 148 gateway := &model.Proxy{Type: model.Router} 149 150 tests := []struct { 151 name string 152 proxy *model.Proxy 153 configTypes []resource.GroupVersionKind 154 expect map[XdsType]bool 155 }{ 156 { 157 name: "configTypes is empty", 158 proxy: sidecar, 159 configTypes: nil, 160 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true, RDS: true}, 161 }, 162 { 163 name: "configTypes is empty", 164 proxy: gateway, 165 configTypes: nil, 166 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true, RDS: true}, 167 }, 168 { 169 name: "sidecar updated for sidecar proxy", 170 proxy: sidecar, 171 configTypes: []resource.GroupVersionKind{collections.IstioNetworkingV1Alpha3Sidecars.Resource().GroupVersionKind()}, 172 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true, RDS: true}, 173 }, 174 { 175 name: "sidecar updated for gateway proxy", 176 proxy: gateway, 177 configTypes: []resource.GroupVersionKind{collections.IstioNetworkingV1Alpha3Sidecars.Resource().GroupVersionKind()}, 178 expect: map[XdsType]bool{}, 179 }, 180 { 181 name: "quotaSpec updated for sidecar proxy", 182 proxy: sidecar, 183 configTypes: []resource.GroupVersionKind{collections.IstioMixerV1ConfigClientQuotaspecs.Resource().GroupVersionKind()}, 184 expect: map[XdsType]bool{LDS: true, RDS: true}, 185 }, 186 { 187 name: "quotaSpec updated for gateway", 188 proxy: gateway, 189 configTypes: []resource.GroupVersionKind{collections.IstioMixerV1ConfigClientQuotaspecs.Resource().GroupVersionKind()}, 190 expect: map[XdsType]bool{}, 191 }, 192 { 193 name: "authorizationpolicy updated", 194 proxy: sidecar, 195 configTypes: []resource.GroupVersionKind{collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind()}, 196 expect: map[XdsType]bool{LDS: true}, 197 }, 198 { 199 name: "authorizationpolicy updated", 200 proxy: gateway, 201 configTypes: []resource.GroupVersionKind{collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind()}, 202 expect: map[XdsType]bool{LDS: true}, 203 }, 204 { 205 name: "unknown type updated", 206 proxy: sidecar, 207 configTypes: []resource.GroupVersionKind{{Kind: "unknown"}}, 208 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true, RDS: true}, 209 }, 210 { 211 name: "unknown type updated", 212 proxy: gateway, 213 configTypes: []resource.GroupVersionKind{}, 214 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true, RDS: true}, 215 }, 216 { 217 name: "gateway and virtualservice updated for gateway proxy", 218 proxy: gateway, 219 configTypes: []resource.GroupVersionKind{collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), 220 collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind()}, 221 expect: map[XdsType]bool{LDS: true, RDS: true}, 222 }, 223 { 224 name: "virtualservice and destinationrule updated", 225 proxy: sidecar, 226 configTypes: []resource.GroupVersionKind{collections.IstioNetworkingV1Alpha3Destinationrules.Resource().GroupVersionKind(), 227 collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind()}, 228 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true, RDS: true}, 229 }, 230 { 231 name: "requestauthentication updated", 232 proxy: sidecar, 233 configTypes: []resource.GroupVersionKind{collections.IstioSecurityV1Beta1Requestauthentications.Resource().GroupVersionKind()}, 234 expect: map[XdsType]bool{LDS: true}, 235 }, 236 { 237 name: "requestauthentication updated", 238 proxy: gateway, 239 configTypes: []resource.GroupVersionKind{collections.IstioSecurityV1Beta1Requestauthentications.Resource().GroupVersionKind()}, 240 expect: map[XdsType]bool{LDS: true}, 241 }, 242 { 243 name: "peerauthentication updated", 244 proxy: sidecar, 245 configTypes: []resource.GroupVersionKind{collections.IstioSecurityV1Beta1Peerauthentications.Resource().GroupVersionKind()}, 246 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true}, 247 }, 248 { 249 name: "peerauthentication updated", 250 proxy: gateway, 251 configTypes: []resource.GroupVersionKind{collections.IstioSecurityV1Beta1Peerauthentications.Resource().GroupVersionKind()}, 252 expect: map[XdsType]bool{CDS: true, EDS: true, LDS: true}, 253 }, 254 } 255 256 for _, tt := range tests { 257 t.Run(tt.name, func(t *testing.T) { 258 cfgs := map[model.ConfigKey]struct{}{} 259 for _, kind := range tt.configTypes { 260 cfgs[model.ConfigKey{ 261 Kind: kind, 262 Name: "name", 263 Namespace: "ns", 264 }] = struct{}{} 265 } 266 pushEv := &XdsEvent{configsUpdated: cfgs} 267 out := PushTypeFor(tt.proxy, pushEv) 268 if !reflect.DeepEqual(out, tt.expect) { 269 t.Errorf("expected: %v, but got %v", tt.expect, out) 270 } 271 }) 272 } 273} 274 275func BenchmarkListEquals(b *testing.B) { 276 size := 100 277 var l []string 278 for i := 0; i < size; i++ { 279 l = append(l, strconv.Itoa(i)) 280 } 281 var equal []string 282 for i := 0; i < size; i++ { 283 equal = append(equal, strconv.Itoa(i)) 284 } 285 var notEqual []string 286 for i := 0; i < size; i++ { 287 notEqual = append(notEqual, strconv.Itoa(i)) 288 } 289 notEqual[size-1] = "z" 290 291 for n := 0; n < b.N; n++ { 292 listEqualUnordered(l, equal) 293 listEqualUnordered(l, notEqual) 294 } 295} 296