istio
210 строк · 7.8 Кб
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
15package serviceentry16
17import (18"reflect"19"testing"20
21"k8s.io/apimachinery/pkg/types"22
23networking "istio.io/api/networking/v1alpha3"24"istio.io/istio/pilot/pkg/model"25"istio.io/istio/pkg/config/constants"26"istio.io/istio/pkg/ptr"27"istio.io/istio/pkg/test/util/assert"28"istio.io/istio/pkg/util/sets"29)
30
31func TestServiceInstancesStore(t *testing.T) {32store := serviceInstancesStore{33ip2instance: map[string][]*model.ServiceInstance{},34instances: map[instancesKey]map[configKey][]*model.ServiceInstance{},35instancesBySE: map[types.NamespacedName]map[configKey][]*model.ServiceInstance{},36instancesByHostAndPort: sets.Set[hostPort]{},37}38instances := []*model.ServiceInstance{39makeInstance(selector, "1.1.1.1", 444, selector.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),40makeInstance(selector, "1.1.1.1", 445, selector.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),41makeInstance(dnsSelector, "1.1.1.1", 444, dnsSelector.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),42}43cKey := configKey{44namespace: "default",45name: "test-wle",46}47store.addInstances(cKey, instances)48
49// 1. test getByIP50gotInstances := store.getByIP("1.1.1.1")51if !reflect.DeepEqual(instances, gotInstances) {52t.Errorf("got unexpected instances : %v", gotInstances)53}54
55// 2. test getAll56gotInstances = store.getAll()57if !reflect.DeepEqual(instances, gotInstances) {58t.Errorf("got unexpected instances : %v", gotInstances)59}60
61// 3. test getByKey62gotInstances = store.getByKey(instancesKey{63hostname: "selector.com",64namespace: "selector",65})66expected := []*model.ServiceInstance{67makeInstance(selector, "1.1.1.1", 444, selector.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),68makeInstance(selector, "1.1.1.1", 445, selector.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),69}70if !reflect.DeepEqual(gotInstances, expected) {71t.Errorf("got unexpected instances : %v", gotInstances)72}73
74// 4. test getServiceEntryInstances75expectedSeInstances := map[configKey][]*model.ServiceInstance{cKey: {76makeInstance(selector, "1.1.1.1", 444, selector.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),77makeInstance(selector, "1.1.1.1", 445, selector.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),78}}79key := selector.NamespacedName()80store.updateServiceEntryInstances(key, expectedSeInstances)81
82gotSeInstances := store.getServiceEntryInstances(key)83if !reflect.DeepEqual(gotSeInstances, expectedSeInstances) {84t.Errorf("got unexpected se instances : %v", gotSeInstances)85}86
87// 5. test deleteServiceEntryInstances88store.deleteServiceEntryInstances(key, cKey)89gotSeInstances = store.getServiceEntryInstances(key)90if len(gotSeInstances) != 0 {91t.Errorf("got unexpected instances %v", gotSeInstances)92}93
94// 6. test deleteAllServiceEntryInstances95store.deleteAllServiceEntryInstances(key)96gotSeInstances = store.getServiceEntryInstances(key)97if len(gotSeInstances) != 0 {98t.Errorf("got unexpected instances %v", gotSeInstances)99}100
101// 7. test deleteInstanceKeys102store.deleteInstanceKeys(cKey, instances)103gotInstances = store.getAll()104if len(gotInstances) != 0 {105t.Errorf("got unexpected instances %v", gotSeInstances)106}107}
108
109func TestServiceStore(t *testing.T) {110store := serviceStore{111servicesBySE: map[types.NamespacedName][]*model.Service{},112}113
114expectedServices := []*model.Service{115makeService("*.istio.io", "httpDNSRR", constants.UnspecifiedIP, map[string]int{"http-port": 80, "http-alt-port": 8080}, true, model.DNSRoundRobinLB),116makeService("*.istio.io", "httpDNSRR", constants.UnspecifiedIP, map[string]int{"http-port": 80, "http-alt-port": 8080}, true, model.DNSLB),117}118
119store.updateServices(httpDNSRR.NamespacedName(), expectedServices)120got := store.getServices(httpDNSRR.NamespacedName())121if !reflect.DeepEqual(got, expectedServices) {122t.Errorf("got unexpected services %v", got)123}124
125got = store.getAllServices()126if !reflect.DeepEqual(got, expectedServices) {127t.Errorf("got unexpected services %v", got)128}129if !store.allocateNeeded {130t.Errorf("expected allocate needed")131}132store.allocateNeeded = false133store.deleteServices(httpDNSRR.NamespacedName())134got = store.getAllServices()135if got != nil {136t.Errorf("got unexpected services %v", got)137}138if store.allocateNeeded {139t.Errorf("expected no allocate needed")140}141}
142
143// Tests that when multiple service entries with "DNSRounbRobinLB" resolution type
144// are created with different/same endpoints, we only consider the first service because
145// Envoy's LogicalDNS type of cluster does not allow more than one locality LB Endpoint.
146func TestServiceInstancesForDnsRoundRobinLB(t *testing.T) {147otherNs := ptr.Of(dnsRoundRobinLBSE1.DeepCopy())148otherNs.Namespace = "other"149store := serviceInstancesStore{150ip2instance: map[string][]*model.ServiceInstance{},151instances: map[instancesKey]map[configKey][]*model.ServiceInstance{},152instancesBySE: map[types.NamespacedName]map[configKey][]*model.ServiceInstance{},153instancesByHostAndPort: sets.Set[hostPort]{},154}155instances := []*model.ServiceInstance{156makeInstance(dnsRoundRobinLBSE1, "1.1.1.1", 444, dnsRoundRobinLBSE1.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),157makeInstance(dnsRoundRobinLBSE1, "1.1.1.1", 445, dnsRoundRobinLBSE1.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),158}159cKey := configKey{160namespace: "dns",161name: "dns-round-robin-1",162}163// Add instance related to first Service Entry and validate they are added correctly.164store.addInstances(cKey, instances)165
166store.addInstances(167configKey{namespace: otherNs.Namespace, name: otherNs.Name},168[]*model.ServiceInstance{169makeInstance(otherNs, "1.1.1.1", 444, otherNs.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),170makeInstance(otherNs, "1.1.1.1", 445, otherNs.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),171},172)173
174expected := []*model.ServiceInstance{175makeInstance(dnsRoundRobinLBSE1, "1.1.1.1", 444, dnsRoundRobinLBSE1.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),176makeInstance(dnsRoundRobinLBSE1, "1.1.1.1", 445, dnsRoundRobinLBSE1.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),177}178assert.Equal(t, store.getByKey(instancesKey{179hostname: "example.com",180namespace: "dns",181}), expected)182
183otherNsExpected := []*model.ServiceInstance{184makeInstance(otherNs, "1.1.1.1", 444, otherNs.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),185makeInstance(otherNs, "1.1.1.1", 445, otherNs.Spec.(*networking.ServiceEntry).Ports[1], nil, PlainText),186}187assert.Equal(t, store.getByKey(instancesKey{188hostname: "example.com",189namespace: otherNs.Namespace,190}), otherNsExpected)191
192// Add instance related to second Service Entry and validate it is ignored.193instances = []*model.ServiceInstance{194makeInstance(dnsRoundRobinLBSE2, "2.2.2.2", 444, dnsRoundRobinLBSE2.Spec.(*networking.ServiceEntry).Ports[0], nil, PlainText),195}196cKey = configKey{197namespace: "dns",198name: "dns-round-robin-2",199}200store.addInstances(cKey, instances)201
202assert.Equal(t, store.getByKey(instancesKey{203hostname: "example.com",204namespace: "dns",205}), expected)206assert.Equal(t, store.getByKey(instancesKey{207hostname: "example.com",208namespace: otherNs.Namespace,209}), otherNsExpected)210}
211