Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initialize-with-vt-dba-tcp flag to enable TCP/IP connection access to the underlying MySQL instance #15354

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions go/cmd/vttestserver/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"os/signal"
"path"
"strconv"
"strings"
"syscall"
Expand All @@ -47,13 +48,14 @@ type topoFlags struct {
}

var (
basePort int
config vttest.Config
doSeed bool
mycnf string
protoTopo string
seed vttest.SeedConfig
topo topoFlags
basePort int
config vttest.Config
doSeed bool
mycnf string
protoTopo string
seed vttest.SeedConfig
topo topoFlags
doCreateTCPUser bool
)

func (t *topoFlags) buildTopology() (*vttestpb.VTTestTopology, error) {
Expand Down Expand Up @@ -219,25 +221,44 @@ func New() (cmd *cobra.Command) {
cmd.Flags().StringVar(&config.ExternalTopoGlobalRoot, "external_topo_global_root", "", "the path of the global topology data in the global topology server for vtcombo process")

cmd.Flags().DurationVar(&config.VtgateTabletRefreshInterval, "tablet_refresh_interval", 10*time.Second, "Interval at which vtgate refreshes tablet information from topology server.")

cmd.Flags().BoolVar(&doCreateTCPUser, "initialize-with-vt-dba-tcp", false, "If this flag is enabled, MySQL will be initialized with an additional user named vt_dba_tcp, who will have access via TCP/IP connection.")
acl.RegisterFlags(cmd.Flags())

return cmd
}

func newEnv() (env vttest.Environment, err error) {
if basePort != 0 {
func newEnv() (env *vttest.LocalTestEnv, err error) {
if basePort == 0 {
env, err = vttest.NewLocalTestEnv(0)
} else {
if config.DataDir == "" {
env, err = vttest.NewLocalTestEnv(basePort)
if err != nil {
return
}
} else {
env, err = vttest.NewLocalTestEnvWithDirectory(basePort, config.DataDir)
if err != nil {
return
}
}
}
if err != nil {
return
}

if doCreateTCPUser {
// The original initFile does not have any users who can access through TCP/IP connection.
// Here we update the init file to create the user.
mysqlInitFile := env.InitDBFile
createUserCmd := `
# Admin user for TCP/IP connection with all privileges.
CREATE USER 'vt_dba_tcp'@'%';
GRANT ALL ON *.* TO 'vt_dba_tcp'@'%';
GRANT GRANT OPTION ON *.* TO 'vt_dba_tcp'@'%';
`
newInitFile := path.Join(env.Directory(), "init_db_with_vt_dba_tcp.sql")
err = vttest.WriteInitDBFile(mysqlInitFile, createUserCmd, newInitFile)
if err != nil {
return
}
env.InitDBFile = newInitFile
}

if protoTopo == "" {
config.Topology, err = topo.buildTopology()
Expand Down
33 changes: 33 additions & 0 deletions go/cmd/vttestserver/cli/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,39 @@ func TestForeignKeysAndDDLModes(t *testing.T) {
assert.NoError(t, err)
}

// TestCreateDbaTCPUser tests that the vt_dba_tcp user is created and can connect through TCP/IP connection
// when --initialize-with-vt-dba-tcp is set to true.
func TestCreateDbaTCPUser(t *testing.T) {
conf := config
defer resetConfig(conf)

clusterInstance, err := startCluster("--initialize-with-vt-dba-tcp=true")
assert.NoError(t, err)
defer clusterInstance.TearDown()

defer func() {
if t.Failed() {
cluster.PrintFiles(t, clusterInstance.Env.Directory(), "init_db_with_vt_dba_tcp.sql")
}
}()

// Ensure that the vt_dba_tcp user was created and can connect through TCP/IP connection.
ctx := context.Background()
vtParams := mysql.ConnParams{
Host: "127.0.0.1",
Uname: "vt_dba_tcp",
Port: clusterInstance.Env.PortForProtocol("mysql", ""),
}
conn, err := mysql.Connect(ctx, &vtParams)
assert.NoError(t, err)
defer conn.Close()

// Ensure that the existing vt_dba user remains unaffected, meaning it cannot connect through TCP/IP connection.
vtParams.Uname = "vt_dba"
_, err = mysql.Connect(ctx, &vtParams)
assert.Error(t, err)
}

func TestCanGetKeyspaces(t *testing.T) {
conf := config
defer resetConfig(conf)
Expand Down
1 change: 1 addition & 0 deletions go/flags/endtoend/vttestserver.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Flags:
--grpc_server_keepalive_time duration After a duration of this time, if the server doesn't see any activity, it pings the client to see if the transport is still alive. (default 10s)
--grpc_server_keepalive_timeout duration After having pinged for keepalive check, the server waits for a duration of Timeout and if no activity is seen even after that the connection is closed. (default 10s)
-h, --help help for vttestserver
--initialize-with-vt-dba-tcp If this flag is enabled, MySQL will be initialized with an additional user named vt_dba_tcp, who will have access via TCP/IP connection.
--initialize_with_random_data If this flag is each table-shard will be initialized with random data. See also the 'rng_seed' and 'min_shard_size' and 'max_shard_size' flags.
--keep_logs duration keep logs for this long (using ctime) (zero to keep forever)
--keep_logs_by_mtime duration keep logs for this long (using mtime) (zero to keep forever)
Expand Down
4 changes: 3 additions & 1 deletion go/vt/vttest/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type LocalTestEnv struct {
BasePort int
TmpPath string
DefaultMyCnf []string
InitDBFile string
Env []string
EnableToxiproxy bool
}
Expand Down Expand Up @@ -133,7 +134,7 @@ func (env *LocalTestEnv) BinaryPath(binary string) string {
func (env *LocalTestEnv) MySQLManager(mycnf []string, snapshot string) (MySQLManager, error) {
mysqlctl := &Mysqlctl{
Binary: env.BinaryPath("mysqlctl"),
InitFile: path.Join(os.Getenv("VTROOT"), "config/init_db.sql"),
InitFile: env.InitDBFile,
Directory: env.TmpPath,
Port: env.PortForProtocol("mysql", ""),
MyCnf: append(env.DefaultMyCnf, mycnf...),
Expand Down Expand Up @@ -281,6 +282,7 @@ func NewLocalTestEnvWithDirectory(basePort int, directory string) (*LocalTestEnv
BasePort: basePort,
TmpPath: directory,
DefaultMyCnf: mycnf,
InitDBFile: path.Join(os.Getenv("VTROOT"), "config/init_db.sql"),
Env: []string{
fmt.Sprintf("VTDATAROOT=%s", directory),
"VTTEST=endtoend",
Expand Down
23 changes: 16 additions & 7 deletions go/vt/vttest/toxiproxyctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,16 @@

// The original initFile does not have any users who can access through TCP/IP connection.
// Here we update the init file to create the user.
initDb, _ := os.ReadFile(mysqlctl.InitFile)
createUserCmd := fmt.Sprintf(`
# Admin user for TCP/IP connection with all privileges.
CREATE USER '%s'@'127.0.0.1';
GRANT ALL ON *.* TO '%s'@'127.0.0.1';
GRANT GRANT OPTION ON *.* TO '%s'@'127.0.0.1';
`, dbaUser, dbaUser, dbaUser)
sql, err := getInitDBSQL(string(initDb), createUserCmd)
if err != nil {
return nil, vterrors.Wrap(err, "failed to get a modified init db sql")
}
newInitFile := path.Join(mysqlctl.Directory, "init_db_toxiproxyctl.sql")
err = os.WriteFile(newInitFile, []byte(sql), 0600)
err := WriteInitDBFile(mysqlctl.InitFile, createUserCmd, newInitFile)

Check warning on line 73 in go/vt/vttest/toxiproxyctl.go

View check run for this annotation

Codecov / codecov/patch

go/vt/vttest/toxiproxyctl.go#L73

Added line #L73 was not covered by tests
if err != nil {
return nil, vterrors.Wrap(err, "failed to write a modified init db file")
return nil, vterrors.Wrap(err, "failed to get a modified init db sql")

Check warning on line 75 in go/vt/vttest/toxiproxyctl.go

View check run for this annotation

Codecov / codecov/patch

go/vt/vttest/toxiproxyctl.go#L75

Added line #L75 was not covered by tests
}
mysqlctl.InitFile = newInitFile

Expand Down Expand Up @@ -235,6 +230,20 @@
return ctl.proxy.RemoveToxic("my-timeout")
}

// WriteInitDBFile is a helper function that writes a modified init_db.sql file with custom SQL statements.
func WriteInitDBFile(initFile, customSQL, newInitFile string) error {
initDb, _ := os.ReadFile(initFile)
sql, err := getInitDBSQL(string(initDb), customSQL)
if err != nil {
return vterrors.Wrap(err, "failed to get a modified init db sql")

Check warning on line 238 in go/vt/vttest/toxiproxyctl.go

View check run for this annotation

Codecov / codecov/patch

go/vt/vttest/toxiproxyctl.go#L234-L238

Added lines #L234 - L238 were not covered by tests
}
err = os.WriteFile(newInitFile, []byte(sql), 0600)
if err != nil {
return vterrors.Wrap(err, "failed to write a modified init db file")

Check warning on line 242 in go/vt/vttest/toxiproxyctl.go

View check run for this annotation

Codecov / codecov/patch

go/vt/vttest/toxiproxyctl.go#L240-L242

Added lines #L240 - L242 were not covered by tests
}
return nil

Check warning on line 244 in go/vt/vttest/toxiproxyctl.go

View check run for this annotation

Codecov / codecov/patch

go/vt/vttest/toxiproxyctl.go#L244

Added line #L244 was not covered by tests
}

// getInitDBSQL is a helper function that retrieves the modified contents of the init_db.sql file with custom SQL statements.
// We avoid using vitess.io/vitess/go/test/endtoend/utils.GetInitDBSQL as importing this package adds unnecessary flags to vttestserver.
func getInitDBSQL(initDBSQL string, customSQL string) (string, error) {
Expand Down
Loading