istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/xds/nds_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 package xds_test 15 16 import ( 17 "reflect" 18 "testing" 19 "time" 20 21 core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 22 discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" 23 "github.com/google/go-cmp/cmp" 24 "google.golang.org/protobuf/testing/protocmp" 25 26 "istio.io/istio/pilot/pkg/model" 27 "istio.io/istio/pilot/pkg/util/protoconv" 28 v3 "istio.io/istio/pilot/pkg/xds/v3" 29 "istio.io/istio/pilot/test/xds" 30 "istio.io/istio/pkg/config/constants" 31 dnsProto "istio.io/istio/pkg/dns/proto" 32 ) 33 34 func TestNDS(t *testing.T) { 35 cases := []struct { 36 name string 37 meta model.NodeMetadata 38 expected *dnsProto.NameTable 39 }{ 40 { 41 name: "auto allocate", 42 meta: model.NodeMetadata{ 43 DNSCapture: true, 44 DNSAutoAllocate: true, 45 }, 46 expected: &dnsProto.NameTable{ 47 Table: map[string]*dnsProto.NameTable_NameInfo{ 48 "random-1.host.example": { 49 Ips: []string{"240.240.116.21"}, 50 Registry: "External", 51 }, 52 "random-2.host.example": { 53 Ips: []string{"9.9.9.9"}, 54 Registry: "External", 55 }, 56 "random-3.host.example": { 57 Ips: []string{"240.240.81.100"}, 58 Registry: "External", 59 }, 60 }, 61 }, 62 }, 63 { 64 name: "just capture", 65 meta: model.NodeMetadata{ 66 DNSCapture: true, 67 }, 68 expected: &dnsProto.NameTable{ 69 Table: map[string]*dnsProto.NameTable_NameInfo{ 70 "random-2.host.example": { 71 Ips: []string{"9.9.9.9"}, 72 Registry: "External", 73 }, 74 }, 75 }, 76 }, 77 } 78 for _, tt := range cases { 79 t.Run(tt.name, func(t *testing.T) { 80 s := xds.NewFakeDiscoveryServer(t, xds.FakeOptions{ 81 ConfigString: mustReadFile(t, "./testdata/nds-se.yaml"), 82 }) 83 84 ads := s.ConnectADS().WithType(v3.NameTableType) 85 res := ads.RequestResponseAck(t, &discovery.DiscoveryRequest{ 86 Node: &core.Node{ 87 Id: ads.ID, 88 Metadata: tt.meta.ToStruct(), 89 }, 90 }) 91 92 nt := &dnsProto.NameTable{} 93 err := res.Resources[0].UnmarshalTo(nt) 94 if err != nil { 95 t.Fatal("Failed to unmarshal name table", err) 96 return 97 } 98 if len(nt.Table) == 0 { 99 t.Fatalf("expected more than 0 entries in name table") 100 } 101 if diff := cmp.Diff(nt, tt.expected, protocmp.Transform()); diff != "" { 102 t.Fatalf("name table does not match expected value:\n %v", diff) 103 } 104 }) 105 } 106 } 107 108 func TestGenerate(t *testing.T) { 109 nt := &dnsProto.NameTable{ 110 Table: make(map[string]*dnsProto.NameTable_NameInfo), 111 } 112 emptyNameTable := model.Resources{&discovery.Resource{Resource: protoconv.MessageToAny(nt)}} 113 114 cases := []struct { 115 name string 116 proxy *model.Proxy 117 resources []string 118 request *model.PushRequest 119 nameTable []*discovery.Resource 120 }{ 121 { 122 name: "partial push with headless endpoint update", 123 proxy: &model.Proxy{Type: model.SidecarProxy}, 124 request: &model.PushRequest{Reason: model.NewReasonStats(model.HeadlessEndpointUpdate)}, 125 nameTable: emptyNameTable, 126 }, 127 { 128 name: "full push", 129 proxy: &model.Proxy{Type: model.SidecarProxy}, 130 request: &model.PushRequest{Full: true}, 131 nameTable: emptyNameTable, 132 }, 133 { 134 name: "partial push with no headless endpoint update", 135 proxy: &model.Proxy{Type: model.SidecarProxy}, 136 request: &model.PushRequest{}, 137 nameTable: nil, 138 }, 139 } 140 for _, tt := range cases { 141 t.Run(tt.name, func(t *testing.T) { 142 if tt.proxy.Metadata == nil { 143 tt.proxy.Metadata = &model.NodeMetadata{} 144 } 145 tt.proxy.Metadata.ClusterID = constants.DefaultClusterName 146 s := xds.NewFakeDiscoveryServer(t, xds.FakeOptions{}) 147 148 gen := s.Discovery.Generators[v3.NameTableType] 149 tt.request.Start = time.Now() 150 nametable, _, _ := gen.Generate(s.SetupProxy(tt.proxy), &model.WatchedResource{ResourceNames: tt.resources}, tt.request) 151 if len(tt.nameTable) == 0 { 152 if len(nametable) != 0 { 153 t.Errorf("unexpected nametable. want: %v, got: %v", tt.nameTable, nametable) 154 } 155 } else { 156 if !reflect.DeepEqual(tt.nameTable[0].Resource, nametable[0].Resource) { 157 t.Errorf("unexpected nametable. want: %v, got: %v", tt.nameTable, nametable) 158 } 159 } 160 }) 161 } 162 }