mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 16:34:02 +01:00
202 lines
4.2 KiB
Go
202 lines
4.2 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/knadh/koanf/providers/env"
|
|
"github.com/knadh/koanf/providers/posflag"
|
|
"github.com/knadh/koanf/v2"
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/stashapp/stash/pkg/fsutil"
|
|
"github.com/stashapp/stash/pkg/logger"
|
|
)
|
|
|
|
type flagStruct struct {
|
|
configFilePath string
|
|
nobrowser bool
|
|
}
|
|
|
|
var (
|
|
flags flagStruct
|
|
|
|
homeDir, _ = os.UserHomeDir()
|
|
|
|
defaultConfigLocations = []string{
|
|
"config.yml",
|
|
filepath.Join(homeDir, ".stash", "config.yml"),
|
|
}
|
|
|
|
// map of env vars to config keys
|
|
envBinds = map[string]string{
|
|
"host": Host,
|
|
"port": Port,
|
|
"external_host": ExternalHost,
|
|
"generated": Generated,
|
|
"metadata": Metadata,
|
|
"blobs": BlobsPath,
|
|
"cache": Cache,
|
|
"stash": Stash,
|
|
"ui": UILocation,
|
|
}
|
|
)
|
|
|
|
var errConfigNotFound = errors.New("config file not found")
|
|
|
|
func init() {
|
|
pflag.IP("host", net.IPv4(0, 0, 0, 0), "ip address for the host")
|
|
pflag.Int("port", 9999, "port to serve from")
|
|
pflag.StringVarP(&flags.configFilePath, "config", "c", "", "config file to use")
|
|
pflag.BoolVar(&flags.nobrowser, "nobrowser", false, "Don't open a browser window after launch")
|
|
pflag.StringP("ui-location", "u", "", "path to the webui")
|
|
}
|
|
|
|
// Called at startup
|
|
func Initialize() (*Config, error) {
|
|
cfg := &Config{
|
|
main: koanf.New("."),
|
|
overrides: koanf.New("."),
|
|
}
|
|
|
|
cfg.initOverrides()
|
|
|
|
err := cfg.initConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if cfg.isNewSystem {
|
|
if cfg.Validate() == nil {
|
|
// system has been initialised by the environment
|
|
cfg.isNewSystem = false
|
|
}
|
|
}
|
|
|
|
if !cfg.isNewSystem {
|
|
cfg.setExistingSystemDefaults()
|
|
|
|
err := cfg.SetInitialConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = cfg.Write()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = cfg.Validate()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
instance = cfg
|
|
return instance, nil
|
|
}
|
|
|
|
// Called by tests to initialize an empty config
|
|
func InitializeEmpty() *Config {
|
|
cfg := &Config{
|
|
main: koanf.New("."),
|
|
overrides: koanf.New("."),
|
|
}
|
|
instance = cfg
|
|
return instance
|
|
}
|
|
|
|
func (i *Config) loadFromCommandLine() {
|
|
v := i.overrides
|
|
|
|
if err := v.Load(posflag.ProviderWithFlag(pflag.CommandLine, ".", v, func(f *pflag.Flag) (string, interface{}) {
|
|
// ignore flags that have not been changed
|
|
if !f.Changed {
|
|
return "", nil
|
|
}
|
|
|
|
return f.Name, posflag.FlagVal(pflag.CommandLine, f)
|
|
}), nil); err != nil {
|
|
logger.Errorf("failed to load flags: %v", err)
|
|
}
|
|
}
|
|
|
|
func (i *Config) loadFromEnv() {
|
|
v := i.overrides
|
|
|
|
if err := v.Load(env.ProviderWithValue("STASH_", ".", func(key, value string) (string, interface{}) {
|
|
key = strings.ToLower(strings.TrimPrefix(key, "STASH_"))
|
|
if newKey, ok := envBinds[key]; ok {
|
|
return newKey, value
|
|
}
|
|
|
|
return "", nil
|
|
}), nil); err != nil {
|
|
logger.Errorf("failed to load envs: %v", err)
|
|
}
|
|
}
|
|
|
|
func (i *Config) initOverrides() {
|
|
i.loadFromCommandLine()
|
|
i.loadFromEnv()
|
|
}
|
|
|
|
func (i *Config) initConfig() error {
|
|
configFile := ""
|
|
envConfigFile := os.Getenv("STASH_CONFIG_FILE")
|
|
|
|
if flags.configFilePath != "" {
|
|
configFile = flags.configFilePath
|
|
} else if envConfigFile != "" {
|
|
configFile = envConfigFile
|
|
}
|
|
|
|
if configFile != "" {
|
|
// if file does not exist, assume it is a new system
|
|
if exists, _ := fsutil.FileExists(configFile); !exists {
|
|
i.isNewSystem = true
|
|
i.SetConfigFile(configFile)
|
|
|
|
// ensure we can write to the file
|
|
if err := fsutil.Touch(configFile); err != nil {
|
|
return fmt.Errorf(`could not write to provided config path "%s": %v`, configFile, err)
|
|
} else {
|
|
// remove the file
|
|
os.Remove(configFile)
|
|
}
|
|
|
|
return nil
|
|
} else {
|
|
// load from provided config file
|
|
if err := i.loadFirstFromFiles([]string{configFile}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else {
|
|
// load from default locations
|
|
if err := i.loadFirstFromFiles(defaultConfigLocations); err != nil {
|
|
if errors.Is(err, errConfigNotFound) {
|
|
i.isNewSystem = true
|
|
return nil
|
|
}
|
|
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (i *Config) loadFirstFromFiles(f []string) error {
|
|
for _, ff := range f {
|
|
if exists, _ := fsutil.FileExists(ff); exists {
|
|
return i.load(ff)
|
|
}
|
|
}
|
|
|
|
return errConfigNotFound
|
|
}
|