100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func (c *Config) ToFile() File {
|
|
if c == nil {
|
|
return File{}
|
|
}
|
|
return File{
|
|
Listen: ListenFile{Host: c.ListenHost, Port: c.ListenPort},
|
|
LocalAuth: LocalAuthFile{Username: c.LocalUsername, Password: c.LocalPassword},
|
|
Tunnel: TunnelFile{
|
|
URL: c.TunnelURL,
|
|
EncodeBase64: c.EncodeBase64,
|
|
TLSInsecureSkipVerify: c.TLSInsecureSkipVerify,
|
|
},
|
|
Remote: RemoteFile{
|
|
Host: c.RemoteHost,
|
|
Port: c.RemotePort,
|
|
Username: c.RemoteUsername,
|
|
Password: c.RemotePassword,
|
|
Database: c.RemoteDatabase,
|
|
Charset: c.RemoteCharset,
|
|
},
|
|
Options: OptionsFile{
|
|
RequestTimeout: int(c.RequestTimeout.Seconds()),
|
|
MaxConnections: c.MaxConnections,
|
|
LogLevel: c.LogLevel,
|
|
LogSQL: c.LogSQL,
|
|
LogFile: relativeLogFile(c.Path, c.LogFile),
|
|
},
|
|
}
|
|
}
|
|
|
|
func relativeLogFile(cfgPath, logFile string) string {
|
|
if logFile == "" {
|
|
return DefaultLogFile
|
|
}
|
|
if !filepath.IsAbs(logFile) {
|
|
return filepath.ToSlash(filepath.Clean(logFile))
|
|
}
|
|
dir := filepath.Dir(cfgPath)
|
|
rel, err := filepath.Rel(dir, logFile)
|
|
if err != nil {
|
|
return logFile
|
|
}
|
|
return filepath.ToSlash(rel)
|
|
}
|
|
|
|
func Save(path string, c *Config) error {
|
|
if path == "" {
|
|
return fmt.Errorf("config path is empty")
|
|
}
|
|
if dir := filepath.Dir(path); dir != "" && dir != "." {
|
|
if err := os.MkdirAll(dir, 0o750); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
raw, err := yaml.Marshal(c.ToFile())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out := append([]byte("# Written by mysql-tunnel. Contains secrets; do not commit.\n"), raw...)
|
|
return os.WriteFile(path, out, 0o600)
|
|
}
|
|
|
|
func DefaultSavePath() string {
|
|
if exe, err := os.Executable(); err == nil {
|
|
return filepath.Join(filepath.Dir(exe), "config.yaml")
|
|
}
|
|
return "config.yaml"
|
|
}
|
|
|
|
// LoadOrEmpty returns a parsed config, or defaults if the file is missing or invalid.
|
|
func LoadOrEmpty(path string) *Config {
|
|
if path == "" {
|
|
path = DefaultSavePath()
|
|
}
|
|
if _, err := os.Stat(path); err != nil {
|
|
c := Defaults()
|
|
c.Path = path
|
|
return &c
|
|
}
|
|
cfg, err := Parse(path, Overrides{})
|
|
if err != nil {
|
|
c := Defaults()
|
|
c.Path = path
|
|
c.Warnings = append(c.Warnings, err.Error())
|
|
return &c
|
|
}
|
|
cfg.ResolvePaths()
|
|
return cfg
|
|
}
|