Skip to content

Commit 69604ed

Browse files
authored
Add initialize_with_vt_dba_tcp flag to enable TCP/IP connection access to the underlying MySQL instance (#15354)
Signed-off-by: Yohei Yoshimuta <yoheimuta@gmail.com>
1 parent aba0d83 commit 69604ed

File tree

5 files changed

+89
-23
lines changed

5 files changed

+89
-23
lines changed

go/cmd/vttestserver/cli/main.go

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"os"
2424
"os/signal"
25+
"path"
2526
"strconv"
2627
"strings"
2728
"syscall"
@@ -47,13 +48,14 @@ type topoFlags struct {
4748
}
4849

4950
var (
50-
basePort int
51-
config vttest.Config
52-
doSeed bool
53-
mycnf string
54-
protoTopo string
55-
seed vttest.SeedConfig
56-
topo topoFlags
51+
basePort int
52+
config vttest.Config
53+
doSeed bool
54+
mycnf string
55+
protoTopo string
56+
seed vttest.SeedConfig
57+
topo topoFlags
58+
doCreateTCPUser bool
5759
)
5860

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

222224
cmd.Flags().DurationVar(&config.VtgateTabletRefreshInterval, "tablet_refresh_interval", 10*time.Second, "Interval at which vtgate refreshes tablet information from topology server.")
225+
226+
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.")
223227
acl.RegisterFlags(cmd.Flags())
224228

225229
return cmd
226230
}
227231

