136 lines
2.9 KiB
Go
136 lines
2.9 KiB
Go
package config
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
|
|
"git.dotya.ml/mirre-mt/pcmt/slogging"
|
|
"github.com/philandstuff/dhall-golang/v6"
|
|
"golang.org/x/exp/slog"
|
|
)
|
|
|
|
type session struct {
|
|
CookieName string
|
|
CookieSecret string
|
|
}
|
|
|
|
type Config struct {
|
|
Host string
|
|
Port int
|
|
AppName string
|
|
LiveMode bool
|
|
DevelMode bool
|
|
Session session
|
|
Registration struct{ Allowed bool }
|
|
Logger struct {
|
|
Json bool //nolint:revive
|
|
Fmt string
|
|
}
|
|
}
|
|
|
|
const schemaCompatibility = "0.0.0" //nolint:unused
|
|
|
|
var log slogging.Slogger
|
|
|
|
func LoadConfig(conf string, isPath bool) (*Config, error) {
|
|
var config Config
|
|
|
|
var err error
|
|
|
|
slogger := slogging.Logger()
|
|
// initialise if not already initialised.
|
|
if slogger == nil {
|
|
slogger = slogging.Init(true)
|
|
}
|
|
|
|
// have a local copy.
|
|
log = *slogger
|
|
// add attr to all statements made with the local copy.
|
|
log.Logger = log.Logger.With(
|
|
slog.Group("pcmt extra", slog.String("module", "config")),
|
|
)
|
|
|
|
switch {
|
|
case isPath:
|
|
log.Debug("config from file")
|
|
|
|
err = dhall.UnmarshalFile(conf, &config)
|
|
case !isPath:
|
|
log.Debug("config raw from cmdline")
|
|
|
|
err = dhall.Unmarshal([]byte(conf), &config)
|
|
}
|
|
|
|
if !config.Logger.Json {
|
|
slogger = slogging.Init(false)
|
|
log.Logger = slogger.Logger.With(
|
|
slog.Group("pcmt extra", slog.String("module", "config")),
|
|
)
|
|
}
|
|
|
|
if config.DevelMode && os.Getenv("PCMT_DEVEL") != "False" {
|
|
log.Debug("set DEBUG level based on config value")
|
|
|
|
slogger = slogging.SetLevel(slogging.LevelDebug)
|
|
log.Logger = slogger.Logger.With(
|
|
slog.Group("pcmt extra", slog.String("module", "config")),
|
|
)
|
|
|
|
log.Debugf("parsed config: %+v", config)
|
|
|
|
if dhallCmdExists() {
|
|
_ = prettyPrintConfig(conf, isPath)
|
|
}
|
|
}
|
|
|
|
// only return now, one we had a chance to print the loaded config (as
|
|
// would be the case if the config adhered to the schema but our type
|
|
// definition above didn't - "don't know how to decode <nil> into ...")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
func prettyPrintConfig(conf string, isPath bool) error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
|
|
var cmd *exec.Cmd
|
|
if isPath {
|
|
cmd = exec.CommandContext(ctx, "/bin/sh", "-c", "dhall --file "+conf) //nolint:gosec
|
|
} else {
|
|
cmd = exec.CommandContext(ctx, "/bin/sh", "-c", "dhall <<< \""+conf+"\"") //nolint:gosec
|
|
}
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
log.Debug("could not pretty-print config", "error", err)
|
|
return err
|
|
}
|
|
|
|
if isPath {
|
|
fmt.Fprintln(os.Stderr, "\n"+conf+":\n"+string(output))
|
|
} else {
|
|
fmt.Fprintln(os.Stderr, "\nconfig:\n"+string(output))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func dhallCmdExists() bool {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
|
|
if err := exec.CommandContext(ctx, "/bin/sh", "-c", "command -v dhall").Run(); err != nil {
|
|
log.Debug("no command dhall")
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|