go.etcd.io/etcd@v3.3.27+incompatible/pkg/srv/srv_test.go (about) 1 // Copyright 2015 The etcd 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 srv 16 17 import ( 18 "errors" 19 "net" 20 "reflect" 21 "strings" 22 "testing" 23 24 "github.com/coreos/etcd/pkg/testutil" 25 ) 26 27 func TestSRVGetCluster(t *testing.T) { 28 defer func() { 29 lookupSRV = net.LookupSRV 30 resolveTCPAddr = net.ResolveTCPAddr 31 }() 32 33 name := "dnsClusterTest" 34 dns := map[string]string{ 35 "1.example.com.:2480": "10.0.0.1:2480", 36 "2.example.com.:2480": "10.0.0.2:2480", 37 "3.example.com.:2480": "10.0.0.3:2480", 38 "4.example.com.:2380": "10.0.0.3:2380", 39 } 40 srvAll := []*net.SRV{ 41 {Target: "1.example.com.", Port: 2480}, 42 {Target: "2.example.com.", Port: 2480}, 43 {Target: "3.example.com.", Port: 2480}, 44 } 45 46 tests := []struct { 47 withSSL []*net.SRV 48 withoutSSL []*net.SRV 49 urls []string 50 51 expected string 52 }{ 53 { 54 []*net.SRV{}, 55 []*net.SRV{}, 56 nil, 57 58 "", 59 }, 60 { 61 srvAll, 62 []*net.SRV{}, 63 nil, 64 65 "0=https://1.example.com:2480,1=https://2.example.com:2480,2=https://3.example.com:2480", 66 }, 67 { 68 srvAll, 69 []*net.SRV{{Target: "4.example.com.", Port: 2380}}, 70 nil, 71 72 "0=https://1.example.com:2480,1=https://2.example.com:2480,2=https://3.example.com:2480,3=http://4.example.com:2380", 73 }, 74 { 75 srvAll, 76 []*net.SRV{{Target: "4.example.com.", Port: 2380}}, 77 []string{"https://10.0.0.1:2480"}, 78 79 "dnsClusterTest=https://1.example.com:2480,0=https://2.example.com:2480,1=https://3.example.com:2480,2=http://4.example.com:2380", 80 }, 81 // matching local member with resolved addr and return unresolved hostnames 82 { 83 srvAll, 84 nil, 85 []string{"https://10.0.0.1:2480"}, 86 87 "dnsClusterTest=https://1.example.com:2480,0=https://2.example.com:2480,1=https://3.example.com:2480", 88 }, 89 // reject if apurls are TLS but SRV is only http 90 { 91 nil, 92 srvAll, 93 []string{"https://10.0.0.1:2480"}, 94 95 "0=http://2.example.com:2480,1=http://3.example.com:2480", 96 }, 97 } 98 99 resolveTCPAddr = func(network, addr string) (*net.TCPAddr, error) { 100 if strings.Contains(addr, "10.0.0.") { 101 // accept IP addresses when resolving apurls 102 return net.ResolveTCPAddr(network, addr) 103 } 104 if dns[addr] == "" { 105 return nil, errors.New("missing dns record") 106 } 107 return net.ResolveTCPAddr(network, dns[addr]) 108 } 109 110 for i, tt := range tests { 111 lookupSRV = func(service string, proto string, domain string) (string, []*net.SRV, error) { 112 if service == "etcd-server-ssl" { 113 return "", tt.withSSL, nil 114 } 115 if service == "etcd-server" { 116 return "", tt.withoutSSL, nil 117 } 118 return "", nil, errors.New("Unknown service in mock") 119 } 120 urls := testutil.MustNewURLs(t, tt.urls) 121 str, err := GetCluster("etcd-server", name, "example.com", urls) 122 if err != nil { 123 t.Fatalf("%d: err: %#v", i, err) 124 } 125 if strings.Join(str, ",") != tt.expected { 126 t.Errorf("#%d: cluster = %s, want %s", i, str, tt.expected) 127 } 128 } 129 } 130 131 func TestSRVDiscover(t *testing.T) { 132 defer func() { lookupSRV = net.LookupSRV }() 133 134 tests := []struct { 135 withSSL []*net.SRV 136 withoutSSL []*net.SRV 137 expected []string 138 }{ 139 { 140 []*net.SRV{}, 141 []*net.SRV{}, 142 []string{}, 143 }, 144 { 145 []*net.SRV{ 146 {Target: "10.0.0.1", Port: 2480}, 147 {Target: "10.0.0.2", Port: 2480}, 148 {Target: "10.0.0.3", Port: 2480}, 149 }, 150 []*net.SRV{}, 151 []string{"https://10.0.0.1:2480", "https://10.0.0.2:2480", "https://10.0.0.3:2480"}, 152 }, 153 { 154 []*net.SRV{ 155 {Target: "10.0.0.1", Port: 2480}, 156 {Target: "10.0.0.2", Port: 2480}, 157 {Target: "10.0.0.3", Port: 2480}, 158 }, 159 []*net.SRV{ 160 {Target: "10.0.0.1", Port: 7001}, 161 }, 162 []string{"https://10.0.0.1:2480", "https://10.0.0.2:2480", "https://10.0.0.3:2480", "http://10.0.0.1:7001"}, 163 }, 164 { 165 []*net.SRV{ 166 {Target: "10.0.0.1", Port: 2480}, 167 {Target: "10.0.0.2", Port: 2480}, 168 {Target: "10.0.0.3", Port: 2480}, 169 }, 170 []*net.SRV{ 171 {Target: "10.0.0.1", Port: 7001}, 172 }, 173 []string{"https://10.0.0.1:2480", "https://10.0.0.2:2480", "https://10.0.0.3:2480", "http://10.0.0.1:7001"}, 174 }, 175 { 176 []*net.SRV{ 177 {Target: "a.example.com", Port: 2480}, 178 {Target: "b.example.com", Port: 2480}, 179 {Target: "c.example.com", Port: 2480}, 180 }, 181 []*net.SRV{}, 182 []string{"https://a.example.com:2480", "https://b.example.com:2480", "https://c.example.com:2480"}, 183 }, 184 } 185 186 for i, tt := range tests { 187 lookupSRV = func(service string, proto string, domain string) (string, []*net.SRV, error) { 188 if service == "etcd-client-ssl" { 189 return "", tt.withSSL, nil 190 } 191 if service == "etcd-client" { 192 return "", tt.withoutSSL, nil 193 } 194 return "", nil, errors.New("Unknown service in mock") 195 } 196 197 srvs, err := GetClient("etcd-client", "example.com") 198 if err != nil { 199 t.Fatalf("%d: err: %#v", i, err) 200 } 201 202 if !reflect.DeepEqual(srvs.Endpoints, tt.expected) { 203 t.Errorf("#%d: endpoints = %v, want %v", i, srvs.Endpoints, tt.expected) 204 } 205 206 } 207 }