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  }