github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cli/haproxy_test.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package cli
    12  
    13  import (
    14  	"reflect"
    15  	"testing"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/base"
    18  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb"
    19  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    20  	"github.com/cockroachdb/cockroach/pkg/server/serverpb"
    21  	"github.com/cockroachdb/cockroach/pkg/server/status/statuspb"
    22  	"github.com/cockroachdb/cockroach/pkg/util"
    23  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    24  )
    25  
    26  func TestNodeStatusToNodeInfoConversion(t *testing.T) {
    27  	defer leaktest.AfterTest(t)()
    28  
    29  	testCases := []struct {
    30  		input    serverpb.NodesResponse
    31  		expected []haProxyNodeInfo
    32  	}{
    33  		{
    34  			serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{
    35  				{
    36  					Desc: roachpb.NodeDescriptor{
    37  						NodeID: 1,
    38  						Address: util.UnresolvedAddr{
    39  							AddressField: "addr",
    40  						},
    41  					},
    42  					// Flags but no http port.
    43  					Args: []string{"--unwanted", "-unwanted"},
    44  				},
    45  			}},
    46  			[]haProxyNodeInfo{
    47  				{
    48  					NodeID:    1,
    49  					NodeAddr:  "addr",
    50  					CheckPort: base.DefaultHTTPPort,
    51  				},
    52  			},
    53  		},
    54  		{
    55  			serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{
    56  				{
    57  					Desc: roachpb.NodeDescriptor{NodeID: 1},
    58  					Args: []string{"--unwanted", "--http-port=1234"},
    59  				},
    60  				{
    61  					Desc: roachpb.NodeDescriptor{NodeID: 2},
    62  					Args: nil,
    63  				},
    64  				{
    65  					Desc: roachpb.NodeDescriptor{NodeID: 3},
    66  					Args: []string{"--http-addr=foo:4567"},
    67  				},
    68  			}},
    69  			[]haProxyNodeInfo{
    70  				{
    71  					NodeID:    1,
    72  					CheckPort: "1234",
    73  				},
    74  				{
    75  					NodeID:    2,
    76  					CheckPort: base.DefaultHTTPPort,
    77  				},
    78  				{
    79  					NodeID:    3,
    80  					CheckPort: "4567",
    81  				},
    82  			},
    83  		},
    84  		{
    85  			serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{
    86  				{
    87  					Desc: roachpb.NodeDescriptor{NodeID: 1},
    88  					Args: []string{"--http-port", "5678", "--unwanted"},
    89  				},
    90  			}},
    91  			[]haProxyNodeInfo{
    92  				{
    93  					NodeID:    1,
    94  					CheckPort: "5678",
    95  				},
    96  			},
    97  		},
    98  		{
    99  			serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{
   100  				{
   101  					Desc: roachpb.NodeDescriptor{NodeID: 1},
   102  					// We shouldn't see this, because the flag needs an argument on startup,
   103  					// but check that we fall back to the default port.
   104  					Args: []string{"-http-port"},
   105  				},
   106  			}},
   107  			[]haProxyNodeInfo{
   108  				{
   109  					NodeID:    1,
   110  					CheckPort: base.DefaultHTTPPort,
   111  				},
   112  			},
   113  		},
   114  		// Check that decommission{ing,ed} nodes are not considered for
   115  		// generating the configuration.
   116  		{
   117  			serverpb.NodesResponse{
   118  				Nodes: []statuspb.NodeStatus{
   119  					{Desc: roachpb.NodeDescriptor{NodeID: 1}},
   120  					{Desc: roachpb.NodeDescriptor{NodeID: 2}},
   121  					{Desc: roachpb.NodeDescriptor{NodeID: 3}},
   122  					{Desc: roachpb.NodeDescriptor{NodeID: 4}},
   123  					{Desc: roachpb.NodeDescriptor{NodeID: 5}},
   124  					{Desc: roachpb.NodeDescriptor{NodeID: 6}},
   125  				},
   126  				LivenessByNodeID: map[roachpb.NodeID]kvserverpb.NodeLivenessStatus{
   127  					1: kvserverpb.NodeLivenessStatus_DEAD,
   128  					2: kvserverpb.NodeLivenessStatus_DECOMMISSIONING,
   129  					3: kvserverpb.NodeLivenessStatus_UNKNOWN,
   130  					4: kvserverpb.NodeLivenessStatus_UNAVAILABLE,
   131  					5: kvserverpb.NodeLivenessStatus_LIVE,
   132  					6: kvserverpb.NodeLivenessStatus_DECOMMISSIONED,
   133  				},
   134  			},
   135  			[]haProxyNodeInfo{
   136  				{NodeID: 1, CheckPort: base.DefaultHTTPPort},
   137  				// Node 2 is decommissioning.
   138  				{NodeID: 3, CheckPort: base.DefaultHTTPPort},
   139  				{NodeID: 4, CheckPort: base.DefaultHTTPPort},
   140  				{NodeID: 5, CheckPort: base.DefaultHTTPPort},
   141  				// Node 6 is decommissioned.
   142  			},
   143  		},
   144  	}
   145  
   146  	for i, testCase := range testCases {
   147  		output := nodeStatusesToNodeInfos(&testCase.input)
   148  		if !reflect.DeepEqual(output, testCase.expected) {
   149  			t.Fatalf("test %d: unexpected output %v, expected %v", i, output, testCase.expected)
   150  		}
   151  	}
   152  }
   153  
   154  func TestMatchLocalityRegexp(t *testing.T) {
   155  	defer leaktest.AfterTest(t)()
   156  
   157  	testCases := []struct {
   158  		locality string // The locality as passed to `start --locality=xx`
   159  		desired  string // The desired locality as passed to `gen haproxy --locality=xx`
   160  		matches  bool
   161  	}{
   162  		{"", "", true},
   163  		{"region=us-east1", "", true},
   164  		{"country=us,region=us-east1,datacenter=blah", "", true},
   165  		{"country=us,region=us-east1,datacenter=blah", "country=us", true},
   166  		{"country=us,region=us-east1,datacenter=blah", "count.*=us", false},
   167  		{"country=us,region=us-east1,datacenter=blah", "country=u", false},
   168  		{"country=us,region=us-east1,datacenter=blah", "try=us", false},
   169  		{"country=us,region=us-east1,datacenter=blah", "region=us-east1", true},
   170  		{"country=us,region=us-east1,datacenter=blah", "region=us.*", true},
   171  		{"country=us,region=us-east1,datacenter=blah", "region=us.*,country=us", true},
   172  		{"country=us,region=us-east1,datacenter=blah", "region=notus", false},
   173  		{"country=us,region=us-east1,datacenter=blah", "something=else", false},
   174  		{"country=us,region=us-east1,datacenter=blah", "region=us.*,zone=foo", false},
   175  	}
   176  
   177  	for testNum, testCase := range testCases {
   178  		// We're not testing locality parsing: fail on error.
   179  		var locality, desired roachpb.Locality
   180  		if testCase.locality != "" {
   181  			if err := locality.Set(testCase.locality); err != nil {
   182  				t.Fatal(err)
   183  			}
   184  		}
   185  		if testCase.desired != "" {
   186  			if err := desired.Set(testCase.desired); err != nil {
   187  				t.Fatal(err)
   188  			}
   189  		}
   190  		matches, _ := localityMatches(locality, desired)
   191  		if matches != testCase.matches {
   192  			t.Errorf("#%d: expected match %t, got %t", testNum, testCase.matches, matches)
   193  		}
   194  	}
   195  }