blob: 96e2b46d4899dee2ea684fab96a180a202d4a2cc [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model_test
import (
"fmt"
"net"
"reflect"
"sync"
"testing"
"time"
)
import (
"github.com/miekg/dns"
meshconfig "istio.io/api/mesh/v1alpha1"
)
import (
"github.com/apache/dubbo-go-pixiu/pilot/pkg/model"
"github.com/apache/dubbo-go-pixiu/pilot/pkg/serviceregistry/memory"
"github.com/apache/dubbo-go-pixiu/pilot/pkg/xds"
"github.com/apache/dubbo-go-pixiu/pkg/config/mesh"
"github.com/apache/dubbo-go-pixiu/pkg/test/scopes"
"github.com/apache/dubbo-go-pixiu/pkg/test/util/retry"
"github.com/apache/dubbo-go-pixiu/pkg/util/sets"
)
func TestGatewayHostnames(t *testing.T) {
origMinGatewayTTL := model.MinGatewayTTL
model.MinGatewayTTL = 30 * time.Millisecond
t.Cleanup(func() {
model.MinGatewayTTL = origMinGatewayTTL
})
gwHost := "test.gw.istio.io"
dnsServer := newFakeDNSServer(":0", 1, sets.New(gwHost))
model.NetworkGatewayTestDNSServers = []string{dnsServer.Server.PacketConn.LocalAddr().String()}
t.Cleanup(func() {
if err := dnsServer.Shutdown(); err != nil {
t.Logf("failed shutting down fake dns server")
}
})
meshNetworks := mesh.NewFixedNetworksWatcher(nil)
xdsUpdater := &xds.FakeXdsUpdater{Events: make(chan xds.FakeXdsEvent, 10)}
env := &model.Environment{NetworksWatcher: meshNetworks, ServiceDiscovery: memory.NewServiceDiscovery()}
if err := env.InitNetworksManager(xdsUpdater); err != nil {
t.Fatal(err)
}
var firstIP string
t.Run("initial resolution", func(t *testing.T) {
meshNetworks.SetNetworks(&meshconfig.MeshNetworks{Networks: map[string]*meshconfig.Network{
"nw0": {Gateways: []*meshconfig.Network_IstioNetworkGateway{{
Gw: &meshconfig.Network_IstioNetworkGateway_Address{
Address: gwHost,
},
Port: 15443,
}}},
}})
xdsUpdater.WaitDurationOrFail(t, model.MinGatewayTTL+5*time.Second, "xds")
gws := env.NetworkManager.AllGateways()
if len(gws) != 1 {
t.Fatalf("expected 1 IP")
}
if gws[0].Network != "nw0" {
t.Fatalf("unexpected network: %v", gws)
}
firstIP = gws[0].Addr
})
t.Run("re-resolve after TTL", func(t *testing.T) {
if testing.Short() {
t.Skip()
}
// after the update, we should see the next gateway. Since TTL is low we don't know the exact IP, but we know it should change from
// the original
retry.UntilOrFail(t, func() bool {
return !reflect.DeepEqual(env.NetworkManager.AllGateways(), []model.NetworkGateway{{Network: "nw0", Addr: firstIP, Port: 15443}})
})
})
t.Run("forget", func(t *testing.T) {
meshNetworks.SetNetworks(nil)
xdsUpdater.WaitDurationOrFail(t, 5*time.Second, "xds")
if len(env.NetworkManager.AllGateways()) > 0 {
t.Fatalf("expected no gateways")
}
})
}
type fakeDNSServer struct {
*dns.Server
ttl uint32
mu sync.Mutex
// map fqdn hostname -> query count
hosts map[string]int
}
func newFakeDNSServer(addr string, ttl uint32, hosts sets.Set) *fakeDNSServer {
waitLock := sync.Mutex{}
waitLock.Lock()
s := &fakeDNSServer{
Server: &dns.Server{Addr: addr, Net: "udp", NotifyStartedFunc: waitLock.Unlock},
ttl: ttl,
hosts: make(map[string]int, len(hosts)),
}
s.Handler = s
for k := range hosts {
s.hosts[dns.Fqdn(k)] = 0
}
go func() {
if err := s.ListenAndServe(); err != nil {
scopes.Framework.Errorf("fake dns server error: %v", err)
}
}()
waitLock.Lock()
return s
}
func (s *fakeDNSServer) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
s.mu.Lock()
defer s.mu.Unlock()
msg := (&dns.Msg{}).SetReply(r)
switch r.Question[0].Qtype {
case dns.TypeA, dns.TypeANY:
domain := msg.Question[0].Name
c, ok := s.hosts[domain]
if ok {
s.hosts[domain]++
msg.Answer = append(msg.Answer, &dns.A{
Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl},
A: net.ParseIP(fmt.Sprintf("10.0.0.%d", c)),
})
}
}
if err := w.WriteMsg(msg); err != nil {
scopes.Framework.Errorf("failed writing fake DNS response: %v", err)
}
}