diff --git a/.github/workflows/check_make_parser.yml b/.github/workflows/check_make_parser.yml index efc6c737e73..c46f5bffc5f 100644 --- a/.github/workflows/check_make_parser.yml +++ b/.github/workflows/check_make_parser.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/cluster_endtoend.yml b/.github/workflows/cluster_endtoend.yml index 5d31167f707..448622241a1 100644 --- a/.github/workflows/cluster_endtoend.yml +++ b/.github/workflows/cluster_endtoend.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/e2e_race.yml b/.github/workflows/e2e_race.yml index 2e6fb4f4938..040639d96b6 100644 --- a/.github/workflows/e2e_race.yml +++ b/.github/workflows/e2e_race.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/endtoend.yml b/.github/workflows/endtoend.yml index b10977d4860..7a0c594ee35 100644 --- a/.github/workflows/endtoend.yml +++ b/.github/workflows/endtoend.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/local_example.yml b/.github/workflows/local_example.yml index b08ce73f886..496229ade18 100644 --- a/.github/workflows/local_example.yml +++ b/.github/workflows/local_example.yml @@ -17,7 +17,7 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 37df2da855a..7ea0e8b7c1a 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -19,31 +19,59 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" + sudo apt-get update if [ ${{matrix.name}} = "mysql57" ]; then sudo apt-get install -y mysql-server mysql-client - elif [ ${{matrix.name}} = "mysql80" ]; then + else + # Uninstall likely installed MySQL first sudo apt-get remove -y mysql-server mysql-client - sudo rm -rf /var/lib/mysql - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb - echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections - sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* - sudo apt-get update || echo "update failed" - sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-server mysql-client - elif [ ${{matrix.name}} = "mariadb101" ]; then - sudo apt-get remove -y mysql-server mysql-client - sudo apt install -y mariadb-server mariadb-client - sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 + + if [ ${{matrix.name}} = "percona56" ]; then + # Currently this fails on vt/vttablet/tabletserver/vstreamer + # Once we fix issue #5571 we can enable it. + sudo rm -rf /var/lib/mysql + wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb + sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y percona-server-server-5.6 percona-server-client-5.6 + elif [ ${{matrix.name}} = "mysql80" ]; then + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb + echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections + sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* + sudo apt-get update + sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-server mysql-client + elif [ ${{matrix.name}} = "mariadb101" ]; then + sudo apt install -y mariadb-server mariadb-client + elif [ ${{matrix.name}} = "mariadb102" ]; then + # Currently this fails on vitess.io/vitess/go/mysql + # Once we fix issue #5569 we can enable it. + sudo apt-get install -y software-properties-common + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 + sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.2/ubuntu bionic main' + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt install -y mariadb-server + elif [ ${{matrix.name}} = "mariadb103" ]; then + # Currently this fails on vitess.io/vitess/go/mysql + # Once we fix issue #5569 we can enable it. + sudo apt-get install -y software-properties-common + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 + sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.3/ubuntu bionic main' + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt install -y mariadb-server + fi fi sudo apt-get install -y make unzip g++ curl git wget ant openjdk-8-jdk sudo service mysql stop + sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ - sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld || echo "could not remove mysqld profile" + mkdir -p dist bin curl -L https://github.com/coreos/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz | tar -zxC dist mv dist/etcd-v3.3.10-linux-amd64/{etcd,etcdctl} bin/ + go mod download - name: Run make tools diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml index 6f065bf2737..fb1c6d5b822 100644 --- a/.github/workflows/unit_race.yml +++ b/.github/workflows/unit_race.yml @@ -17,12 +17,17 @@ jobs: - name: Get dependencies run: | - sudo apt-get update || echo "update failed" - sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ curl git wget sudo service mysql stop sudo service etcd stop sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + + mkdir -p dist bin + curl -L https://github.com/coreos/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz | tar -zxC dist + mv dist/etcd-v3.3.10-linux-amd64/{etcd,etcdctl} bin/ + go mod download - name: Run make tools diff --git a/go/cmd/vtqueryserver/index.go b/go/cmd/vtqueryserver/index.go deleted file mode 100644 index be06ed6f10b..00000000000 --- a/go/cmd/vtqueryserver/index.go +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "net/http" -) - -// This is a separate file so it can be selectively included/excluded from -// builds to opt in/out of the redirect. - -func init() { - // Anything unrecognized gets redirected to the status page. - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/debug/status", http.StatusFound) - }) -} diff --git a/go/cmd/vtqueryserver/plugin_auth_static.go b/go/cmd/vtqueryserver/plugin_auth_static.go deleted file mode 100644 index 84cdec6cec0..00000000000 --- a/go/cmd/vtqueryserver/plugin_auth_static.go +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreedto in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -// This plugin imports staticauthserver to register the flat-file implementation of AuthServer. - -import ( - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/vt/vtqueryserver" -) - -func init() { - vtqueryserver.RegisterPluginInitializer(func() { mysql.InitAuthServerStatic() }) -} diff --git a/go/cmd/vtqueryserver/plugin_grpcqueryservice.go b/go/cmd/vtqueryserver/plugin_grpcqueryservice.go deleted file mode 100644 index 0d574f33a5f..00000000000 --- a/go/cmd/vtqueryserver/plugin_grpcqueryservice.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -// Imports and register the gRPC queryservice server - -import ( - "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/vttablet/grpcqueryservice" - "vitess.io/vitess/go/vt/vttablet/tabletserver" -) - -func init() { - tabletserver.RegisterFunctions = append(tabletserver.RegisterFunctions, func(qsc tabletserver.Controller) { - if servenv.GRPCCheckServiceMap("queryservice") { - grpcqueryservice.Register(servenv.GRPCServer, qsc.QueryService()) - } - }) - -} diff --git a/go/cmd/vtqueryserver/plugin_opentracing.go b/go/cmd/vtqueryserver/plugin_opentracing.go deleted file mode 100644 index 43cdf6ce589..00000000000 --- a/go/cmd/vtqueryserver/plugin_opentracing.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "vitess.io/vitess/go/trace" - - "vitess.io/vitess/go/vt/servenv" -) - -func init() { - servenv.OnRun(func() { - closer := trace.StartTracing("vtqueryserver") - servenv.OnClose(trace.LogErrorsWhenClosing(closer)) - }) -} diff --git a/go/cmd/vtqueryserver/vtqueryserver.go b/go/cmd/vtqueryserver/vtqueryserver.go deleted file mode 100644 index 705c2bc9c38..00000000000 --- a/go/cmd/vtqueryserver/vtqueryserver.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "flag" - "os" - - "vitess.io/vitess/go/vt/dbconfigs" - "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/vtqueryserver" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" -) - -var ( - dbName string - mysqlSocketFile = flag.String("mysql-socket-file", "", "path to unix socket file to connect to mysql") -) - -func init() { - servenv.RegisterDefaultFlags() - // TODO(demmer): remove once migrated to using db_name - flag.StringVar(&dbName, "db-config-app-dbname", "", "db connection dbname") - flag.StringVar(&dbName, "db_name", "", "db connection dbname") -} - -func main() { - dbconfigs.RegisterFlags(dbconfigs.App, dbconfigs.AppDebug) - flag.Parse() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - - if len(flag.Args()) > 0 { - flag.Usage() - log.Exit("vtqueryserver doesn't take any positional arguments") - } - if err := tabletenv.VerifyConfig(); err != nil { - log.Exitf("invalid config: %v", err) - } - - tabletenv.Init() - - servenv.Init() - - dbcfgs, err := dbconfigs.Init(*mysqlSocketFile) - if err != nil { - log.Fatal(err) - } - // DB name must be explicitly set. - dbcfgs.DBName.Set(dbName) - - err = vtqueryserver.Init(dbcfgs) - if err != nil { - log.Exitf("error initializing proxy: %v", err) - } - - servenv.RunDefault() -} diff --git a/go/mysql/server_test.go b/go/mysql/server_flaky_test.go similarity index 100% rename from go/mysql/server_test.go rename to go/mysql/server_flaky_test.go diff --git a/go/vt/topo/consultopo/server_test.go b/go/vt/topo/consultopo/server_flaky_test.go similarity index 100% rename from go/vt/topo/consultopo/server_test.go rename to go/vt/topo/consultopo/server_flaky_test.go diff --git a/go/vt/vtqueryserver/endtoend_test.go b/go/vt/vtqueryserver/endtoend_test.go deleted file mode 100644 index 4e981967a02..00000000000 --- a/go/vt/vtqueryserver/endtoend_test.go +++ /dev/null @@ -1,489 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package vtqueryserver - -import ( - "context" - "flag" - "fmt" - "io/ioutil" - "os" - "strings" - "testing" - "time" - - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/dbconfigs" - "vitess.io/vitess/go/vt/vttablet/tabletserver" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" - "vitess.io/vitess/go/vt/vttest" - - vttestpb "vitess.io/vitess/go/vt/proto/vttest" -) - -var ( - queryServer *tabletserver.TabletServer - mysqlConnParams mysql.ConnParams - proxyConnParams mysql.ConnParams -) - -func TestMain(m *testing.M) { - flag.Parse() // Do not remove this comment, import into google3 depends on it - tabletenv.Init() - - exitCode := func() int { - // Launch MySQL. - // We need a Keyspace in the topology, so the DbName is set. - // We need a Shard too, so the database 'vttest' is created. - cfg := vttest.Config{ - Topology: &vttestpb.VTTestTopology{ - Keyspaces: []*vttestpb.Keyspace{ - { - Name: "vttest", - Shards: []*vttestpb.Shard{ - { - Name: "0", - DbNameOverride: "vttest", - }, - }, - }, - }, - }, - OnlyMySQL: true, - } - if err := cfg.InitSchemas("vttest", testSchema, nil); err != nil { - fmt.Fprintf(os.Stderr, "InitSchemas failed: %v\n", err) - return 1 - } - defer os.RemoveAll(cfg.SchemaDir) - cluster := vttest.LocalCluster{ - Config: cfg, - } - if err := cluster.Setup(); err != nil { - fmt.Fprintf(os.Stderr, "could not launch mysql: %v\n", err) - return 1 - } - defer cluster.TearDown() - mysqlConnParams = cluster.MySQLConnParams() - - // Setup a unix socket to connect to the proxy. - // We use a temporary file. - unixSocket, err := ioutil.TempFile("", "mysqlproxy.sock") - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to create temp file: %v", err) - return 1 - } - proxySock := unixSocket.Name() - os.Remove(proxySock) - - proxyConnParams.UnixSocket = proxySock - proxyConnParams.Uname = "proxy" - proxyConnParams.Pass = "letmein" - - *mysqlServerSocketPath = proxyConnParams.UnixSocket - *mysqlAuthServerImpl = "none" - - // set a short query timeout and a constrained connection pool - // to test that end to end timeouts work - tabletenv.Config.QueryTimeout = 2 - tabletenv.Config.PoolSize = 1 - tabletenv.Config.QueryPoolTimeout = 0.1 - defer func() { tabletenv.Config = tabletenv.DefaultQsConfig }() - - // Initialize the query service on top of the vttest MySQL database. - dbcfgs := dbconfigs.NewTestDBConfigs(mysqlConnParams, mysqlConnParams, cluster.DbName()) - queryServer, err = initProxy(dbcfgs) - if err != nil { - fmt.Fprintf(os.Stderr, "could not start proxy: %v\n", err) - return 1 - } - defer queryServer.StopService() - - // Initialize the MySQL server protocol to talk to the query service. - initMySQLProtocol() - defer shutdownMySQLProtocol() - - return m.Run() - }() - os.Exit(exitCode) -} - -var testSchema = ` -create table test(id int, val varchar(256), primary key(id)); -create table valtest(intval int default 0, floatval float default null, charval varchar(256) default null, binval varbinary(256) default null, primary key(intval)); -` - -func testFetch(t *testing.T, conn *mysql.Conn, sql string, expectedRows int) *sqltypes.Result { - t.Helper() - - result, err := conn.ExecuteFetch(sql, 1000, false) - if err != nil { - t.Errorf("error: %v", err) - return nil - } - - if len(result.Rows) != expectedRows { - t.Errorf("expected %d rows but got %d", expectedRows, len(result.Rows)) - } - - return result -} - -func testDML(t *testing.T, conn *mysql.Conn, sql string, expectedNumQueries int64, expectedRowsAffected uint64) { - t.Helper() - - numQueries := tabletenv.MySQLStats.Counts()["Exec"] - result, err := conn.ExecuteFetch(sql, 1000, false) - if err != nil { - t.Errorf("error: %v", err) - } - numQueries = tabletenv.MySQLStats.Counts()["Exec"] - numQueries - - if numQueries != expectedNumQueries { - t.Errorf("expected %d mysql queries but got %d", expectedNumQueries, numQueries) - } - - if result.RowsAffected != expectedRowsAffected { - t.Errorf("expected %d rows affected but got %d", expectedRowsAffected, result.RowsAffected) - } -} - -func TestQueries(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - // Try a simple query case. - testFetch(t, conn, "select * from test", 0) - - // Try a simple error case. - _, err = conn.ExecuteFetch("select * from aa", 1000, true) - if err == nil || !strings.Contains(err.Error(), "table aa not found in schema") { - t.Fatalf("expected error but got: %v", err) - } -} - -func TestAutocommitDMLs(t *testing.T) { - ctx := context.Background() - - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testDML(t, conn, "insert into test (id, val) values(1, 'hello')", 3, 1) - - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - testDML(t, conn, "delete from test", 4, 1) - - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 0) -} - -func TestPassthroughDMLs(t *testing.T) { - ctx := context.Background() - - queryServer.SetPassthroughDMLs(true) - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testDML(t, conn, "insert into test (id, val) values(1, 'hello')", 3, 1) - testDML(t, conn, "insert into test (id, val) values(2, 'hello')", 3, 1) - testDML(t, conn, "insert into test (id, val) values(3, 'hello')", 3, 1) - - // Subquery DMLs are errors in passthrough mode with SBR, unless - // SetAllowUnsafeDMLs is set - _, err = conn.ExecuteFetch("update test set val='goodbye'", 1000, true) - if err == nil || !strings.Contains(err.Error(), "cannot identify primary key of statement") { - t.Fatalf("expected error but got: %v", err) - } - - queryServer.SetAllowUnsafeDMLs(true) - - // This is 3 queries in passthrough mode and not 4 queries as it would - // be in non-passthrough mode - testDML(t, conn, "update test set val='goodbye'", 3, 3) - - testFetch(t, conn, "select * from test where val='goodbye'", 3) - testFetch(t, conn2, "select * from test where val='goodbye'", 3) - - testDML(t, conn, "delete from test", 4, 3) - - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 0) -} - -func TestTransactions(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testDML(t, conn, "begin", 1, 0) - testDML(t, conn, "insert into test (id, val) values(1, 'hello')", 1, 1) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 0) - testDML(t, conn, "commit", 1, 0) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - testDML(t, conn, "begin", 1, 0) - testDML(t, conn, "delete from test", 2, 1) - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 1) - testDML(t, conn, "rollback", 1, 0) - - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - testDML(t, conn2, "begin", 1, 0) - testDML(t, conn2, "delete from test", 2, 1) - testDML(t, conn2, "commit", 1, 0) - - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 0) -} - -func TestNoAutocommit(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testFetch(t, conn, "set autocommit=0", 0) - - testDML(t, conn, "insert into test (id, val) values(1, 'hello')", 2, 1) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 0) - testDML(t, conn, "commit", 1, 0) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - testDML(t, conn, "delete from test", 3, 1) - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 1) - testDML(t, conn, "rollback", 1, 0) - - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - testFetch(t, conn2, "set autocommit=0", 0) - testDML(t, conn2, "delete from test", 3, 1) - testDML(t, conn2, "commit", 1, 0) - - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 0) -} - -func TestTransactionsInProcess(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testDML(t, conn, "begin", 1, 0) - testDML(t, conn, "insert into test (id, val) values(1, 'hello')", 1, 1) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 0) - - // A second begin causes the first transaction to commit and then - // runs the begin - testDML(t, conn, "begin", 2, 0) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - testDML(t, conn, "rollback", 1, 0) - - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - // Setting autocommit=1 (when it was previously 0) causes the existing transaction to commit - testDML(t, conn, "set autocommit=0", 0, 0) - // (2 queries -- begin b/c autocommit = 0; insert) - testDML(t, conn, "insert into test (id, val) values(2, 'hello')", 2, 1) - testFetch(t, conn, "select * from test", 2) - testFetch(t, conn2, "select * from test", 1) - - // (1 query -- commit b/c of autocommit change) - testDML(t, conn, "set autocommit=1", 1, 0) - testFetch(t, conn, "select * from test", 2) - testFetch(t, conn2, "select * from test", 2) - - // Setting autocommit=1 doesn't cause the existing transaction to commit if it was already - // autocommit=1. Therefore rollback is effective. - testDML(t, conn, "set autocommit=1", 0, 0) - testDML(t, conn, "begin", 1, 0) - testDML(t, conn, "insert into test (id, val) values(3, 'hello')", 1, 1) - testFetch(t, conn, "select * from test", 3) - testFetch(t, conn2, "select * from test", 2) - - testDML(t, conn, "set autocommit=1", 0, 0) - testDML(t, conn, "rollback", 1, 0) - testFetch(t, conn, "select * from test", 2) - testFetch(t, conn2, "select * from test", 2) - - // Basic autocommit test - testDML(t, conn, "insert into test (id, val) values(3, 'hello')", 3, 1) - testFetch(t, conn, "select * from test", 3) - testFetch(t, conn2, "select * from test", 3) - - // Cleanup - testDML(t, conn2, "begin", 1, 0) - testDML(t, conn2, "delete from test", 2, 3) - testDML(t, conn2, "commit", 1, 0) - - testFetch(t, conn, "select * from test", 0) - testFetch(t, conn2, "select * from test", 0) - -} - -func TestErrorDoesntDropTransaction(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testDML(t, conn, "begin", 1, 0) - testDML(t, conn, "insert into test (id, val) values(1, 'hello')", 1, 1) - _, err = conn.ExecuteFetch("select this is garbage", 1, false) - if err == nil { - t.Log("Expected error for garbage sql request") - t.FailNow() - } - // First connection should still see its data. - testFetch(t, conn, "select * from test", 1) - // But second won't, since it's uncommitted. - testFetch(t, conn2, "select * from test", 0) - - // Commit works still. - testDML(t, conn, "commit", 1, 0) - testFetch(t, conn, "select * from test", 1) - testFetch(t, conn2, "select * from test", 1) - - // Cleanup - testDML(t, conn2, "begin", 1, 0) - testDML(t, conn2, "delete from test", 2, 1) - testDML(t, conn2, "commit", 1, 0) -} - -func TestOther(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - testFetch(t, conn, "explain select * from test", 1) - testFetch(t, conn, "select table_name, table_rows from information_schema.tables where table_name='test'", 1) -} - -func TestQueryDeadline(t *testing.T) { - ctx := context.Background() - conn, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - // First run a query that is killed by the slow query killer after 2s - _, err = conn.ExecuteFetch("select sleep(5) from dual", 1000, false) - wantErr := "EOF (errno 2013) (sqlstate HY000) (CallerID: userData1): Sql: \"select sleep(:vtp1) from dual\", " + - "BindVars: {#maxLimit: \"type:INT64 value:\\\"10001\\\" \"vtp1: \"type:INT64 value:\\\"5\\\" \"} " + - "(errno 2013) (sqlstate HY000) during query: select sleep(5) from dual" - if err == nil || err.Error() != wantErr { - t.Errorf("error want '%v', got '%v'", wantErr, err) - } - - sqlErr, ok := err.(*mysql.SQLError) - if !ok { - t.Fatalf("Unexpected error type: %T, want %T", err, &mysql.SQLError{}) - } - if got, want := sqlErr.Number(), mysql.CRServerLost; got != want { - t.Errorf("Unexpected error code: %d, want %d", got, want) - } - - conn, err = mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - conn2, err := mysql.Connect(ctx, &proxyConnParams) - if err != nil { - t.Fatal(err) - } - - // Now send another query to tie up the connection, followed up by - // a query that should fail due to not getting the conn from the - // conn pool - err = conn.WriteComQuery("select sleep(1.75) from dual") - if err != nil { - t.Errorf("unexpected error sending query: %v", err) - } - time.Sleep(200 * time.Millisecond) - - _, err = conn2.ExecuteFetch("select 1 from dual", 1000, false) - wantErr = "query pool wait time exceeded" - if err == nil || !strings.Contains(err.Error(), wantErr) { - t.Errorf("want error %v, got %v", wantErr, err) - } - sqlErr, ok = err.(*mysql.SQLError) - if !ok { - t.Fatalf("Unexpected error type: %T, want %T", err, &mysql.SQLError{}) - } - if got, want := sqlErr.Number(), mysql.ERTooManyUserConnections; got != want { - t.Errorf("Unexpected error code: %d, want %d", got, want) - } - - _, _, _, err = conn.ReadQueryResult(1000, false) - if err != nil { - t.Errorf("unexpected error %v", err) - } - -} diff --git a/go/vt/vtqueryserver/plugin_mysql_server.go b/go/vt/vtqueryserver/plugin_mysql_server.go deleted file mode 100644 index 189eddbe6fa..00000000000 --- a/go/vt/vtqueryserver/plugin_mysql_server.go +++ /dev/null @@ -1,277 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vtqueryserver - -import ( - "flag" - "fmt" - "net" - "os" - "syscall" - - "golang.org/x/net/context" - - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/callerid" - "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/mysqlproxy" - "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/vttls" - - querypb "vitess.io/vitess/go/vt/proto/query" -) - -var ( - mysqlServerPort = flag.Int("mysqlproxy_server_port", -1, "If set, also listen for MySQL binary protocol connections on this port.") - mysqlServerBindAddress = flag.String("mysqlproxy_server_bind_address", "", "Binds on this address when listening to MySQL binary protocol. Useful to restrict listening to 'localhost' only for instance.") - mysqlServerSocketPath = flag.String("mysqlproxy_server_socket_path", "", "This option specifies the Unix socket file to use when listening for local connections. By default it will be empty and it won't listen to a unix socket") - mysqlAuthServerImpl = flag.String("mysql_auth_server_impl", "static", "Which auth server implementation to use.") - mysqlAllowClearTextWithoutTLS = flag.Bool("mysql_allow_clear_text_without_tls", false, "If set, the server will allow the use of a clear text password over non-SSL connections.") - - mysqlSslCert = flag.String("mysqlproxy_server_ssl_cert", "", "Path to the ssl cert for mysql server plugin SSL") - mysqlSslKey = flag.String("mysqlproxy_server_ssl_key", "", "Path to ssl key for mysql server plugin SSL") - mysqlSslCa = flag.String("mysqlproxy_server_ssl_ca", "", "Path to ssl CA for mysql server plugin SSL. If specified, server will require and validate client certs.") - - mysqlSlowConnectWarnThreshold = flag.Duration("mysqlproxy_slow_connect_warn_threshold", 0, "Warn if it takes more than the given threshold for a mysql connection to establish") - - mysqlConnReadTimeout = flag.Duration("mysql_server_read_timeout", 0, "connection read timeout") - mysqlConnWriteTimeout = flag.Duration("mysql_server_write_timeout", 0, "connection write timeout") - mysqlQueryTimeout = flag.Duration("mysql_server_query_timeout", 0, "mysql query timeout") -) - -// proxyHandler implements the Listener interface. -// It stores the Session in the ClientData of a Connection, if a transaction -// is in progress. -type proxyHandler struct { - mp *mysqlproxy.Proxy -} - -func newProxyHandler(mp *mysqlproxy.Proxy) *proxyHandler { - return &proxyHandler{ - mp: mp, - } -} - -func (mh *proxyHandler) NewConnection(c *mysql.Conn) { -} - -func (mh *proxyHandler) ConnectionClosed(c *mysql.Conn) { - // Rollback if there is an ongoing transaction. Ignore error. - var ctx context.Context - var cancel context.CancelFunc - if *mysqlQueryTimeout != 0 { - ctx, cancel = context.WithTimeout(context.Background(), *mysqlQueryTimeout) - defer cancel() - } else { - ctx = context.Background() - } - session, _ := c.ClientData.(*mysqlproxy.ProxySession) - if session != nil && session.TransactionID != 0 { - _ = mh.mp.Rollback(ctx, session) - } -} - -func (mh *proxyHandler) ComInitDB(c *mysql.Conn, schemaName string) { - mh.session(c).TargetString = schemaName -} - -func (mh *proxyHandler) ComQuery(c *mysql.Conn, query string, callback func(*sqltypes.Result) error) error { - var ctx context.Context - var cancel context.CancelFunc - if *mysqlQueryTimeout != 0 { - ctx, cancel = context.WithTimeout(context.Background(), *mysqlQueryTimeout) - defer cancel() - } else { - ctx = context.Background() - } - // Fill in the ImmediateCallerID with the UserData returned by - // the AuthServer plugin for that user. If nothing was - // returned, use the User. This lets the plugin map a MySQL - // user used for authentication to a Vitess User used for - // Table ACLs and Vitess authentication in general. - im := c.UserData.Get() - ef := callerid.NewEffectiveCallerID( - c.User, /* principal: who */ - c.RemoteAddr().String(), /* component: running client process */ - "mysqlproxy MySQL Connector" /* subcomponent: part of the client */) - ctx = callerid.NewContext(ctx, ef, im) - - session := mh.session(c) - session, result, err := mh.mp.Execute(ctx, session, query, make(map[string]*querypb.BindVariable)) - err = mysql.NewSQLErrorFromError(err) - if err != nil { - return err - } - - return callback(result) -} - -func (mh *proxyHandler) WarningCount(c *mysql.Conn) uint16 { - return 0 -} - -func (mh *proxyHandler) ComPrepare(c *mysql.Conn, query string) ([]*querypb.Field, error) { - return nil, nil -} - -func (mh *proxyHandler) ComStmtExecute(c *mysql.Conn, prepare *mysql.PrepareData, callback func(*sqltypes.Result) error) error { - return nil -} - -func (mh *proxyHandler) ComResetConnection(c *mysql.Conn) { -} - -func (mh *proxyHandler) session(c *mysql.Conn) *mysqlproxy.ProxySession { - session, _ := c.ClientData.(*mysqlproxy.ProxySession) - if session == nil { - session = &mysqlproxy.ProxySession{ - Options: &querypb.ExecuteOptions{ - IncludedFields: querypb.ExecuteOptions_ALL, - }, - Autocommit: true, - } - if c.Capabilities&mysql.CapabilityClientFoundRows != 0 { - session.Options.ClientFoundRows = true - } - c.ClientData = session - } - return session -} - -var mysqlListener *mysql.Listener -var mysqlUnixListener *mysql.Listener - -// initiMySQLProtocol starts the mysql protocol. -// It should be called only once in a process. -func initMySQLProtocol() { - log.Infof("initializing mysql protocol") - - // Flag is not set, just return. - if *mysqlServerPort < 0 && *mysqlServerSocketPath == "" { - return - } - - // If no mysqlproxy was created, just return. - if mysqlProxy == nil { - log.Fatalf("mysqlProxy not initialized") - return - } - - // Initialize registered AuthServer implementations (or other plugins) - for _, initFn := range pluginInitializers { - initFn() - } - authServer := mysql.GetAuthServer(*mysqlAuthServerImpl) - - // Create a Listener. - var err error - mh := newProxyHandler(mysqlProxy) - if *mysqlServerPort >= 0 { - mysqlListener, err = mysql.NewListener("tcp", net.JoinHostPort(*mysqlServerBindAddress, fmt.Sprintf("%v", *mysqlServerPort)), authServer, mh, *mysqlConnReadTimeout, *mysqlConnWriteTimeout) - if err != nil { - log.Exitf("mysql.NewListener failed: %v", err) - } - if *mysqlSslCert != "" && *mysqlSslKey != "" { - mysqlListener.TLSConfig, err = vttls.ServerConfig(*mysqlSslCert, *mysqlSslKey, *mysqlSslCa) - if err != nil { - log.Exitf("grpcutils.TLSServerConfig failed: %v", err) - return - } - } - mysqlListener.AllowClearTextWithoutTLS = *mysqlAllowClearTextWithoutTLS - - // Check for the connection threshold - if *mysqlSlowConnectWarnThreshold != 0 { - log.Infof("setting mysql slow connection threshold to %v", mysqlSlowConnectWarnThreshold) - mysqlListener.SlowConnectWarnThreshold = *mysqlSlowConnectWarnThreshold - } - // Start listening for tcp - go mysqlListener.Accept() - log.Infof("listening on %s:%d", *mysqlServerBindAddress, *mysqlServerPort) - } - - if *mysqlServerSocketPath != "" { - // Let's create this unix socket with permissions to all users. In this way, - // clients can connect to mysqlproxy mysql server without being mysqlproxy user - oldMask := syscall.Umask(000) - mysqlUnixListener, err = newMysqlUnixSocket(*mysqlServerSocketPath, authServer, mh) - _ = syscall.Umask(oldMask) - if err != nil { - log.Exitf("mysql.NewListener failed: %v", err) - return - } - // Listen for unix socket - go mysqlUnixListener.Accept() - } -} - -// newMysqlUnixSocket creates a new unix socket mysql listener. If a socket file already exists, attempts -// to clean it up. -func newMysqlUnixSocket(address string, authServer mysql.AuthServer, handler mysql.Handler) (*mysql.Listener, error) { - listener, err := mysql.NewListener("unix", address, authServer, handler, *mysqlConnReadTimeout, *mysqlConnWriteTimeout) - switch err := err.(type) { - case nil: - return listener, nil - case *net.OpError: - log.Warningf("Found existent socket when trying to create new unix mysql listener: %s, attempting to clean up", address) - // err.Op should never be different from listen, just being extra careful - // in case in the future other errors are returned here - if err.Op != "listen" { - return nil, err - } - _, dialErr := net.Dial("unix", address) - if dialErr == nil { - log.Errorf("Existent socket '%s' is still accepting connections, aborting", address) - return nil, err - } - removeFileErr := os.Remove(address) - if removeFileErr != nil { - log.Errorf("Couldn't remove existent socket file: %s", address) - return nil, err - } - listener, listenerErr := mysql.NewListener("unix", address, authServer, handler, *mysqlConnReadTimeout, *mysqlConnWriteTimeout) - return listener, listenerErr - default: - return nil, err - } -} - -func shutdownMySQLProtocol() { - log.Infof("shutting down mysql protocol") - if mysqlListener != nil { - mysqlListener.Close() - mysqlListener = nil - } - - if mysqlUnixListener != nil { - mysqlUnixListener.Close() - mysqlUnixListener = nil - } -} - -func init() { - servenv.OnRun(initMySQLProtocol) - servenv.OnTerm(shutdownMySQLProtocol) -} - -var pluginInitializers []func() - -// RegisterPluginInitializer lets plugins register themselves to be init'ed at servenv.OnRun-time -func RegisterPluginInitializer(initializer func()) { - pluginInitializers = append(pluginInitializers, initializer) -} diff --git a/go/vt/vtqueryserver/plugin_mysql_server_test.go b/go/vt/vtqueryserver/plugin_mysql_server_test.go deleted file mode 100644 index 646eac5687c..00000000000 --- a/go/vt/vtqueryserver/plugin_mysql_server_test.go +++ /dev/null @@ -1,177 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vtqueryserver - -import ( - "io/ioutil" - "os" - "strings" - "testing" - - "golang.org/x/net/context" - - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/sqltypes" - querypb "vitess.io/vitess/go/vt/proto/query" -) - -type testHandler struct { - lastConn *mysql.Conn -} - -func (th *testHandler) NewConnection(c *mysql.Conn) { - th.lastConn = c -} - -func (th *testHandler) ConnectionClosed(c *mysql.Conn) { -} - -func (th *testHandler) ComInitDB(c *mysql.Conn, schemaName string) { -} - -func (th *testHandler) ComQuery(c *mysql.Conn, q string, callback func(*sqltypes.Result) error) error { - return nil -} - -func (th *testHandler) ComPrepare(c *mysql.Conn, q string) ([]*querypb.Field, error) { - return nil, nil -} - -func (th *testHandler) ComStmtExecute(c *mysql.Conn, prepare *mysql.PrepareData, callback func(*sqltypes.Result) error) error { - return nil -} - -func (th *testHandler) ComResetConnection(c *mysql.Conn) { - -} - -func (th *testHandler) WarningCount(c *mysql.Conn) uint16 { - return 0 -} - -func TestConnectionUnixSocket(t *testing.T) { - th := &testHandler{} - - authServer := mysql.NewAuthServerStatic() - - authServer.Entries["user1"] = []*mysql.AuthServerStaticEntry{ - { - Password: "password1", - UserData: "userData1", - SourceHost: "localhost", - }, - } - - // Use tmp file to reserve a path, remove it immediately, we only care about - // name in this context - unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock") - if err != nil { - t.Fatalf("Failed to create temp file") - } - os.Remove(unixSocket.Name()) - - l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th) - if err != nil { - t.Fatalf("NewUnixSocket failed: %v", err) - } - defer l.Close() - go l.Accept() - - params := &mysql.ConnParams{ - UnixSocket: unixSocket.Name(), - Uname: "user1", - Pass: "password1", - } - - c, err := mysql.Connect(context.Background(), params) - if err != nil { - t.Errorf("Should be able to connect to server but found error: %v", err) - } - c.Close() -} - -func TestConnectionStaleUnixSocket(t *testing.T) { - th := &testHandler{} - - authServer := mysql.NewAuthServerStatic() - - authServer.Entries["user1"] = []*mysql.AuthServerStaticEntry{ - { - Password: "password1", - UserData: "userData1", - SourceHost: "localhost", - }, - } - - // First let's create a file. In this way, we simulate - // having a stale socket on disk that needs to be cleaned up. - unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock") - if err != nil { - t.Fatalf("Failed to create temp file") - } - - l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th) - if err != nil { - t.Fatalf("NewListener failed: %v", err) - } - defer l.Close() - go l.Accept() - - params := &mysql.ConnParams{ - UnixSocket: unixSocket.Name(), - Uname: "user1", - Pass: "password1", - } - - c, err := mysql.Connect(context.Background(), params) - if err != nil { - t.Errorf("Should be able to connect to server but found error: %v", err) - } - c.Close() -} - -func TestConnectionRespectsExistingUnixSocket(t *testing.T) { - th := &testHandler{} - - authServer := mysql.NewAuthServerStatic() - - authServer.Entries["user1"] = []*mysql.AuthServerStaticEntry{ - { - Password: "password1", - UserData: "userData1", - SourceHost: "localhost", - }, - } - - unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock") - if err != nil { - t.Fatalf("Failed to create temp file") - } - os.Remove(unixSocket.Name()) - - l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th) - if err != nil { - t.Errorf("NewListener failed: %v", err) - } - defer l.Close() - go l.Accept() - _, err = newMysqlUnixSocket(unixSocket.Name(), authServer, th) - want := "listen unix" - if err == nil || !strings.HasPrefix(err.Error(), want) { - t.Errorf("Error: %v, want prefix %s", err, want) - } -} diff --git a/go/vt/vtqueryserver/status.go b/go/vt/vtqueryserver/status.go deleted file mode 100644 index 42db438f351..00000000000 --- a/go/vt/vtqueryserver/status.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package vtqueryserver - -import ( - "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/vttablet/tabletserver" -) - -var ( - // proxyTemplate contains the style sheet and the tablet itself. - proxyTemplate = ` - -
- Target Keyspace: {{.Target.Keyspace}} - |
- - Schema - Schema Query Plans - Schema Query Stats - Schema Table Stats - | -- Query Stats - Streaming Query Stats - Consolidations - Current Query Log - Current Transaction Log - In-flight 2PC Transactions - | -- Query Service Health Check - Current Stream Queries - | -