228-
func newEnv() (env vttest.Environment, err error) {
229-
if basePort != 0 {
232+
func newEnv() (env *vttest.LocalTestEnv, err error) {
233+
if basePort == 0 {
234+
env, err = vttest.NewLocalTestEnv(0)
235+
} else {
230236
if config.DataDir == "" {
231237
env, err = vttest.NewLocalTestEnv(basePort)
232-
if err != nil {
233-
return
234-
}
235238
} else {
236239
env, err = vttest.NewLocalTestEnvWithDirectory(basePort, config.DataDir)
237-
if err != nil {
238-
return
239-
}
240240
}
241241
}
242+
if err != nil {
243+
return
244+
}
245+
246+
if doCreateTCPUser {
247+
// The original initFile does not have any users who can access through TCP/IP connection.
248+
// Here we update the init file to create the user.
249+
mysqlInitFile := env.InitDBFile
250+
createUserCmd := `
251+
# Admin user for TCP/IP connection with all privileges.
252+
CREATE USER 'vt_dba_tcp'@'%';
253+
GRANT ALL ON *.* TO 'vt_dba_tcp'@'%';
254+
GRANT GRANT OPTION ON *.* TO 'vt_dba_tcp'@'%';
255+
`
256+
newInitFile := path.Join(env.Directory(), "init_db_with_vt_dba_tcp.sql")
257+
err = vttest.WriteInitDBFile(mysqlInitFile, createUserCmd, newInitFile)
258+
if err != nil {
259+
return
260+
}
261+
env.InitDBFile = newInitFile
262+
}
242263

243264
if protoTopo == "" {
244265
config.Topology, err = topo.buildTopology()

go/cmd/vttestserver/cli/main_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,39 @@ func TestForeignKeysAndDDLModes(t *testing.T) {
186186
assert.NoError(t, err)
187187
}
188188

189+
// TestCreateDbaTCPUser tests that the vt_dba_tcp user is created and can connect through TCP/IP connection
190+
// when --initialize-with-vt-dba-tcp is set to true.
191+
func TestCreateDbaTCPUser(t *testing.T) {
192+
conf := config
193+
defer resetConfig(conf)
194+
195+
clusterInstance, err := startCluster("--initialize-with-vt-dba-tcp=true")
196+
assert.NoError(t, err)
197+
defer clusterInstance.TearDown()
198+
199+
defer func() {
200+
if t.Failed() {
201+
cluster.PrintFiles(t, clusterInstance.Env.Directory(), "init_db_with_vt_dba_tcp.sql")
202+
}
203+
}()
204+
205+
// Ensure that the vt_dba_tcp user was created and can connect through TCP/IP connection.
206+
ctx := context.Background()
207+
vtParams := mysql.ConnParams{
208+
Host: "127.0.0.1",
209+
Uname: "vt_dba_tcp",
210+
Port: clusterInstance.Env.PortForProtocol("mysql", ""),
211+
}
212+
conn, err := mysql.Connect(ctx, &vtParams)
213+
assert.NoError(t, err)
214+
defer conn.Close()
215+
216+
// Ensure that the existing vt_dba user remains unaffected, meaning it cannot connect through TCP/IP connection.
217+
vtParams.Uname = "vt_dba"
218+
_, err = mysql.Connect(ctx, &vtParams)
219+
assert.Error(t, err)
220+
}
221+
189222
func TestCanGetKeyspaces(t *testing.T) {
190223
conf := config
191224
defer resetConfig(conf)

go/flags/endtoend/vttestserver.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Flags:
7272
--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)
7373
--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)
7474
-h, --help help for vttestserver
75+
--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.
7576
--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.
7677
--keep_logs duration keep logs for this long (using ctime) (zero to keep forever)
7778
--keep_logs_by_mtime duration keep logs for this long (using mtime) (zero to keep forever)

go/vt/vttest/environment.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ type LocalTestEnv struct {
9999
BasePort int
100100
TmpPath string
101101
DefaultMyCnf []string
102+
InitDBFile string
102103
Env []string
103104
EnableToxiproxy bool
104105
}
@@ -133,7 +134,7 @@ func (env *LocalTestEnv) BinaryPath(binary string) string {
133134
func (env *LocalTestEnv) MySQLManager(mycnf []string, snapshot string) (MySQLManager, error) {
134135
mysqlctl := &Mysqlctl{
135136
Binary: env.BinaryPath("mysqlctl"),
136-
InitFile: path.Join(os.Getenv("VTROOT"), "config/init_db.sql"),
137+
InitFile: env.InitDBFile,
137138
Directory: env.TmpPath,
138139
Port: env.PortForProtocol("mysql", ""),
139140
MyCnf: append(env.DefaultMyCnf, mycnf...),
@@ -281,6 +282,7 @@ func NewLocalTestEnvWithDirectory(basePort int, directory string) (*LocalTestEnv
281282
BasePort: basePort,
282283
TmpPath: directory,
283284
DefaultMyCnf: mycnf,
285+
InitDBFile: path.Join(os.Getenv("VTROOT"), "config/init_db.sql"),
284286
Env: []string{
285287
fmt.Sprintf("VTDATAROOT=%s", directory),
286288
"VTTEST=endtoend",

go/vt/vttest/toxiproxyctl.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,16 @@ func NewToxiproxyctl(binary string, apiPort, mysqlPort int, mysqlctl *Mysqlctl,
6363

6464
// The original initFile does not have any users who can access through TCP/IP connection.
6565
// Here we update the init file to create the user.
66-
initDb, _ := os.ReadFile(mysqlctl.InitFile)
6766
createUserCmd := fmt.Sprintf(`
6867
# Admin user for TCP/IP connection with all privileges.
6968
CREATE USER '%s'@'127.0.0.1';
7069
GRANT ALL ON *.* TO '%s'@'127.0.0.1';
7170
GRANT GRANT OPTION ON *.* TO '%s'@'127.0.0.1';
7271
`, dbaUser, dbaUser, dbaUser)
73-
sql, err := getInitDBSQL(string(initDb), createUserCmd)
74-
if err != nil {
75-
return nil, vterrors.Wrap(err, "failed to get a modified init db sql")
76-
}
7772
newInitFile := path.Join(mysqlctl.Directory, "init_db_toxiproxyctl.sql")
78-
err = os.WriteFile(newInitFile, []byte(sql), 0600)
73+
err := WriteInitDBFile(mysqlctl.InitFile, createUserCmd, newInitFile)
7974
if err != nil {
80-
return nil, vterrors.Wrap(err, "failed to write a modified init db file")
75+
return nil, vterrors.Wrap(err, "failed to get a modified init db sql")
8176
}
8277
mysqlctl.InitFile = newInitFile
8378

@@ -235,6 +230,20 @@ func (ctl *Toxiproxyctl) RemoveTimeoutToxic() error {
235230
return ctl.proxy.RemoveToxic("my-timeout")
236231
}
237232

233+
// WriteInitDBFile is a helper function that writes a modified init_db.sql file with custom SQL statements.
234+
func WriteInitDBFile(initFile, customSQL, newInitFile string) error {
235+
initDb, _ := os.ReadFile(initFile)
236+
sql, err := getInitDBSQL(string(initDb), customSQL)
237+
if err != nil {
238+
return vterrors.Wrap(err, "failed to get a modified init db sql")
239+
}
240+
err = os.WriteFile(newInitFile, []byte(sql), 0600)
241+
if err != nil {
242+
return vterrors.Wrap(err, "failed to write a modified init db file")
243+
}
244+
return nil
245+
}
246+
238247
// getInitDBSQL is a helper function that retrieves the modified contents of the init_db.sql file with custom SQL statements.
239248
// We avoid using vitess.io/vitess/go/test/endtoend/utils.GetInitDBSQL as importing this package adds unnecessary flags to vttestserver.
240249
func getInitDBSQL(initDBSQL string, customSQL string) (string, error) {

0 commit comments

Comments
 (0)