conf: add pretty printing,raw conf, conf tests
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
* also, set debug logger directly in config if devel mode is set * add new flag to indicate whether the passed config is path or raw config
This commit is contained in:
parent
2a56ba3456
commit
dfdcc77737
@ -1,6 +1,12 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"git.dotya.ml/mirre-mt/pcmt/slogging"
|
||||
"github.com/philandstuff/dhall-golang/v6"
|
||||
)
|
||||
@ -15,15 +21,72 @@ type Config struct {
|
||||
SessionCookieSecret string
|
||||
}
|
||||
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
func LoadConfig(conf string, isPath bool) (*Config, error) {
|
||||
var config Config
|
||||
|
||||
err := dhall.UnmarshalFile(path, &config)
|
||||
var err error
|
||||
|
||||
if isPath {
|
||||
slogging.GetLogger().Debug("config from file")
|
||||
|
||||
err = dhall.UnmarshalFile(conf, &config)
|
||||
} else {
|
||||
slogging.GetLogger().Debug("config raw from cmdline")
|
||||
|
||||
err = dhall.Unmarshal([]byte(conf), &config)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slogging.GetLogger().Debugf("parsed config: %+v", config)
|
||||
if config.DevelMode {
|
||||
_ = slogging.SetLevel(slogging.LevelDebug)
|
||||
|
||||
slogging.GetLogger().Debugf("parsed config: %+v", config)
|
||||
|
||||
if dhallCmdExists() {
|
||||
_ = prettyPrintConfig(conf, isPath)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
slogging.GetLogger().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 {
|
||||
slogging.GetLogger().Debug("no command dhall")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
114
config/config_test.go
Normal file
114
config/config_test.go
Normal file
@ -0,0 +1,114 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.dotya.ml/mirre-mt/pcmt/slogging"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
if os.Getenv("CI") == "true" {
|
||||
t.Skip("we're running in CI apparently, skipping these tests")
|
||||
}
|
||||
|
||||
confPath := "./testconfigs/"
|
||||
ts := []struct {
|
||||
name string
|
||||
fails bool
|
||||
isPath bool
|
||||
conf string
|
||||
}{
|
||||
{
|
||||
// incorrect type of the `Host` field.
|
||||
name: "1.dhall",
|
||||
fails: true,
|
||||
isPath: true,
|
||||
conf: "1.dhall",
|
||||
},
|
||||
{
|
||||
name: "2.dhall",
|
||||
fails: false,
|
||||
isPath: true,
|
||||
conf: "2.dhall",
|
||||
},
|
||||
{
|
||||
name: "3.dhall",
|
||||
fails: false,
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
sha256:ad7ba86d5d388a99b7543faa0e4c81ba1d9b78fa6c32fdaf4ac4477089d177be
|
||||
? https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
let c = Config::{ DevelMode = True }
|
||||
|
||||
in c
|
||||
`,
|
||||
},
|
||||
{
|
||||
// misses final `in`.
|
||||
name: "4.dhall",
|
||||
fails: true,
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
sha256:ad7ba86d5d388a99b7543faa0e4c81ba1d9b78fa6c32fdaf4ac4477089d177be
|
||||
? https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
let c = Config::{ DevelMode = True }
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "5.dhall",
|
||||
fails: false,
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
in ConfigSchema.Schema::{ DevelMode = True, Port = 5555 }
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "6.dhall",
|
||||
fails: false,
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
in ConfigSchema.Schema.default // { DevelMode = True }
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
_ = slogging.Init(false)
|
||||
|
||||
for _, tc := range ts {
|
||||
t.Logf("running test case %s", tc.name)
|
||||
|
||||
var err error
|
||||
|
||||
shouldFail := tc.fails
|
||||
|
||||
if tc.isPath {
|
||||
_, err = LoadConfig(confPath+tc.conf, tc.isPath)
|
||||
} else {
|
||||
_, err = LoadConfig(tc.conf, tc.isPath)
|
||||
}
|
||||
|
||||
switch {
|
||||
case err == nil && shouldFail:
|
||||
t.Errorf("test case '%s' should have failed", tc.name)
|
||||
|
||||
case err != nil && !shouldFail:
|
||||
t.Log(err)
|
||||
t.Errorf("test case '%s' should not have failed", tc.name)
|
||||
}
|
||||
}
|
||||
}
|
9
config/testconfigs/1.dhall
Normal file
9
config/testconfigs/1.dhall
Normal file
@ -0,0 +1,9 @@
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
sha256:ad7ba86d5d388a99b7543faa0e4c81ba1d9b78fa6c32fdaf4ac4477089d177be
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
let c = Config::{ Host = False }
|
||||
|
||||
in c
|
9
config/testconfigs/2.dhall
Normal file
9
config/testconfigs/2.dhall
Normal file
@ -0,0 +1,9 @@
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt/raw/branch/development/config/schema/package.dhall
|
||||
sha256:ad7ba86d5d388a99b7543faa0e4c81ba1d9b78fa6c32fdaf4ac4477089d177be
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
let c = Config::{ Host = "localhost" }
|
||||
|
||||
in c
|
19
run.go
19
run.go
@ -51,13 +51,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.`
|
||||
)
|
||||
|
||||
var (
|
||||
host = flag.String("host", "unset", "host address to listen on")
|
||||
port = flag.Int("port", -1, "TCP port to listen on")
|
||||
configFlag = flag.String("config", "config.dhall", "Default path of the config file")
|
||||
devel = flag.Bool("devel", false, "Run the application in dev mode, connect to a local browser-sync instance for hot-reloading")
|
||||
license = flag.Bool("license", false, "Print licensing information and exit")
|
||||
version = "dev"
|
||||
log *slogging.Logger
|
||||
host = flag.String("host", "unset", "host address to listen on")
|
||||
port = flag.Int("port", -1, "TCP port to listen on")
|
||||
configFlag = flag.String("config", "config.dhall", "Default path of the config file")
|
||||
configIsPathFlag = flag.Bool("configIsPath", true, "Whether the provided config is path or raw config")
|
||||
devel = flag.Bool("devel", false, "Run the application in dev mode, connect to a local browser-sync instance for hot-reloading")
|
||||
license = flag.Bool("license", false, "Print licensing information and exit")
|
||||
version = "dev"
|
||||
log *slogging.Logger
|
||||
)
|
||||
|
||||
func run() error {
|
||||
@ -81,9 +82,9 @@ func run() error {
|
||||
// TODO: SBOM: https://actuated.dev/blog/sbom-in-github-actions
|
||||
// TODO: SBOM: https://www.docker.com/blog/generate-sboms-with-buildkit/
|
||||
|
||||
conf, err := config.LoadConfig(*configFlag)
|
||||
conf, err := config.LoadConfig(*configFlag, *configIsPathFlag)
|
||||
if err != nil {
|
||||
log.Errorf("error loading config file at '%s', bailing", *configFlag)
|
||||
log.Errorf("error loading config file '%s', bailing", *configFlag)
|
||||
return err
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user