Skip to content
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
10 changes: 10 additions & 0 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,16 @@ type Config struct {
// MockHeadlessLogin is used in tests for mocking the Headless login response.
MockHeadlessLogin SSHLoginFunc

// OverrideMySQLOptionFilePath overrides the MySQL option file path to use.
// Useful in parallel tests so they don't all use the default path in the
// user home dir.
OverrideMySQLOptionFilePath string

// OverridePostgresServiceFilePath overrides the Postgres service file path.
// Useful in parallel tests so they don't all use the default path in the
// user home dir.
OverridePostgresServiceFilePath string

// HomePath is where tsh stores profiles
HomePath string

Expand Down
11 changes: 10 additions & 1 deletion lib/client/db/dbcmd/dbcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func (c *CLICommandBuilder) getMySQLOracleCommand() (*exec.Cmd, error) {
// We save configuration to ~/.my.cnf, but on Windows that file is not read,
// see tables 4.1 and 4.2 on https://dev.mysql.com/doc/refman/8.0/en/option-files.html.
// We instruct mysql client to use use that file with --defaults-extra-file.
configPath, err := mysql.DefaultConfigPath(c.tc.HomePath)
configPath, err := c.getMySQLOptionFilePath()
if err != nil {
return nil, trace.Wrap(err)
}
Expand All @@ -346,6 +346,15 @@ func (c *CLICommandBuilder) getMySQLOracleCommand() (*exec.Cmd, error) {
return exec.Command(mysqlBin, args...), nil
}

// getMySQLOptionFilePath gets the filepath to .my.cnf from the default location
// in ~/.my.cnf, unless overridden by config.
func (c *CLICommandBuilder) getMySQLOptionFilePath() (string, error) {
if c.tc.OverrideMySQLOptionFilePath != "" {
return c.tc.OverrideMySQLOptionFilePath, nil
}
return mysql.DefaultConfigPath()
}

// getMySQLCommand returns mariadb command if the binary is on the path. Otherwise,
// mysql command is returned. Both mysql versions (MariaDB and Oracle) are supported.
func (c *CLICommandBuilder) getMySQLCommand() (*exec.Cmd, error) {
Expand Down
9 changes: 3 additions & 6 deletions lib/client/db/mysql/optionfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ type OptionFile struct {
// DefaultConfigPath returns the default config path, which is .my.cnf file in
// the user's home directory. Home dir is determined by environment if not
// supplied as an argument.
func DefaultConfigPath(home string) (string, error) {
if home != "" {
return filepath.Join(home, mysqlOptionFile), nil
}
func DefaultConfigPath() (string, error) {
home, err := os.UserHomeDir()
if err != nil || home == "" {
usr, err := utils.CurrentUser()
Expand All @@ -63,8 +60,8 @@ func DefaultConfigPath(home string) (string, error) {
}

// Load loads MySQL option file from the default location.
func Load(home string) (*OptionFile, error) {
cnfPath, err := DefaultConfigPath(home)
func Load() (*OptionFile, error) {
cnfPath, err := DefaultConfigPath()
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
12 changes: 4 additions & 8 deletions lib/client/db/postgres/servicefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,10 @@ type ServiceFile struct {
}

// DefaultConfigPath returns the default config path, which is .pg_service.conf
// file in the user's home directory. Home dir is determined by environment if
// not supplied as an argument.
func defaultConfigPath(home string) (string, error) {
// file in the user's home directory.
func defaultConfigPath() (string, error) {
// Default location is .pg_service.conf file in the user's home directory.
// TODO(r0mant): Check PGSERVICEFILE and PGSYSCONFDIR env vars as well.
if home != "" {
return filepath.Join(home, pgServiceFile), nil
}
home, err := os.UserHomeDir()
if err != nil || home == "" {
usr, err := utils.CurrentUser()
Expand All @@ -65,8 +61,8 @@ func defaultConfigPath(home string) (string, error) {
}

// Load loads Postgres connection service file from the default location.
func Load(home string) (*ServiceFile, error) {
cnfPath, err := defaultConfigPath(home)
func Load() (*ServiceFile, error) {
cnfPath, err := defaultConfigPath()
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
10 changes: 8 additions & 2 deletions lib/client/db/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,15 @@ func IsSupported(db tlsca.RouteToDatabase) bool {
func load(tc *client.TeleportClient, db tlsca.RouteToDatabase) (profile.ConnectProfileFile, error) {
switch db.Protocol {
case defaults.ProtocolPostgres:
return postgres.Load(tc.HomePath)
if tc.OverridePostgresServiceFilePath != "" {
return postgres.LoadFromPath(tc.OverridePostgresServiceFilePath)
}
return postgres.Load()
case defaults.ProtocolMySQL:
return mysql.Load(tc.HomePath)
if tc.OverrideMySQLOptionFilePath != "" {
return mysql.LoadFromPath(tc.OverrideMySQLOptionFilePath)
}
return mysql.Load()
}
return nil, trace.BadParameter("unsupported database protocol %q",
db.Protocol)
Expand Down
20 changes: 16 additions & 4 deletions tool/tsh/common/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,23 @@ func testDatabaseLogin(t *testing.T) {
if len(selectors) == 0 {
selectors = []string{test.databaseName}
}

// override the mysql/postgres config file paths to avoid parallel
// updates to the default location in the user home dir.
mySqlCnfPath := filepath.Join(tmpHomePath, ".my.cnf")
pgCnfPath := filepath.Join(tmpHomePath, ".pg_service.conf")
// all subsequent tsh commands need these options.
cliOpts := []CliOption{
// set .tsh location to the temp dir for this test.
setHomePath(tmpHomePath),
setOverrideMySQLConfigPath(mySqlCnfPath),
setOverridePostgresConfigPath(pgCnfPath),
}
args := append([]string{
// default --db-user and --db-name are selected from roles.
"db", "login",
}, selectors...)
err := Run(context.Background(), args, setHomePath(tmpHomePath))
err := Run(context.Background(), args, cliOpts...)
require.NoError(t, err)

// Fetch the active profile.
Expand All @@ -270,7 +282,7 @@ func testDatabaseLogin(t *testing.T) {
args := append([]string{
"db", "config",
}, selectors...)
err := Run(context.Background(), args, setHomePath(tmpHomePath))
err := Run(context.Background(), args, cliOpts...)

if test.expectErrForConfigCmd {
require.Error(t, err)
Expand All @@ -284,7 +296,7 @@ func testDatabaseLogin(t *testing.T) {
args := append([]string{
"db", "env",
}, selectors...)
err := Run(context.Background(), args, setHomePath(tmpHomePath))
err := Run(context.Background(), args, cliOpts...)

if test.expectErrForEnvCmd {
require.Error(t, err)
Expand All @@ -299,7 +311,7 @@ func testDatabaseLogin(t *testing.T) {
args := append([]string{
"db", "logout",
}, selectors...)
err := Run(context.Background(), args, setHomePath(tmpHomePath))
err := Run(context.Background(), args, cliOpts...)
require.NoError(t, err)
})
})
Expand Down
14 changes: 14 additions & 0 deletions tool/tsh/common/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,16 @@ type CLIConf struct {
// MockHeadlessLogin used in tests to override Headless login handler in teleport client.
MockHeadlessLogin client.SSHLoginFunc

// overrideMySQLOptionFilePath overrides the MySQL option file path to use.
// Useful in parallel tests so they don't all use the default path in the
// user home dir.
overrideMySQLOptionFilePath string

// overridePostgresServiceFilePath overrides the Postgres service file path.
// Useful in parallel tests so they don't all use the default path in the
// user home dir.
overridePostgresServiceFilePath string

// HomePath is where tsh stores profiles
HomePath string

Expand Down Expand Up @@ -3701,6 +3711,10 @@ func loadClientConfigFromCLIConf(cf *CLIConf, proxy string) (*client.Config, err
c.MockHeadlessLogin = cf.MockHeadlessLogin
c.DTAuthnRunCeremony = cf.DTAuthnRunCeremony

// pass along MySQL/Postgres path overrides (only used in tests).
c.OverrideMySQLOptionFilePath = cf.overrideMySQLOptionFilePath
c.OverridePostgresServiceFilePath = cf.overridePostgresServiceFilePath

// Set tsh home directory
c.HomePath = cf.HomePath

Expand Down
14 changes: 14 additions & 0 deletions tool/tsh/common/tsh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3367,6 +3367,20 @@ func setHomePath(path string) CliOption {
}
}

func setOverrideMySQLConfigPath(path string) CliOption {
return func(cf *CLIConf) error {
cf.overrideMySQLOptionFilePath = path
return nil
}
}

func setOverridePostgresConfigPath(path string) CliOption {
return func(cf *CLIConf) error {
cf.overridePostgresServiceFilePath = path
return nil
}
}

func setKubeConfigPath(path string) CliOption {
return func(cf *CLIConf) error {
cf.KubeConfigPath = path
Expand Down