vitess.io/vitess@v0.16.2/go/test/endtoend/clustertest/vtctld_test.go (about) 1 /* 2 Copyright 2019 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 clustertest 19 20 import ( 21 "encoding/json" 22 "fmt" 23 "io" 24 "net/http" 25 "reflect" 26 "strings" 27 "testing" 28 29 "vitess.io/vitess/go/vt/log" 30 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 34 "vitess.io/vitess/go/test/endtoend/cluster" 35 ) 36 37 var ( 38 oneTableOutput = `+---+ 39 | a | 40 +---+ 41 | 1 | 42 +---+ 43 ` 44 ) 45 46 func TestVtctldProcess(t *testing.T) { 47 defer cluster.PanicHandler(t) 48 url := fmt.Sprintf("http://%s:%d/api/keyspaces/", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort) 49 testURL(t, url, "keyspace url") 50 51 healthCheckURL := fmt.Sprintf("http://%s:%d/debug/health", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort) 52 testURL(t, healthCheckURL, "vtctld health check url") 53 54 url = fmt.Sprintf("http://%s:%d/api/topodata/", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort) 55 testTopoDataAPI(t, url) 56 57 testListAllTablets(t) 58 testTabletStatus(t) 59 testExecuteAsDba(t) 60 testExecuteAsApp(t) 61 } 62 63 func testTopoDataAPI(t *testing.T, url string) { 64 resp, err := http.Get(url) 65 require.NoError(t, err) 66 defer resp.Body.Close() 67 assert.Equal(t, resp.StatusCode, 200) 68 69 resultMap := make(map[string]any) 70 respByte, err := io.ReadAll(resp.Body) 71 require.NoError(t, err) 72 err = json.Unmarshal(respByte, &resultMap) 73 require.NoError(t, err) 74 75 errorValue := reflect.ValueOf(resultMap["Error"]) 76 assert.Empty(t, errorValue.String()) 77 78 assert.Contains(t, resultMap, "Children") 79 children := reflect.ValueOf(resultMap["Children"]) 80 childrenGot := fmt.Sprintf("%s", children) 81 assert.Contains(t, childrenGot, "global") 82 assert.Contains(t, childrenGot, clusterInstance.Cell) 83 } 84 85 func testListAllTablets(t *testing.T) { 86 // first w/o any filters, aside from cell 87 result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ListAllTablets", clusterInstance.Cell) 88 require.NoError(t, err) 89 90 tablets := getAllTablets() 91 92 tabletsFromCMD := strings.Split(result, "\n") 93 tabletCountFromCMD := 0 94 95 for _, line := range tabletsFromCMD { 96 if len(line) > 0 { 97 tabletCountFromCMD = tabletCountFromCMD + 1 98 assert.Contains(t, tablets, strings.Split(line, " ")[0]) 99 } 100 } 101 assert.Equal(t, tabletCountFromCMD, len(tablets)) 102 103 // now filtering with the first keyspace and tablet type of primary, in 104 // addition to the cell 105 result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( 106 "ListAllTablets", "--", "--keyspace", clusterInstance.Keyspaces[0].Name, 107 "--tablet_type", "primary", 108 clusterInstance.Cell) 109 require.NoError(t, err) 110 111 // We should only return a single primary tablet per shard in the first keyspace 112 tabletsFromCMD = strings.Split(result, "\n") 113 // We don't count the final newline with nothing after it (it becomes an empty 114 // line at the end of the slice) 115 assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), len(tabletsFromCMD)-1) 116 } 117 118 func testTabletStatus(t *testing.T) { 119 resp, err := http.Get(fmt.Sprintf("http://%s:%d", clusterInstance.Hostname, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].HTTPPort)) 120 require.NoError(t, err) 121 defer resp.Body.Close() 122 respByte, err := io.ReadAll(resp.Body) 123 require.NoError(t, err) 124 result := string(respByte) 125 log.Infof("Tablet status response: %v", result) 126 assert.True(t, strings.Contains(result, `Alias: <a href="http://localhost:`)) 127 assert.True(t, strings.Contains(result, `</html>`)) 128 } 129 130 func testExecuteAsDba(t *testing.T) { 131 result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ExecuteFetchAsDba", clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].Alias, `SELECT 1 AS a`) 132 require.NoError(t, err) 133 assert.Equal(t, result, oneTableOutput) 134 } 135 136 func testExecuteAsApp(t *testing.T) { 137 result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ExecuteFetchAsApp", clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].Alias, `SELECT 1 AS a`) 138 require.NoError(t, err) 139 assert.Equal(t, result, oneTableOutput) 140 } 141 142 func getAllTablets() []string { 143 tablets := make([]string, 0) 144 for _, ks := range clusterInstance.Keyspaces { 145 for _, shard := range ks.Shards { 146 for _, tablet := range shard.Vttablets { 147 tablets = append(tablets, tablet.Alias) 148 } 149 } 150 } 151 return tablets 152 }