mirror of
https://github.com/bytedream/docker4ssh.git
synced 2025-06-27 09:50:31 +02:00
Initial commit
This commit is contained in:
189
server/config/config.go
Normal file
189
server/config/config.go
Normal file
@ -0,0 +1,189 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/BurntSushi/toml"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var globConfig *Config
|
||||
|
||||
type Config struct {
|
||||
Profile struct {
|
||||
Dir string `toml:"Dir"`
|
||||
Default struct {
|
||||
Password string `toml:"Password"`
|
||||
NetworkMode int `toml:"NetworkMode"`
|
||||
Configurable bool `toml:"Configurable"`
|
||||
RunLevel int `toml:"RunLevel"`
|
||||
StartupInformation bool `toml:"StartupInformation"`
|
||||
ExitAfter string `toml:"ExitAfter"`
|
||||
KeepOnExit bool `toml:"KeepOnExit"`
|
||||
} `toml:"default"`
|
||||
Dynamic struct {
|
||||
Enable bool `toml:"Enable"`
|
||||
Password string `toml:"Password"`
|
||||
NetworkMode int `toml:"NetworkMode"`
|
||||
Configurable bool `toml:"Configurable"`
|
||||
RunLevel int `toml:"RunLevel"`
|
||||
StartupInformation bool `toml:"StartupInformation"`
|
||||
ExitAfter string `toml:"ExitAfter"`
|
||||
KeepOnExit bool `toml:"KeepOnExit"`
|
||||
} `toml:"dynamic"`
|
||||
} `toml:"profile"`
|
||||
Api struct {
|
||||
Port uint16 `toml:"Port"`
|
||||
Configure struct {
|
||||
Binary string `toml:"Binary"`
|
||||
Man string `toml:"Man"`
|
||||
} `toml:"configure"`
|
||||
} `toml:"api"`
|
||||
SSH struct {
|
||||
Port uint16 `toml:"Port"`
|
||||
Keyfile string `toml:"Keyfile"`
|
||||
Passphrase string `toml:"Passphrase"`
|
||||
} `toml:"ssh"`
|
||||
Database struct {
|
||||
Sqlite3File string `toml:"Sqlite3File"`
|
||||
} `toml:"Database"`
|
||||
Network struct {
|
||||
Default struct {
|
||||
Subnet string `toml:"Subnet"`
|
||||
} `toml:"default"`
|
||||
Isolate struct {
|
||||
Subnet string `toml:"Subnet"`
|
||||
} `toml:"isolate"`
|
||||
} `toml:"network"`
|
||||
Logging struct {
|
||||
Level string `toml:"Level"`
|
||||
OutputFile string `toml:"OutputFile"`
|
||||
ErrorFile string `toml:"ErrorFile"`
|
||||
ConsoleOutput bool `toml:"ConsoleOutput"`
|
||||
ConsoleError bool `toml:"ConsoleError"`
|
||||
} `toml:"logging"`
|
||||
}
|
||||
|
||||
func InitConfig(includeEnv bool) (*Config, error) {
|
||||
configFiles := []string{
|
||||
"./docker4ssh.conf",
|
||||
"~/.docker4ssh",
|
||||
"~/.config/docker4ssh.conf",
|
||||
"/etc/docker4ssh/docker4ssh.conf",
|
||||
}
|
||||
|
||||
for _, file := range configFiles {
|
||||
if _, err := os.Stat(file); !os.IsNotExist(err) {
|
||||
return LoadConfig(file, includeEnv)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no speicfied config file (%s) could be found", strings.Join(configFiles, ", "))
|
||||
}
|
||||
|
||||
func LoadConfig(file string, includeEnv bool) (*Config, error) {
|
||||
config := &Config{}
|
||||
|
||||
if _, err := toml.DecodeFile(file, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// make paths absolute
|
||||
dir := filepath.Dir(file)
|
||||
config.Profile.Dir = absoluteFile(dir, config.Profile.Dir)
|
||||
config.Api.Configure.Binary = absoluteFile(dir, config.Api.Configure.Binary)
|
||||
config.Api.Configure.Man = absoluteFile(dir, config.Api.Configure.Man)
|
||||
config.SSH.Keyfile = absoluteFile(dir, config.SSH.Keyfile)
|
||||
config.Database.Sqlite3File = absoluteFile(dir, config.Database.Sqlite3File)
|
||||
config.Logging.OutputFile = absoluteFile(dir, config.Logging.OutputFile)
|
||||
config.Logging.ErrorFile = absoluteFile(dir, config.Logging.ErrorFile)
|
||||
|
||||
if includeEnv {
|
||||
if err := updateFromEnv(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func absoluteFile(path, file string) string {
|
||||
if filepath.IsAbs(file) {
|
||||
return file
|
||||
}
|
||||
return filepath.Join(path, file)
|
||||
}
|
||||
|
||||
// updateFromEnv looks up if specific environment variable are given which can
|
||||
// also be used to configure the program.
|
||||
// Every key in the config file can also be specified via environment variables.
|
||||
// The env variable syntax is SECTION_KEY -> e.g. DEFAULT_PASSWORD or API_PORT
|
||||
func updateFromEnv(config *Config) error {
|
||||
re := reflect.ValueOf(config).Elem()
|
||||
rt := re.Type()
|
||||
|
||||
for i := 0; i < re.NumField(); i++ {
|
||||
rf := re.Field(i)
|
||||
ree := rt.Field(i)
|
||||
|
||||
if err := envParseField(strings.ToUpper(ree.Tag.Get("toml")), rf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func envParseField(prefix string, value reflect.Value) error {
|
||||
for j := 0; j < value.NumField(); j++ {
|
||||
rtt := value.Type().Field(j)
|
||||
rff := value.Field(j)
|
||||
|
||||
if rff.Kind() == reflect.Struct {
|
||||
if err := envParseField(fmt.Sprintf("%s_%s", prefix, strings.ToUpper(rtt.Tag.Get("toml"))), rff); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
envName := fmt.Sprintf("%s_%s", prefix, strings.ToUpper(rtt.Tag.Get("toml")))
|
||||
val, ok := os.LookupEnv(envName)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var expected string
|
||||
switch rff.Kind() {
|
||||
case reflect.String:
|
||||
rff.SetString(val)
|
||||
continue
|
||||
case reflect.Bool:
|
||||
b, err := strconv.ParseBool(val)
|
||||
if err == nil {
|
||||
rff.SetBool(b)
|
||||
continue
|
||||
}
|
||||
expected = "true / false (boolean)"
|
||||
case reflect.Uint16:
|
||||
ui, err := strconv.ParseUint(val, 10, 16)
|
||||
if err == nil {
|
||||
rff.SetUint(ui)
|
||||
continue
|
||||
}
|
||||
expected = "number (uint16)"
|
||||
default:
|
||||
return fmt.Errorf("parsed not implemented config type '%s'", rff.Kind())
|
||||
}
|
||||
return fmt.Errorf("failed to parse environment variable '%s': cannot parse value '%s' as %s", envName, val, expected)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetConfig() *Config {
|
||||
return globConfig
|
||||
}
|
||||
|
||||
func SetConfig(config *Config) {
|
||||
globConfig = config
|
||||
}
|
Reference in New Issue
Block a user