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 }