vitess.io/vitess@v0.16.2/go/test/endtoend/vtgate/keyspace_watches/keyspace_watch_test.go (about)

     1  /*
     2  Copyright 2021 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  Test the vtgate's ability to route while watching a subset of keyspaces.
    19  */
    20  
    21  package keyspacewatches
    22  
    23  import (
    24  	"database/sql"
    25  	"fmt"
    26  	"math/rand"
    27  	"os"
    28  	"testing"
    29  	"time"
    30  
    31  	_ "github.com/go-sql-driver/mysql"
    32  	"github.com/stretchr/testify/require"
    33  
    34  	"vitess.io/vitess/go/mysql"
    35  	"vitess.io/vitess/go/test/endtoend/cluster"
    36  )
    37  
    38  var (
    39  	vtParams              mysql.ConnParams
    40  	keyspaceUnshardedName = "ks1"
    41  	cell                  = "zone1"
    42  	hostname              = "localhost"
    43  	mysqlAuthServerStatic = "mysql_auth_server_static.json"
    44  	sqlSchema             = `
    45  	create table keyspaces_to_watch_test(
    46  		id BIGINT NOT NULL,
    47  		msg VARCHAR(64) NOT NULL,
    48  		PRIMARY KEY (id)
    49  	) Engine=InnoDB;`
    50  	vschemaDDL      = "alter vschema create vindex test_vdx using hash"
    51  	vschemaDDLError = fmt.Sprintf("Error 1105 (HY000): cannot perform Update on keyspaces/%s/VSchema as the topology server connection is read-only",
    52  		keyspaceUnshardedName)
    53  )
    54  
    55  // createConfig creates a config file in TmpDir in vtdataroot and writes the given data.
    56  func createConfig(clusterInstance *cluster.LocalProcessCluster, name, data string) error {
    57  	// creating new file
    58  	f, err := os.Create(clusterInstance.TmpDirectory + "/" + name)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	if data == "" {
    64  		return nil
    65  	}
    66  
    67  	// write the given data
    68  	_, err = fmt.Fprint(f, data)
    69  	return err
    70  }
    71  
    72  func createCluster(extraVTGateArgs []string) (*cluster.LocalProcessCluster, int) {
    73  	clusterInstance := cluster.NewCluster(cell, hostname)
    74  
    75  	// Start topo server
    76  	if err := clusterInstance.StartTopo(); err != nil {
    77  		return nil, 1
    78  	}
    79  
    80  	// create auth server config
    81  	SQLConfig := `{
    82  		"testuser1": {
    83  			"Password": "testpassword1",
    84  			"UserData": "vtgate client 1"
    85  		}
    86  	}`
    87  	if err := createConfig(clusterInstance, mysqlAuthServerStatic, SQLConfig); err != nil {
    88  		return nil, 1
    89  	}
    90  
    91  	// Start keyspace
    92  	keyspace := &cluster.Keyspace{
    93  		Name:      keyspaceUnshardedName,
    94  		SchemaSQL: sqlSchema,
    95  	}
    96  	if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil {
    97  		return nil, 1
    98  	}
    99  
   100  	vtGateArgs := []string{
   101  		"--mysql_auth_server_static_file", clusterInstance.TmpDirectory + "/" + mysqlAuthServerStatic,
   102  		"--keyspaces_to_watch", keyspaceUnshardedName,
   103  	}
   104  
   105  	if extraVTGateArgs != nil {
   106  		vtGateArgs = append(vtGateArgs, extraVTGateArgs...)
   107  	}
   108  	clusterInstance.VtGateExtraArgs = vtGateArgs
   109  
   110  	// Start vtgate
   111  	if err := clusterInstance.StartVtgate(); err != nil {
   112  		return nil, 1
   113  	}
   114  	vtParams = mysql.ConnParams{
   115  		Host: clusterInstance.Hostname,
   116  		Port: clusterInstance.VtgateMySQLPort,
   117  	}
   118  	rand.Seed(time.Now().UnixNano())
   119  	return clusterInstance, 0
   120  }
   121  
   122  func TestRoutingWithKeyspacesToWatch(t *testing.T) {
   123  	defer cluster.PanicHandler(t)
   124  
   125  	clusterInstance, exitCode := createCluster(nil)
   126  	defer clusterInstance.Teardown()
   127  
   128  	if exitCode != 0 {
   129  		os.Exit(exitCode)
   130  	}
   131  
   132  	dsn := fmt.Sprintf(
   133  		"testuser1:testpassword1@tcp(%s:%v)/",
   134  		clusterInstance.Hostname,
   135  		clusterInstance.VtgateMySQLPort,
   136  	)
   137  	db, err := sql.Open("mysql", dsn)
   138  	require.Nil(t, err)
   139  	defer db.Close()
   140  
   141  	// if this returns w/o failing the test we're good to go
   142  	_, err = db.Exec("select * from keyspaces_to_watch_test")
   143  	require.Nil(t, err)
   144  }
   145  
   146  func TestVSchemaDDLWithKeyspacesToWatch(t *testing.T) {
   147  	defer cluster.PanicHandler(t)
   148  
   149  	extraVTGateArgs := []string{
   150  		"--vschema_ddl_authorized_users", "%",
   151  	}
   152  	clusterInstance, exitCode := createCluster(extraVTGateArgs)
   153  	defer clusterInstance.Teardown()
   154  
   155  	if exitCode != 0 {
   156  		os.Exit(exitCode)
   157  	}
   158  
   159  	dsn := fmt.Sprintf(
   160  		"testuser1:testpassword1@tcp(%s:%v)/",
   161  		clusterInstance.Hostname,
   162  		clusterInstance.VtgateMySQLPort,
   163  	)
   164  	db, err := sql.Open("mysql", dsn)
   165  	require.Nil(t, err)
   166  	defer db.Close()
   167  
   168  	// The topo server must be read-only when using keyspaces_to_watch in order to prevent
   169  	// potentially corrupting the VSchema based on this vtgates limited view of the world
   170  	_, err = db.Exec(vschemaDDL)
   171  	require.EqualError(t, err, vschemaDDLError)
   172  }