Skip to content

Commit

Permalink
Merge pull request #8644 from milogreg/config-file-gen
Browse files Browse the repository at this point in the history
Generate config.yaml when running sql-server
  • Loading branch information
zachmu authored Jan 10, 2025
2 parents 0cbfe0e + 00815e5 commit 53a9c9a
Show file tree
Hide file tree
Showing 9 changed files with 850 additions and 76 deletions.
17 changes: 17 additions & 0 deletions go/cmd/dolt/commands/sqlserver/command_line_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,11 @@ func NewCommandLineConfig(creds *cli.UserPassword, apr *argparser.ArgParseResult
if creds == nil {
if user, ok := apr.GetValue(cli.UserFlag); ok {
config.withUser(user)
config.valuesSet[servercfg.UserKey] = struct{}{}
}
if password, ok := apr.GetValue(cli.PasswordFlag); ok {
config.withPassword(password)
config.valuesSet[servercfg.PasswordKey] = struct{}{}
}
} else {
config.withUser(creds.Username)
Expand Down Expand Up @@ -163,7 +165,14 @@ func NewCommandLineConfig(creds *cli.UserPassword, apr *argparser.ArgParseResult
}

config.autoCommit = !apr.Contains(noAutoCommitFlag)
if apr.Contains(noAutoCommitFlag) {
config.valuesSet[servercfg.AutoCommitKey] = struct{}{}
}

config.allowCleartextPasswords = apr.Contains(allowCleartextPasswordsFlag)
if apr.Contains(allowCleartextPasswordsFlag) {
config.valuesSet[servercfg.AllowCleartextPasswordsKey] = struct{}{}
}

if connStr, ok := apr.GetValue(goldenMysqlConn); ok {
cli.Println(connStr)
Expand Down Expand Up @@ -341,12 +350,14 @@ func (cfg *commandLineServerConfig) Socket() string {
// WithHost updates the host and returns the called `*commandLineServerConfig`, which is useful for chaining calls.
func (cfg *commandLineServerConfig) WithHost(host string) *commandLineServerConfig {
cfg.host = host
cfg.valuesSet[servercfg.HostKey] = struct{}{}
return cfg
}

// WithPort updates the port and returns the called `*commandLineServerConfig`, which is useful for chaining calls.
func (cfg *commandLineServerConfig) WithPort(port int) *commandLineServerConfig {
cfg.port = port
cfg.valuesSet[servercfg.PortKey] = struct{}{}
return cfg
}

Expand All @@ -373,12 +384,14 @@ func (cfg *commandLineServerConfig) withTimeout(timeout uint64) *commandLineServ
// withReadOnly updates the read only flag and returns the called `*commandLineServerConfig`, which is useful for chaining calls.
func (cfg *commandLineServerConfig) withReadOnly(readonly bool) *commandLineServerConfig {
cfg.readOnly = readonly
cfg.valuesSet[servercfg.ReadOnlyKey] = struct{}{}
return cfg
}

// withLogLevel updates the log level and returns the called `*commandLineServerConfig`, which is useful for chaining calls.
func (cfg *commandLineServerConfig) withLogLevel(loglevel servercfg.LogLevel) *commandLineServerConfig {
cfg.logLevel = loglevel
cfg.valuesSet[servercfg.LogLevelKey] = struct{}{}
return cfg
}

Expand Down Expand Up @@ -416,23 +429,27 @@ func (cfg *commandLineServerConfig) withBranchControlFilePath(branchControlFileP

func (cfg *commandLineServerConfig) withAllowCleartextPasswords(allow bool) *commandLineServerConfig {
cfg.allowCleartextPasswords = allow
cfg.valuesSet[servercfg.AllowCleartextPasswordsKey] = struct{}{}
return cfg
}

// WithSocket updates the path to the unix socket file
func (cfg *commandLineServerConfig) WithSocket(sockFilePath string) *commandLineServerConfig {
cfg.socket = sockFilePath
cfg.valuesSet[servercfg.SocketKey] = struct{}{}
return cfg
}

// WithRemotesapiPort sets the remotesapi port to use.
func (cfg *commandLineServerConfig) WithRemotesapiPort(port *int) *commandLineServerConfig {
cfg.remotesapiPort = port
cfg.valuesSet[servercfg.RemotesapiPortKey] = struct{}{}
return cfg
}

func (cfg *commandLineServerConfig) WithRemotesapiReadOnly(readonly *bool) *commandLineServerConfig {
cfg.remotesapiReadOnly = readonly
cfg.valuesSet[servercfg.RemotesapiReadOnlyKey] = struct{}{}
return cfg
}

Expand Down
113 changes: 113 additions & 0 deletions go/cmd/dolt/commands/sqlserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package sqlserver
import (
"net/http"
"os"
"path/filepath"
"strings"
"sync"
"testing"
Expand All @@ -33,6 +34,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/sqle"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
"github.com/dolthub/dolt/go/libraries/utils/config"
"github.com/dolthub/dolt/go/libraries/utils/filesys"
"github.com/dolthub/dolt/go/libraries/utils/svcs"
)

Expand Down Expand Up @@ -510,3 +512,114 @@ func TestReadReplica(t *testing.T) {
assert.ElementsMatch(t, res, []int{0})
})
}

func TestGenerateYamlConfig(t *testing.T) {
args := []string{
"--user", "my_name",
"--timeout", "11",
"--branch-control-file", "dir1/dir2/abc.db",
}

privilegeFilePath, err := filepath.Localize(".doltcfg/privileges.db")
require.NoError(t, err)

expected := `# Dolt SQL server configuration
#
# Uncomment and edit lines as necessary to modify your configuration.
# Full documentation: https://docs.dolthub.com/sql-reference/server/configuration
#
# log_level: info
# max_logged_query_len: 0
# encode_logged_query: false
# behavior:
# read_only: false
# autocommit: true
# disable_client_multi_statements: false
# dolt_transaction_commit: false
# event_scheduler: "OFF"
user:
name: my_name
# password: ""
listener:
# host: localhost
# port: 3306
# max_connections: 100
read_timeout_millis: 11000
write_timeout_millis: 11000
# tls_key: key.pem
# tls_cert: cert.pem
# require_secure_transport: false
# allow_cleartext_passwords: false
# socket: /tmp/mysql.sock
# data_dir: .
# cfg_dir: .doltcfg
# remotesapi:
# port: 8000
# read_only: false
# privilege_file: ` + privilegeFilePath +
`
branch_control_file: dir1/dir2/abc.db
# user_session_vars:
# - name: root
# vars:
# dolt_log_level: warn
# dolt_show_system_tables: 1
# system_variables:
# dolt_log_level: info
# dolt_transaction_commit: 1
# jwks: []
# metrics:
# labels: {}
# host: localhost
# port: 9091
# cluster:
# standby_remotes:
# - name: standby_replica_one
# remote_url_template: https://standby_replica_one.svc.cluster.local:50051/{database}
# - name: standby_replica_two
# remote_url_template: https://standby_replica_two.svc.cluster.local:50051/{database}
# bootstrap_role: primary
# bootstrap_epoch: 1
# remotesapi:
# address: 127.0.0.1
# port: 50051
# tls_key: remotesapi_key.pem
# tls_cert: remotesapi_chain.pem
# tls_ca: standby_cas.pem
# server_name_urls:
# - https://standby_replica_one.svc.cluster.local
# - https://standby_replica_two.svc.cluster.local
# server_name_dns:
# - standby_replica_one.svc.cluster.local
# - standby_replica_two.svc.cluster.local`

ap := SqlServerCmd{}.ArgParser()

dEnv := sqle.CreateTestEnv()

cwd, err := os.Getwd()
require.NoError(t, err)
cwdFs, err := filesys.LocalFilesysWithWorkingDir(cwd)
require.NoError(t, err)

serverConfig, err := ServerConfigFromArgs(ap, nil, args, dEnv, cwdFs)
require.NoError(t, err)

assert.Equal(t, expected, generateYamlConfig(serverConfig))
}
62 changes: 62 additions & 0 deletions go/cmd/dolt/commands/sqlserver/sqlserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strings"

Expand Down Expand Up @@ -244,6 +245,11 @@ func StartServer(ctx context.Context, versionStr, commandStr string, args []stri
return err
}

err = generateYamlConfigIfNone(ap, help, args, dEnv, serverConfig)
if err != nil {
return err
}

err = servercfg.ApplySystemVariables(serverConfig, sql.SystemVariables)
if err != nil {
return err
Expand Down Expand Up @@ -476,8 +482,17 @@ func setupDoltConfig(dEnv *env.DoltEnv, cwd filesys.Filesys, apr *argparser.ArgP
}
serverConfig.withCfgDir(cfgDirPath)

if cfgDirSpecified {
serverConfig.valuesSet[servercfg.CfgDirKey] = struct{}{}
}

if dataDirSpecified {
serverConfig.valuesSet[servercfg.DataDirKey] = struct{}{}
}

if privsFp, ok := apr.GetValue(commands.PrivsFilePathFlag); ok {
serverConfig.withPrivilegeFilePath(privsFp)
serverConfig.valuesSet[servercfg.PrivilegeFilePathKey] = struct{}{}
} else {
path, err := dEnv.FS.Abs(filepath.Join(cfgDirPath, commands.DefaultPrivsName))
if err != nil {
Expand All @@ -488,6 +503,7 @@ func setupDoltConfig(dEnv *env.DoltEnv, cwd filesys.Filesys, apr *argparser.ArgP

if branchControlFilePath, ok := apr.GetValue(commands.BranchCtrlPathFlag); ok {
serverConfig.withBranchControlFilePath(branchControlFilePath)
serverConfig.valuesSet[servercfg.BranchControlFilePathKey] = struct{}{}
} else {
path, err := dEnv.FS.Abs(filepath.Join(cfgDirPath, commands.DefaultBranchCtrlName))
if err != nil {
Expand All @@ -498,3 +514,49 @@ func setupDoltConfig(dEnv *env.DoltEnv, cwd filesys.Filesys, apr *argparser.ArgP

return nil
}

// generateYamlConfigIfNone creates a YAML config file in the database directory if one is not specified in the args
// and one doesn't already exist in the database directory. The fields of the YAML file are generated using the values
// in serverConfig that were explicitly set by the command line args.
func generateYamlConfigIfNone(
ap *argparser.ArgParser,
help cli.UsagePrinter,
args []string,
dEnv *env.DoltEnv,
serverConfig servercfg.ServerConfig) error {
const yamlConfigName = "config.yaml"

apr := cli.ParseArgsOrDie(ap, args, help)

if apr.Contains(configFileFlag) {
return nil
}

path := filepath.Join(serverConfig.DataDir(), yamlConfigName)
exists, _ := dEnv.FS.Exists(path)
if exists {
return nil
}

generatedYaml := generateYamlConfig(serverConfig)

err := dEnv.FS.WriteFile(path, []byte(generatedYaml), os.ModePerm)
if err != nil {
return err
}

return nil
}

// generateYamlConfig returns a YAML string containing the fields in serverConfig that
// were explicitly set by the command line args, along with commented-out placeholders for any
// fields that were not explicitly set by the command line args.
func generateYamlConfig(serverConfig servercfg.ServerConfig) string {
yamlConfig := servercfg.ServerConfigSetValuesAsYAMLConfig(serverConfig)

return `# Dolt SQL server configuration
#
# Uncomment and edit lines as necessary to modify your configuration.
# Full documentation: https://docs.dolthub.com/sql-reference/server/configuration
#` + "\n\n" + yamlConfig.VerboseString()
}
41 changes: 37 additions & 4 deletions go/libraries/doltcore/servercfg/serverconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ type ServerConfig interface {

// DefaultServerConfig creates a `*ServerConfig` that has all of the options set to their default values.
func DefaultServerConfig() ServerConfig {
return defaultServerConfigYAML()
}

func defaultServerConfigYAML() *YAMLConfig {
return &YAMLConfig{
LogLevelStr: ptr(string(DefaultLogLevel)),
MaxQueryLenInLogs: ptr(DefaultMaxLoggedQueryLen),
Expand Down Expand Up @@ -265,10 +269,39 @@ func ValidateConfig(config ServerConfig) error {
}

const (
MaxConnectionsKey = "max_connections"
ReadTimeoutKey = "net_read_timeout"
WriteTimeoutKey = "net_write_timeout"
EventSchedulerKey = "event_scheduler"
HostKey = "host"
PortKey = "port"
UserKey = "user"
PasswordKey = "password"
ReadTimeoutKey = "net_read_timeout"
WriteTimeoutKey = "net_write_timeout"
ReadOnlyKey = "read_only"
LogLevelKey = "log_level"
AutoCommitKey = "autocommit"
DoltTransactionCommitKey = "dolt_transaction_commit"
DataDirKey = "data_dir"
CfgDirKey = "cfg_dir"
MaxConnectionsKey = "max_connections"
TLSKeyKey = "tls_key"
TLSCertKey = "tls_cert"
RequireSecureTransportKey = "require_secure_transport"
MaxLoggedQueryLenKey = "max_logged_query_len"
ShouldEncodeLoggedQueryKey = "should_encode_logged_query"
DisableClientMultiStatementsKey = "disable_client_multi_statements"
MetricsLabelsKey = "metrics_labels"
MetricsHostKey = "metrics_host"
MetricsPortKey = "metrics_port"
PrivilegeFilePathKey = "privilege_file_path"
BranchControlFilePathKey = "branch_control_file_path"
UserVarsKey = "user_vars"
SystemVarsKey = "system_vars"
JwksConfigKey = "jwks_config"
AllowCleartextPasswordsKey = "allow_cleartext_passwords"
SocketKey = "socket"
RemotesapiPortKey = "remotesapi_port"
RemotesapiReadOnlyKey = "remotesapi_read_only"
ClusterConfigKey = "cluster_config"
EventSchedulerKey = "event_scheduler"
)

type SystemVariableTarget interface {
Expand Down
Loading

0 comments on commit 53a9c9a

Please sign in to comment.