vitess.io/vitess@v0.16.2/go/test/endtoend/topoconncache/main_test.go (about)

     1  /*
     2  Copyright 2022 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  
    16  This test cell aliases feature
    17  
    18  We start with no aliases and assert that vtgates can't route to replicas/rondly tablets.
    19  Then we add an alias, and these tablets should be routable
    20  */
    21  
    22  package topoconncache
    23  
    24  import (
    25  	"flag"
    26  	"fmt"
    27  	"net/http"
    28  	"os"
    29  	"os/exec"
    30  	"testing"
    31  
    32  	"vitess.io/vitess/go/test/endtoend/cluster"
    33  )
    34  
    35  var (
    36  	clusterInstance *cluster.LocalProcessCluster
    37  	cell1           = "zone1"
    38  	cell2           = "zone2"
    39  	hostname        = "localhost"
    40  	keyspaceName    = "ks"
    41  	tableName       = "test_table"
    42  	sqlSchema       = `
    43  					create table %s(
    44  					id bigint(20) unsigned auto_increment,
    45  					msg varchar(64),
    46  					primary key (id),
    47  					index by_msg (msg)
    48  					) Engine=InnoDB
    49  `
    50  	commonTabletArg = []string{
    51  		"--vreplication_healthcheck_topology_refresh", "1s",
    52  		"--vreplication_healthcheck_retry_delay", "1s",
    53  		"--vreplication_retry_delay", "1s",
    54  		"--degraded_threshold", "5s",
    55  		"--lock_tables_timeout", "5s",
    56  		"--watch_replication_stream",
    57  		"--enable_replication_reporter",
    58  		"--serving_state_grace_period", "1s",
    59  		"--binlog_player_protocol", "grpc",
    60  	}
    61  	vSchema = `
    62  		{
    63  		  "sharded": true,
    64  		  "vindexes": {
    65  			"hash_index": {
    66  			  "type": "hash"
    67  			}
    68  		  },
    69  		  "tables": {
    70  			"%s": {
    71  			   "column_vindexes": [
    72  				{
    73  				  "column": "id",
    74  				  "name": "hash_index"
    75  				}
    76  			  ]
    77  			}
    78  		  }
    79  		}
    80  `
    81  	shard1Primary *cluster.Vttablet
    82  	shard1Replica *cluster.Vttablet
    83  	shard1Rdonly  *cluster.Vttablet
    84  	shard2Primary *cluster.Vttablet
    85  	shard2Replica *cluster.Vttablet
    86  	shard2Rdonly  *cluster.Vttablet
    87  
    88  	shard1 cluster.Shard
    89  	shard2 cluster.Shard
    90  )
    91  
    92  /*
    93  	This end-to-end test validates the cache fix in topo/server.go inside ConnForCell.
    94  
    95  The issue was, if we delete and add back a cell with same name but at different path, the map of cells
    96  in server.go returned the connection object of the previous cell instead of newly-created one
    97  with the same name.
    98  Topology: We create a keyspace with two shards , having 3 tablets each. Primaries belong
    99  to 'zone1' and replicas/rdonly belongs to cell2.
   100  */
   101  func TestMain(m *testing.M) {
   102  	defer cluster.PanicHandler(nil)
   103  	flag.Parse()
   104  
   105  	exitcode, err := func() (int, error) {
   106  		clusterInstance = cluster.NewCluster(cell1, hostname)
   107  		defer clusterInstance.Teardown()
   108  		clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, cluster.Keyspace{
   109  			Name: keyspaceName,
   110  		})
   111  
   112  		// Start topo server
   113  		if err := clusterInstance.StartTopo(); err != nil {
   114  			return 1, err
   115  		}
   116  
   117  		// Adding another cell in the same cluster
   118  		err := clusterInstance.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+cell2)
   119  		if err != nil {
   120  			return 1, err
   121  		}
   122  		err = clusterInstance.VtctlProcess.AddCellInfo(cell2)
   123  		if err != nil {
   124  			return 1, err
   125  		}
   126  
   127  		vtctldClientProcess := cluster.VtctldClientProcessInstance("localhost", clusterInstance.VtctldProcess.GrpcPort, clusterInstance.TmpDirectory)
   128  		_, err = vtctldClientProcess.ExecuteCommandWithOutput("CreateKeyspace", keyspaceName, "--durability-policy=semi_sync")
   129  		if err != nil {
   130  			return 1, err
   131  		}
   132  
   133  		shard1Primary = clusterInstance.NewVttabletInstance("primary", 0, cell1)
   134  		shard1Replica = clusterInstance.NewVttabletInstance("replica", 0, cell2)
   135  		shard1Rdonly = clusterInstance.NewVttabletInstance("rdonly", 0, cell2)
   136  
   137  		shard2Primary = clusterInstance.NewVttabletInstance("primary", 0, cell1)
   138  		shard2Replica = clusterInstance.NewVttabletInstance("replica", 0, cell2)
   139  		shard2Rdonly = clusterInstance.NewVttabletInstance("rdonly", 0, cell2)
   140  
   141  		var mysqlProcs []*exec.Cmd
   142  		for _, tablet := range []*cluster.Vttablet{shard1Primary, shard1Replica, shard1Rdonly, shard2Primary, shard2Replica, shard2Rdonly} {
   143  			tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory)
   144  			tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort,
   145  				tablet.GrpcPort,
   146  				tablet.TabletUID,
   147  				tablet.Cell,
   148  				"",
   149  				keyspaceName,
   150  				clusterInstance.VtctldProcess.Port,
   151  				tablet.Type,
   152  				clusterInstance.TopoPort,
   153  				hostname,
   154  				clusterInstance.TmpDirectory,
   155  				commonTabletArg,
   156  				clusterInstance.DefaultCharset,
   157  			)
   158  			tablet.VttabletProcess.SupportsBackup = true
   159  			proc, err := tablet.MysqlctlProcess.StartProcess()
   160  			if err != nil {
   161  				return 1, err
   162  			}
   163  			mysqlProcs = append(mysqlProcs, proc)
   164  		}
   165  		for _, proc := range mysqlProcs {
   166  			if err := proc.Wait(); err != nil {
   167  				return 1, err
   168  			}
   169  		}
   170  
   171  		shard1 = cluster.Shard{
   172  			Name:      "-80",
   173  			Vttablets: []*cluster.Vttablet{shard1Primary, shard1Replica, shard1Rdonly},
   174  		}
   175  		for idx := range shard1.Vttablets {
   176  			shard1.Vttablets[idx].VttabletProcess.Shard = shard1.Name
   177  		}
   178  		clusterInstance.Keyspaces[0].Shards = append(clusterInstance.Keyspaces[0].Shards, shard1)
   179  
   180  		shard2 = cluster.Shard{
   181  			Name:      "80-",
   182  			Vttablets: []*cluster.Vttablet{shard2Primary, shard2Replica, shard2Rdonly},
   183  		}
   184  		for idx := range shard2.Vttablets {
   185  			shard2.Vttablets[idx].VttabletProcess.Shard = shard2.Name
   186  		}
   187  		clusterInstance.Keyspaces[0].Shards = append(clusterInstance.Keyspaces[0].Shards, shard2)
   188  
   189  		for _, tablet := range shard1.Vttablets {
   190  			if err := tablet.VttabletProcess.Setup(); err != nil {
   191  				return 1, err
   192  			}
   193  		}
   194  		if err := clusterInstance.VtctlclientProcess.InitializeShard(keyspaceName, shard1.Name, shard1Primary.Cell, shard1Primary.TabletUID); err != nil {
   195  			return 1, err
   196  		}
   197  
   198  		// run a health check on source replica so it responds to discovery
   199  		// (for binlog players) and on the source rdonlys (for workers)
   200  		for _, tablet := range []string{shard1Replica.Alias, shard1Rdonly.Alias} {
   201  			if err := clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet); err != nil {
   202  				return 1, err
   203  			}
   204  		}
   205  
   206  		for _, tablet := range shard2.Vttablets {
   207  			if err := tablet.VttabletProcess.Setup(); err != nil {
   208  				return 1, err
   209  			}
   210  		}
   211  
   212  		if err := clusterInstance.VtctlclientProcess.InitializeShard(keyspaceName, shard2.Name, shard2Primary.Cell, shard2Primary.TabletUID); err != nil {
   213  			return 1, err
   214  		}
   215  
   216  		if err := clusterInstance.StartVTOrc(keyspaceName); err != nil {
   217  			return 1, err
   218  		}
   219  
   220  		if err := clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(sqlSchema, tableName)); err != nil {
   221  			return 1, err
   222  		}
   223  		if err := clusterInstance.VtctlclientProcess.ApplyVSchema(keyspaceName, fmt.Sprintf(vSchema, tableName)); err != nil {
   224  			return 1, err
   225  		}
   226  
   227  		_ = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName)
   228  
   229  		return m.Run(), nil
   230  	}()
   231  	if err != nil {
   232  		fmt.Printf("%v\n", err)
   233  		os.Exit(1)
   234  	} else {
   235  		os.Exit(exitcode)
   236  	}
   237  }
   238  
   239  func testURL(t *testing.T, url string, testCaseName string) {
   240  	statusCode := getStatusForURL(url)
   241  	if got, want := statusCode, 200; got != want {
   242  		t.Errorf("\nurl: %v\nstatus code: %v \nwant %v for %s", url, got, want, testCaseName)
   243  	}
   244  }
   245  
   246  // getStatusForUrl returns the status code for the URL
   247  func getStatusForURL(url string) int {
   248  	resp, err := http.Get(url)
   249  	if err != nil {
   250  		return 0
   251  	}
   252  	defer resp.Body.Close()
   253  	return resp.StatusCode
   254  }