vitess.io/vitess@v0.16.2/go/test/endtoend/topoconncache/topo_conn_cache_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  */
    17  
    18  package topoconncache
    19  
    20  import (
    21  	"fmt"
    22  	"os/exec"
    23  	"strings"
    24  	"sync"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  
    30  	"vitess.io/vitess/go/test/endtoend/cluster"
    31  )
    32  
    33  /*
    34  1. In steady state check the numbers of tablets through 'ListAllTablets'.
    35  2. Now delete 'zone2' and 'ListAllTablets' should return only primary tablets
    36  3. Add the cell back with same name but at different location in topo.
    37  4. 'ListAllTablets' should return all the new tablets.
    38  */
    39  func TestVtctldListAllTablets(t *testing.T) {
    40  	defer cluster.PanicHandler(t)
    41  	url := fmt.Sprintf("http://%s:%d/api/keyspaces/", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort)
    42  	testURL(t, url, "keyspace url")
    43  
    44  	healthCheckURL := fmt.Sprintf("http://%s:%d/debug/health", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort)
    45  	testURL(t, healthCheckURL, "vtctld health check url")
    46  
    47  	testListAllTablets(t)
    48  	deleteCell(t)
    49  	addCellback(t)
    50  }
    51  
    52  func testListAllTablets(t *testing.T) {
    53  	// first w/o any filters, aside from cell
    54  	result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ListAllTablets")
    55  	require.NoError(t, err)
    56  
    57  	tablets := getAllTablets()
    58  	tabletsFromCMD := strings.Split(result, "\n")
    59  	tabletCountFromCMD := 0
    60  	for _, line := range tabletsFromCMD {
    61  		if len(line) > 0 {
    62  			tabletCountFromCMD = tabletCountFromCMD + 1
    63  			assert.Contains(t, tablets, strings.Split(line, " ")[0])
    64  		}
    65  	}
    66  	assert.Equal(t, len(tablets), tabletCountFromCMD)
    67  }
    68  
    69  func deleteCell(t *testing.T) {
    70  	// delete all tablets for cell2
    71  	deleteTablet(t, shard1Replica)
    72  	deleteTablet(t, shard2Replica)
    73  	deleteTablet(t, shard1Rdonly)
    74  	deleteTablet(t, shard2Rdonly)
    75  
    76  	// Delete cell2 info from topo
    77  	res, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("DeleteCellInfo", "--", "--force", cell2)
    78  	t.Log(res)
    79  	require.NoError(t, err)
    80  
    81  	// update clusterInstance to remaining vttablets and shards
    82  	shard1.Vttablets = []*cluster.Vttablet{shard1Primary}
    83  	shard2.Vttablets = []*cluster.Vttablet{shard2Primary}
    84  	clusterInstance.Keyspaces[0].Shards = []cluster.Shard{shard1, shard2}
    85  
    86  	// Now list all tablets
    87  	result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ListAllTablets")
    88  	require.NoError(t, err)
    89  
    90  	tablets := getAllTablets()
    91  	tabletsFromCMD := strings.Split(result, "\n")
    92  	tabletCountFromCMD := 0
    93  
    94  	for _, line := range tabletsFromCMD {
    95  		if len(line) > 0 {
    96  			tabletCountFromCMD = tabletCountFromCMD + 1
    97  			assert.Contains(t, tablets, strings.Split(line, " ")[0])
    98  		}
    99  	}
   100  	assert.Equal(t, len(tablets), tabletCountFromCMD)
   101  }
   102  
   103  func deleteTablet(t *testing.T, tablet *cluster.Vttablet) {
   104  	var wg sync.WaitGroup
   105  	wg.Add(1)
   106  	go func(tablet *cluster.Vttablet) {
   107  		defer wg.Done()
   108  		_ = tablet.VttabletProcess.TearDown()
   109  		_ = tablet.MysqlctlProcess.Stop()
   110  		tablet.MysqlctlProcess.CleanupFiles(tablet.TabletUID)
   111  	}(tablet)
   112  	wg.Wait()
   113  
   114  	err := clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", tablet.Alias)
   115  	require.NoError(t, err)
   116  }
   117  
   118  func addCellback(t *testing.T) {
   119  	// creating new cell , with same name as previously deleted one but at a different root path.
   120  	clusterInstance.VtctlProcess.TopoRootPath = "/org1/obj1/"
   121  
   122  	err := clusterInstance.VtctlProcess.AddCellInfo(cell2)
   123  	require.NoError(t, err)
   124  
   125  	// create new vttablets
   126  	shard1Replica = clusterInstance.NewVttabletInstance("replica", 0, cell2)
   127  	shard1Rdonly = clusterInstance.NewVttabletInstance("rdonly", 0, cell2)
   128  	shard2Replica = clusterInstance.NewVttabletInstance("replica", 0, cell2)
   129  	shard2Rdonly = clusterInstance.NewVttabletInstance("rdonly", 0, cell2)
   130  
   131  	// update clusterInstance to new vttablets and shards
   132  	shard1.Vttablets = []*cluster.Vttablet{shard1Primary, shard1Replica, shard1Rdonly}
   133  	shard2.Vttablets = []*cluster.Vttablet{shard2Primary, shard2Replica, shard2Rdonly}
   134  	clusterInstance.Keyspaces[0].Shards = []cluster.Shard{shard1, shard2}
   135  
   136  	// create sql process for vttablets
   137  	var mysqlProcs []*exec.Cmd
   138  	for _, tablet := range []*cluster.Vttablet{shard1Replica, shard1Rdonly, shard2Replica, shard2Rdonly} {
   139  		tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory)
   140  		tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort,
   141  			tablet.GrpcPort,
   142  			tablet.TabletUID,
   143  			tablet.Cell,
   144  			"",
   145  			keyspaceName,
   146  			clusterInstance.VtctldProcess.Port,
   147  			tablet.Type,
   148  			clusterInstance.TopoPort,
   149  			hostname,
   150  			clusterInstance.TmpDirectory,
   151  			commonTabletArg,
   152  			clusterInstance.DefaultCharset,
   153  		)
   154  		tablet.VttabletProcess.SupportsBackup = true
   155  		proc, err := tablet.MysqlctlProcess.StartProcess()
   156  		require.NoError(t, err)
   157  		mysqlProcs = append(mysqlProcs, proc)
   158  	}
   159  	for _, proc := range mysqlProcs {
   160  		err := proc.Wait()
   161  		require.NoError(t, err)
   162  	}
   163  
   164  	for _, tablet := range []*cluster.Vttablet{shard1Replica, shard1Rdonly} {
   165  		tablet.VttabletProcess.Shard = shard1.Name
   166  		// The tablet should come up as serving since the primary for the shard already exists
   167  		tablet.VttabletProcess.ServingStatus = "SERVING"
   168  		err := tablet.VttabletProcess.Setup()
   169  		require.NoError(t, err)
   170  	}
   171  
   172  	for _, tablet := range []*cluster.Vttablet{shard2Replica, shard2Rdonly} {
   173  		tablet.VttabletProcess.Shard = shard2.Name
   174  		// The tablet should come up as serving since the primary for the shard already exists
   175  		tablet.VttabletProcess.ServingStatus = "SERVING"
   176  		err := tablet.VttabletProcess.Setup()
   177  		require.NoError(t, err)
   178  	}
   179  
   180  	shard1.Vttablets = append(shard1.Vttablets, shard1Replica)
   181  	shard1.Vttablets = append(shard1.Vttablets, shard1Rdonly)
   182  	shard2.Vttablets = append(shard2.Vttablets, shard2Replica)
   183  	shard2.Vttablets = append(shard2.Vttablets, shard1Rdonly)
   184  
   185  	result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ListAllTablets")
   186  	require.NoError(t, err)
   187  
   188  	tablets := getAllTablets()
   189  	tabletsFromCMD := strings.Split(result, "\n")
   190  	tabletCountFromCMD := 0
   191  	for _, line := range tabletsFromCMD {
   192  		if len(line) > 0 {
   193  			tabletCountFromCMD = tabletCountFromCMD + 1
   194  			assert.Contains(t, tablets, strings.Split(line, " ")[0])
   195  		}
   196  	}
   197  	assert.Equal(t, len(tablets), tabletCountFromCMD)
   198  }
   199  
   200  func getAllTablets() []string {
   201  	tablets := make([]string, 0)
   202  	for _, ks := range clusterInstance.Keyspaces {
   203  		for _, shard := range ks.Shards {
   204  			for _, tablet := range shard.Vttablets {
   205  				tablets = append(tablets, tablet.Alias)
   206  			}
   207  		}
   208  	}
   209  	return tablets
   210  }