Merge pull request 'Move to koanf and urfavecli' (#50) from urfavecli into trunk
Reviewed-on: #50
This commit is contained in:
commit
c872f7bb9a
14 changed files with 352 additions and 122 deletions
|
@ -13,28 +13,52 @@ import (
|
||||||
"dynatron.me/x/stillbox/pkg/cmd/serve"
|
"dynatron.me/x/stillbox/pkg/cmd/serve"
|
||||||
"dynatron.me/x/stillbox/pkg/config"
|
"dynatron.me/x/stillbox/pkg/config"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DefaultConfig = "config.yaml"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
configFile := DefaultConfig
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: common.TimeFormat})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: common.TimeFormat})
|
||||||
|
|
||||||
rootCmd := &cobra.Command{
|
cfg := config.New(&configFile)
|
||||||
Use: common.AppName,
|
app := &cli.App{
|
||||||
}
|
Name: common.AppName,
|
||||||
rootCmd.PersistentFlags().BoolP("version", "V", false, "show version")
|
Usage: "a scanner call server",
|
||||||
cfg := config.New(rootCmd)
|
UseShortOptionHandling: true,
|
||||||
rootCmd.PreRun = func(cmd *cobra.Command, args []string) {
|
Before: cfg.Before,
|
||||||
v, _ := rootCmd.PersistentFlags().GetBool("version")
|
Flags: []cli.Flag{
|
||||||
if v {
|
&cli.StringFlag{
|
||||||
fmt.Print(version.String())
|
Name: "config",
|
||||||
os.Exit(0)
|
Value: DefaultConfig,
|
||||||
}
|
Usage: "configuration file",
|
||||||
|
Destination: &configFile,
|
||||||
|
Aliases: []string{"c"},
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "version",
|
||||||
|
Aliases: []string{"V"},
|
||||||
|
Action: func(_ *cli.Context, v bool) error {
|
||||||
|
if v {
|
||||||
|
fmt.Print(version.String())
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
DisableDefaultText: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Commands: []*cli.Command{
|
||||||
|
serve.Command(cfg),
|
||||||
|
admin.Command(cfg),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmds := append([]*cobra.Command{serve.Command(cfg)}, admin.Command(cfg)...)
|
err := app.Run(os.Args)
|
||||||
rootCmd.AddCommand(cmds...)
|
if err != nil {
|
||||||
|
os.Stderr.Write([]byte("Error: " + err.Error() + "\n"))
|
||||||
// cobra is already checking for errors and will print them
|
os.Exit(1)
|
||||||
_ = rootCmd.Execute()
|
}
|
||||||
}
|
}
|
||||||
|
|
15
go.mod
15
go.mod
|
@ -17,11 +17,15 @@ require (
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/hajimehoshi/oto v1.0.1
|
github.com/hajimehoshi/oto v1.0.1
|
||||||
github.com/jackc/pgx/v5 v5.7.1
|
github.com/jackc/pgx/v5 v5.7.1
|
||||||
|
github.com/knadh/koanf/parsers/yaml v0.1.0
|
||||||
|
github.com/knadh/koanf/providers/env v1.0.0
|
||||||
|
github.com/knadh/koanf/providers/file v1.1.2
|
||||||
|
github.com/knadh/koanf/v2 v2.1.2
|
||||||
github.com/nikoksr/notify v1.1.0
|
github.com/nikoksr/notify v1.1.0
|
||||||
github.com/rs/zerolog v1.33.0
|
github.com/rs/zerolog v1.33.0
|
||||||
github.com/spf13/cobra v1.8.1
|
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300
|
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300
|
||||||
|
github.com/urfave/cli/v2 v2.27.5
|
||||||
golang.org/x/crypto v0.29.0
|
golang.org/x/crypto v0.29.0
|
||||||
golang.org/x/sync v0.9.0
|
golang.org/x/sync v0.9.0
|
||||||
golang.org/x/term v0.26.0
|
golang.org/x/term v0.26.0
|
||||||
|
@ -32,18 +36,20 @@ require (
|
||||||
require (
|
require (
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||||
github.com/go-audio/audio v1.0.0 // indirect
|
github.com/go-audio/audio v1.0.0 // indirect
|
||||||
github.com/go-audio/riff v1.0.0 // indirect
|
github.com/go-audio/riff v1.0.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect
|
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
|
github.com/knadh/koanf/maps v0.1.1 // indirect
|
||||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||||
github.com/lestrrat-go/httprc v1.0.6 // indirect
|
github.com/lestrrat-go/httprc v1.0.6 // indirect
|
||||||
|
@ -52,10 +58,13 @@ require (
|
||||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
github.com/segmentio/asm v1.2.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
|
||||||
github.com/stretchr/objx v0.5.2 // indirect
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
golang.org/x/exp/shiny v0.0.0-20241108190413-2d47ceb2692f // indirect
|
golang.org/x/exp/shiny v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||||
golang.org/x/image v0.22.0 // indirect
|
golang.org/x/image v0.22.0 // indirect
|
||||||
|
|
30
go.sum
30
go.sum
|
@ -11,7 +11,8 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoU
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -29,6 +30,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||||
|
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
|
github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
|
||||||
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||||
github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
|
github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
|
||||||
|
@ -71,8 +74,6 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
|
||||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
|
||||||
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0=
|
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0=
|
||||||
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
|
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
@ -85,6 +86,16 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
|
||||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||||
|
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
|
||||||
|
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
|
||||||
|
github.com/knadh/koanf/parsers/yaml v0.1.0 h1:ZZ8/iGfRLvKSaMEECEBPM1HQslrZADk8fP1XFUxVI5w=
|
||||||
|
github.com/knadh/koanf/parsers/yaml v0.1.0/go.mod h1:cvbUDC7AL23pImuQP0oRw/hPuccrNBS2bps8asS0CwY=
|
||||||
|
github.com/knadh/koanf/providers/env v1.0.0 h1:ufePaI9BnWH+ajuxGGiJ8pdTG0uLEUWC7/HDDPGLah0=
|
||||||
|
github.com/knadh/koanf/providers/env v1.0.0/go.mod h1:mzFyRZueYhb37oPmC1HAv/oGEEuyvJDA98r3XAa8Gak=
|
||||||
|
github.com/knadh/koanf/providers/file v1.1.2 h1:aCC36YGOgV5lTtAFz2qkgtWdeQsgfxUkxDOe+2nQY3w=
|
||||||
|
github.com/knadh/koanf/providers/file v1.1.2/go.mod h1:/faSBcv2mxPVjFrXck95qeoyoZ5myJ6uxN8OOVNJJCI=
|
||||||
|
github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ=
|
||||||
|
github.com/knadh/koanf/v2 v2.1.2/go.mod h1:Gphfaen0q1Fc1HTgJgSTC4oRX9R2R5ErYMZJy8fLJBo=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
@ -110,6 +121,10 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||||
|
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||||
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
|
@ -132,14 +147,11 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
|
||||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
|
||||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
@ -151,6 +163,10 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300 h1:XQdibLKagjdevRB6vAjVY4qbSr8rQ610YzTkWcxzxSI=
|
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300 h1:XQdibLKagjdevRB6vAjVY4qbSr8rQ610YzTkWcxzxSI=
|
||||||
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300/go.mod h1:FNa/dfN95vAYCNFrIKRrlRo+MBLbwmR9Asa5f2ljmBI=
|
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300/go.mod h1:FNa/dfN95vAYCNFrIKRrlRo+MBLbwmR9Asa5f2ljmBI=
|
||||||
|
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||||
|
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
|
||||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
||||||
|
|
|
@ -1,34 +1,31 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const AppName = "stillbox"
|
const (
|
||||||
|
AppName = "stillbox"
|
||||||
|
EnvPrefix = "STILLBOX_"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TimeFormat = "Jan 2 15:04:05"
|
TimeFormat = "Jan 2 15:04:05"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cmdOptions interface {
|
type cmdOptions interface {
|
||||||
Options(*cobra.Command, []string) error
|
Options(*cli.Context) error
|
||||||
Execute() error
|
Execute() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunE(c cmdOptions) func(cmd *cobra.Command, args []string) error {
|
func Action(c cmdOptions) cli.ActionFunc {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(ctx *cli.Context) error {
|
||||||
err := c.Options(cmd, args)
|
err := c.Options(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.SilenceUsage = true
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.Execute()
|
return c.Execute()
|
||||||
if err != nil {
|
|
||||||
cmd.SilenceUsage = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
internal/forms/testdata/urlenc3.http
vendored
2
internal/forms/testdata/urlenc3.http
vendored
|
@ -2,7 +2,7 @@ POST /api/talkgroup/ HTTP/1.1
|
||||||
Host: xenon:3051
|
Host: xenon:3051
|
||||||
User-Agent: curl/8.10.1
|
User-Agent: curl/8.10.1
|
||||||
Accept: */*
|
Accept: */*
|
||||||
Content-Length: 16
|
Content-Length: 27
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
page=1&perPage=2&orderBy=id
|
page=1&perPage=2&orderBy=id
|
||||||
|
|
|
@ -68,6 +68,17 @@ func (d *Duration) UnmarshalYAML(n *yaml.Node) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Duration) UnmarshalText(text []byte) error {
|
||||||
|
dur, err := time.ParseDuration(string(text))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = Duration(dur)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||||
s := strings.Trim(string(b), `"`)
|
s := strings.Trim(string(b), `"`)
|
||||||
dur, err := time.ParseDuration(s)
|
dur, err := time.ParseDuration(s)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"dynatron.me/x/stillbox/pkg/config"
|
"dynatron.me/x/stillbox/pkg/config"
|
||||||
"dynatron.me/x/stillbox/pkg/database"
|
"dynatron.me/x/stillbox/pkg/database"
|
||||||
"github.com/spf13/cobra"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
@ -115,59 +115,78 @@ func readPassword(prompt string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command is the users command.
|
// Command is the users command.
|
||||||
func Command(cfg *config.Config) []*cobra.Command {
|
func Command(cfg *config.Configuration) *cli.Command {
|
||||||
userCmd := &cobra.Command{
|
c := &cfg.Config
|
||||||
Use: "users",
|
userCmd := &cli.Command{
|
||||||
Aliases: []string{"u"},
|
Name: "users",
|
||||||
Short: "administers the server",
|
Aliases: []string{"u"},
|
||||||
PersistentPreRunE: cfg.PreRunE(),
|
Usage: "administers users",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
addUserCommand(c),
|
||||||
|
passwdCommand(c),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
userCmd.AddCommand(addUserCommand(cfg), passwdCommand(cfg))
|
|
||||||
|
|
||||||
return []*cobra.Command{userCmd}
|
return userCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func addUserCommand(cfg *config.Config) *cobra.Command {
|
func addUserCommand(cfg *config.Config) *cli.Command {
|
||||||
c := &cobra.Command{
|
c := &cli.Command{
|
||||||
Use: "add",
|
Name: "add",
|
||||||
Short: "adds a user",
|
Description: "adds a user",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
UsageText: "stillbox users add [-a] [-m email] [username]",
|
||||||
|
Args: true,
|
||||||
|
Action: func(ctx *cli.Context) error {
|
||||||
|
if ctx.Args().Len() != 1 {
|
||||||
|
return errors.New(ctx.Command.Usage)
|
||||||
|
}
|
||||||
|
|
||||||
db, err := database.NewClient(context.Background(), cfg.DB)
|
db, err := database.NewClient(context.Background(), cfg.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
username := args[0]
|
username := ctx.Args().Get(0)
|
||||||
isAdmin, err := cmd.Flags().GetBool("admin")
|
isAdmin := ctx.Bool("admin")
|
||||||
if err != nil {
|
email := ctx.String("email")
|
||||||
return err
|
|
||||||
}
|
|
||||||
email, err := cmd.Flags().GetString("email")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddUser(database.CtxWithDB(context.Background(), db), username, email, isAdmin)
|
return AddUser(database.CtxWithDB(context.Background(), db), username, email, isAdmin)
|
||||||
},
|
},
|
||||||
Args: cobra.ExactArgs(1),
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "admin",
|
||||||
|
Aliases: []string{"a"},
|
||||||
|
Value: false,
|
||||||
|
Usage: "user is an admin",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "email",
|
||||||
|
Usage: "email address",
|
||||||
|
Aliases: []string{"m"},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
c.Flags().BoolP("admin", "a", false, "is admin")
|
|
||||||
c.Flags().StringP("email", "m", "", "email address")
|
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func passwdCommand(cfg *config.Config) *cobra.Command {
|
func passwdCommand(cfg *config.Config) *cli.Command {
|
||||||
c := &cobra.Command{
|
c := &cli.Command{
|
||||||
Use: "passwd userid",
|
Name: "passwd",
|
||||||
Short: "changes password for a user",
|
Usage: "changes password for a user",
|
||||||
Args: cobra.ExactArgs(1),
|
UsageText: "stillbox users passwd [username]",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
Args: true,
|
||||||
|
Action: func(ctx *cli.Context) error {
|
||||||
|
if ctx.Args().Len() != 1 {
|
||||||
|
return errors.New(ctx.Command.Usage)
|
||||||
|
}
|
||||||
|
|
||||||
db, err := database.NewClient(context.Background(), cfg.DB)
|
db, err := database.NewClient(context.Background(), cfg.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
username := args[0]
|
username := ctx.Args().Get(0)
|
||||||
|
|
||||||
return Passwd(database.CtxWithDB(context.Background(), db), username)
|
return Passwd(database.CtxWithDB(context.Background(), db), username)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,32 +9,31 @@ import (
|
||||||
"dynatron.me/x/stillbox/pkg/config"
|
"dynatron.me/x/stillbox/pkg/config"
|
||||||
"dynatron.me/x/stillbox/pkg/server"
|
"dynatron.me/x/stillbox/pkg/server"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServeOptions struct {
|
type ServeOptions struct {
|
||||||
cfg *config.Config
|
cfg *config.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func Command(cfg *config.Config) *cobra.Command {
|
func Command(cfg *config.Configuration) *cli.Command {
|
||||||
opts := makeOptions(cfg)
|
opts := makeOptions(cfg)
|
||||||
serveCmd := &cobra.Command{
|
serveCmd := &cli.Command{
|
||||||
Use: "serve",
|
Name: "serve",
|
||||||
Short: "starts the" + common.AppName + " server",
|
Usage: "starts the " + common.AppName + " server",
|
||||||
PersistentPreRunE: cfg.PreRunE(),
|
Action: common.Action(opts),
|
||||||
RunE: common.RunE(opts),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return serveCmd
|
return serveCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeOptions(cfg *config.Config) *ServeOptions {
|
func makeOptions(cfg *config.Configuration) *ServeOptions {
|
||||||
return &ServeOptions{
|
return &ServeOptions{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *ServeOptions) Options(_ *cobra.Command, args []string) error {
|
func (o *ServeOptions) Options(_ *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dynatron.me/x/stillbox/internal/jsontypes"
|
"dynatron.me/x/stillbox/internal/jsontypes"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Configuration struct {
|
||||||
|
Config
|
||||||
|
|
||||||
|
configPath *string `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DB DB `yaml:"db"`
|
DB DB `yaml:"db"`
|
||||||
CORS CORS `yaml:"cors"`
|
CORS CORS `yaml:"cors"`
|
||||||
|
@ -23,8 +26,6 @@ type Config struct {
|
||||||
RateLimit RateLimit `yaml:"rateLimit"`
|
RateLimit RateLimit `yaml:"rateLimit"`
|
||||||
Notify Notify `yaml:"notify"`
|
Notify Notify `yaml:"notify"`
|
||||||
Relay []Relay `yaml:"relay"`
|
Relay []Relay `yaml:"relay"`
|
||||||
|
|
||||||
configPath string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Auth struct {
|
type Auth struct {
|
||||||
|
@ -92,33 +93,3 @@ func (rl *RateLimit) Verify() bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) PreRunE() func(*cobra.Command, []string) error {
|
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
|
||||||
return c.ReadConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(rootCommand *cobra.Command) *Config {
|
|
||||||
c := &Config{}
|
|
||||||
|
|
||||||
rootCommand.PersistentFlags().StringVarP(&c.configPath, "config", "c", "config.yaml", "configuration file")
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) ReadConfig() error {
|
|
||||||
cfgBytes, err := os.ReadFile(c.configPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = yaml.Unmarshal(cfgBytes, c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Str("configPath", c.configPath).Msg("read config")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
66
pkg/config/parse.go
Normal file
66
pkg/config/parse.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"dynatron.me/x/stillbox/internal/common"
|
||||||
|
|
||||||
|
"github.com/go-viper/mapstructure/v2"
|
||||||
|
"github.com/knadh/koanf/parsers/yaml"
|
||||||
|
"github.com/knadh/koanf/providers/env"
|
||||||
|
"github.com/knadh/koanf/providers/file"
|
||||||
|
"github.com/knadh/koanf/v2"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(configFile *string) *Configuration {
|
||||||
|
if configFile == nil {
|
||||||
|
panic("configFile must not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Configuration{configPath: configFile}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) Before(ctx *cli.Context) error {
|
||||||
|
return c.ReadConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) ReadConfig() error {
|
||||||
|
log.Info().Str("configPath", *c.configPath).Msg("read config")
|
||||||
|
|
||||||
|
return c.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) read() error {
|
||||||
|
k := koanf.New(".")
|
||||||
|
err := k.Load(file.Provider(*c.configPath), yaml.Parser())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
k.Load(env.Provider(common.EnvPrefix, ".", func(s string) string {
|
||||||
|
return strings.Replace(strings.ToLower(
|
||||||
|
strings.TrimPrefix(s, common.EnvPrefix)), "_", ".", -1)
|
||||||
|
}), nil)
|
||||||
|
|
||||||
|
err = k.UnmarshalWithConf("", &c.Config,
|
||||||
|
koanf.UnmarshalConf{
|
||||||
|
Tag: "yaml",
|
||||||
|
DecoderConfig: &mapstructure.DecoderConfig{
|
||||||
|
Result: &c.Config,
|
||||||
|
WeaklyTypedInput: true,
|
||||||
|
DecodeHook: mapstructure.ComposeDecodeHookFunc(
|
||||||
|
mapstructure.StringToTimeDurationHookFunc(),
|
||||||
|
mapstructure.TextUnmarshallerHookFunc(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
80
pkg/config/parse_test.go
Normal file
80
pkg/config/parse_test.go
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"dynatron.me/x/stillbox/internal/common"
|
||||||
|
"dynatron.me/x/stillbox/internal/jsontypes"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
var expCfg = &Config{
|
||||||
|
DB: DB{
|
||||||
|
Connect: "postgres://stillbox:somepassword@stillbox:5432/stillbox?sslmode=disable",
|
||||||
|
LogQueries: true,
|
||||||
|
},
|
||||||
|
CORS: CORS{
|
||||||
|
AllowedOrigins: []string{
|
||||||
|
"http://localhost:*",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Auth: Auth{
|
||||||
|
JWTSecret: "somesecret",
|
||||||
|
Domain: "xenon",
|
||||||
|
AllowInsecure: map[string]bool{
|
||||||
|
"localhost": true,
|
||||||
|
"stillbox": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Alerting: Alerting{
|
||||||
|
Enable: true,
|
||||||
|
LookbackDays: 7,
|
||||||
|
HalfLife: jsontypes.Duration(30 * time.Minute),
|
||||||
|
Recent: jsontypes.Duration(2 * time.Hour),
|
||||||
|
AlertThreshold: 0.3,
|
||||||
|
Renotify: common.PtrTo(jsontypes.Duration(30 * time.Minute)),
|
||||||
|
},
|
||||||
|
Log: []Logger{
|
||||||
|
Logger{
|
||||||
|
Level: common.PtrTo("debug"),
|
||||||
|
},
|
||||||
|
Logger{
|
||||||
|
Level: common.PtrTo("error"),
|
||||||
|
File: common.PtrTo("error.log"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Listen: ":3051",
|
||||||
|
Public: true,
|
||||||
|
RateLimit: RateLimit{
|
||||||
|
Enable: true,
|
||||||
|
Requests: 200,
|
||||||
|
Over: 2 * time.Minute,
|
||||||
|
},
|
||||||
|
Notify: Notify{
|
||||||
|
NotifyService{
|
||||||
|
Provider: "slackwebhook",
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"webhookURL": "https://hook",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Relay: []Relay{
|
||||||
|
{
|
||||||
|
URL: "http://relay",
|
||||||
|
APIKey: "secret",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigParse(t *testing.T) {
|
||||||
|
c := &Configuration{configPath: common.PtrTo("testdata/testconfig.yaml")}
|
||||||
|
|
||||||
|
err := c.read()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expCfg, &c.Config)
|
||||||
|
}
|
38
pkg/config/testdata/testconfig.yaml
vendored
Normal file
38
pkg/config/testdata/testconfig.yaml
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
db:
|
||||||
|
connect: 'postgres://stillbox:somepassword@stillbox:5432/stillbox?sslmode=disable'
|
||||||
|
logQueries: true
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- 'http://localhost:*'
|
||||||
|
auth:
|
||||||
|
jwtsecret: 'somesecret'
|
||||||
|
domain: xenon
|
||||||
|
allowInsecureFor:
|
||||||
|
"localhost": true
|
||||||
|
"stillbox": true
|
||||||
|
listen: ':3051'
|
||||||
|
public: true
|
||||||
|
log:
|
||||||
|
- level: debug
|
||||||
|
- level: error
|
||||||
|
file: error.log
|
||||||
|
rateLimit:
|
||||||
|
enable: true
|
||||||
|
requests: 200
|
||||||
|
over: 2m
|
||||||
|
alerting:
|
||||||
|
enable: true
|
||||||
|
lookbackDays: 7
|
||||||
|
halfLife: 30m
|
||||||
|
recent: 2h
|
||||||
|
alertThreshold: 0.3
|
||||||
|
renotify: 30m
|
||||||
|
notify:
|
||||||
|
- provider: slackwebhook
|
||||||
|
config:
|
||||||
|
webhookURL: "https://hook"
|
||||||
|
relay:
|
||||||
|
- url: "http://relay"
|
||||||
|
apiKey: "secret"
|
||||||
|
required: true
|
||||||
|
|
|
@ -27,7 +27,7 @@ const shutdownTimeout = 5 * time.Second
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
auth *auth.Auth
|
auth *auth.Auth
|
||||||
conf *config.Config
|
conf *config.Configuration
|
||||||
db database.Store
|
db database.Store
|
||||||
r *chi.Mux
|
r *chi.Mux
|
||||||
sources sources.Sources
|
sources sources.Sources
|
||||||
|
@ -42,7 +42,7 @@ type Server struct {
|
||||||
rest rest.API
|
rest rest.API
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, cfg *config.Config) (*Server, error) {
|
func New(ctx context.Context, cfg *config.Configuration) (*Server, error) {
|
||||||
logger, err := NewLogger(cfg.Log)
|
logger, err := NewLogger(cfg.Log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -34,7 +34,7 @@ func (s *Server) installHupHandler() {
|
||||||
|
|
||||||
hs := s.huppers()
|
hs := s.huppers()
|
||||||
for _, h := range hs {
|
for _, h := range hs {
|
||||||
h.HUP(s.conf)
|
h.HUP(&s.conf.Config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
Loading…
Reference in a new issue