mirror of
https://github.com/aykhans/dodo.git
synced 2025-09-05 18:44:21 +00:00
add env parser
This commit is contained in:
@@ -4,16 +4,27 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/aykhans/dodo/pkg/config"
|
"github.com/aykhans/dodo/pkg/config/parser"
|
||||||
"github.com/aykhans/dodo/pkg/types"
|
"github.com/aykhans/dodo/pkg/types"
|
||||||
"github.com/aykhans/dodo/pkg/utils"
|
"github.com/aykhans/dodo/pkg/utils"
|
||||||
"github.com/jedib0t/go-pretty/v6/text"
|
"github.com/jedib0t/go-pretty/v6/text"
|
||||||
|
"github.com/k0kubun/pp/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cliParser := config.NewConfigCLIParser(os.Args)
|
envParser := parser.NewConfigENVParser("DODO")
|
||||||
cfg, err := cliParser.Parse()
|
envConfig, err := envParser.Parse()
|
||||||
|
_ = utils.HandleErrorOrDie(err,
|
||||||
|
utils.OnCustomError(func(err types.FieldParseErrors) error {
|
||||||
|
printValidationErrors("ENV", err.Errors...)
|
||||||
|
fmt.Println()
|
||||||
|
os.Exit(1)
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
cliParser := parser.NewConfigCLIParser(os.Args)
|
||||||
|
cliConf, err := cliParser.Parse()
|
||||||
_ = utils.HandleErrorOrDie(err,
|
_ = utils.HandleErrorOrDie(err,
|
||||||
utils.OnSentinelError(types.ErrCLINoArgs, func(err error) error {
|
utils.OnSentinelError(types.ErrCLINoArgs, func(err error) error {
|
||||||
cliParser.PrintHelp()
|
cliParser.PrintHelp()
|
||||||
@@ -35,7 +46,9 @@ func main() {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
fmt.Println(cfg)
|
envConfig.Merge(cliConf)
|
||||||
|
pp.Println(cliConf) //nolint
|
||||||
|
pp.Println(envConfig) //nolint
|
||||||
}
|
}
|
||||||
|
|
||||||
func printValidationErrors(parserName string, errors ...types.FieldParseError) {
|
func printValidationErrors(parserName string, errors ...types.FieldParseError) {
|
||||||
|
5
go.mod
5
go.mod
@@ -4,15 +4,18 @@ go 1.25
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/jedib0t/go-pretty/v6 v6.6.8
|
github.com/jedib0t/go-pretty/v6 v6.6.8
|
||||||
|
github.com/k0kubun/pp/v3 v3.5.0
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.26.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
11
go.sum
11
go.sum
@@ -2,6 +2,12 @@ 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=
|
||||||
github.com/jedib0t/go-pretty/v6 v6.6.8 h1:JnnzQeRz2bACBobIaa/r+nqjvws4yEhcmaZ4n1QzsEc=
|
github.com/jedib0t/go-pretty/v6 v6.6.8 h1:JnnzQeRz2bACBobIaa/r+nqjvws4yEhcmaZ4n1QzsEc=
|
||||||
github.com/jedib0t/go-pretty/v6 v6.6.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
github.com/jedib0t/go-pretty/v6 v6.6.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
||||||
|
github.com/k0kubun/pp/v3 v3.5.0 h1:iYNlYA5HJAJvkD4ibuf9c8y6SHM0QFhaBuCqm1zHp0w=
|
||||||
|
github.com/k0kubun/pp/v3 v3.5.0/go.mod h1:5lzno5ZZeEeTV/Ky6vs3g6d1U3WarDrH8k240vMtGro=
|
||||||
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
|
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-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
@@ -11,10 +17,11 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
|||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
@@ -49,7 +49,7 @@ func NewConfig() *Config {
|
|||||||
return &Config{}
|
return &Config{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) MergeConfig(newConfig *Config) {
|
func (config *Config) Merge(newConfig *Config) {
|
||||||
config.Files = append(config.Files, newConfig.Files...)
|
config.Files = append(config.Files, newConfig.Files...)
|
||||||
if newConfig.Method != nil {
|
if newConfig.Method != nil {
|
||||||
config.Method = newConfig.Method
|
config.Method = newConfig.Method
|
||||||
@@ -75,19 +75,19 @@ func (config *Config) MergeConfig(newConfig *Config) {
|
|||||||
if newConfig.SkipVerify != nil {
|
if newConfig.SkipVerify != nil {
|
||||||
config.SkipVerify = newConfig.SkipVerify
|
config.SkipVerify = newConfig.SkipVerify
|
||||||
}
|
}
|
||||||
if len(newConfig.Params) != 0 {
|
if len(newConfig.Params) != 0 { // TODO: append
|
||||||
config.Params = newConfig.Params
|
config.Params = newConfig.Params
|
||||||
}
|
}
|
||||||
if len(newConfig.Headers) != 0 {
|
if len(newConfig.Headers) != 0 { // TODO: append
|
||||||
config.Headers = newConfig.Headers
|
config.Headers = newConfig.Headers
|
||||||
}
|
}
|
||||||
if len(newConfig.Cookies) != 0 {
|
if len(newConfig.Cookies) != 0 { // TODO: append
|
||||||
config.Cookies = newConfig.Cookies
|
config.Cookies = newConfig.Cookies
|
||||||
}
|
}
|
||||||
if len(newConfig.Bodies) != 0 {
|
if len(newConfig.Bodies) != 0 { // TODO: append
|
||||||
config.Bodies = newConfig.Bodies
|
config.Bodies = newConfig.Bodies
|
||||||
}
|
}
|
||||||
if len(newConfig.Proxies) != 0 {
|
if len(newConfig.Proxies) != 0 { // TODO: append
|
||||||
config.Proxies = newConfig.Proxies
|
config.Proxies = newConfig.Proxies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -56,7 +56,7 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
Proxies: types.Proxies{},
|
Proxies: types.Proxies{},
|
||||||
}
|
}
|
||||||
|
|
||||||
config.MergeConfig(newConfig)
|
config.Merge(newConfig)
|
||||||
|
|
||||||
assert.Equal(t, "POST", *config.Method)
|
assert.Equal(t, "POST", *config.Method)
|
||||||
assert.Equal(t, newURL, config.URL)
|
assert.Equal(t, newURL, config.URL)
|
||||||
@@ -93,7 +93,7 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
DodosCount: utils.ToPtr(uint(10)),
|
DodosCount: utils.ToPtr(uint(10)),
|
||||||
}
|
}
|
||||||
|
|
||||||
config.MergeConfig(newConfig)
|
config.Merge(newConfig)
|
||||||
|
|
||||||
assert.Equal(t, "GET", *config.Method, "Method should remain unchanged")
|
assert.Equal(t, "GET", *config.Method, "Method should remain unchanged")
|
||||||
assert.Equal(t, newURL, config.URL, "URL should be updated")
|
assert.Equal(t, newURL, config.URL, "URL should be updated")
|
||||||
@@ -127,7 +127,7 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
originalConfigCopy := *config
|
originalConfigCopy := *config
|
||||||
config.MergeConfig(newConfig)
|
config.Merge(newConfig)
|
||||||
|
|
||||||
assert.Equal(t, originalConfigCopy.Method, config.Method)
|
assert.Equal(t, originalConfigCopy.Method, config.Method)
|
||||||
assert.Equal(t, originalConfigCopy.URL, config.URL)
|
assert.Equal(t, originalConfigCopy.URL, config.URL)
|
||||||
@@ -157,7 +157,7 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
Proxies: types.Proxies{},
|
Proxies: types.Proxies{},
|
||||||
}
|
}
|
||||||
|
|
||||||
config.MergeConfig(newConfig)
|
config.Merge(newConfig)
|
||||||
|
|
||||||
assert.Equal(t, []types.ConfigFile{*configFile}, config.Files, "Empty Files should not override")
|
assert.Equal(t, []types.ConfigFile{*configFile}, config.Files, "Empty Files should not override")
|
||||||
assert.Equal(t, types.Params{{Key: "original", Value: []string{"value"}}}, config.Params, "Empty Params should not override")
|
assert.Equal(t, types.Params{{Key: "original", Value: []string{"value"}}}, config.Params, "Empty Params should not override")
|
||||||
@@ -182,7 +182,7 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
Method: utils.ToPtr("POST"),
|
Method: utils.ToPtr("POST"),
|
||||||
}
|
}
|
||||||
|
|
||||||
config.MergeConfig(newConfig)
|
config.Merge(newConfig)
|
||||||
|
|
||||||
assert.Equal(t, "POST", *config.Method, "Method should be updated")
|
assert.Equal(t, "POST", *config.Method, "Method should be updated")
|
||||||
assert.Equal(t, []types.ConfigFile{*configFile1, *configFile2}, config.Files, "Files should be appended")
|
assert.Equal(t, []types.ConfigFile{*configFile1, *configFile2}, config.Files, "Files should be appended")
|
||||||
@@ -213,7 +213,7 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
Proxies: types.Proxies{},
|
Proxies: types.Proxies{},
|
||||||
}
|
}
|
||||||
|
|
||||||
config.MergeConfig(newConfig)
|
config.Merge(newConfig)
|
||||||
|
|
||||||
assert.Equal(t, "POST", *config.Method)
|
assert.Equal(t, "POST", *config.Method)
|
||||||
assert.Equal(t, newURL, config.URL)
|
assert.Equal(t, newURL, config.URL)
|
||||||
|
7
pkg/config/parser/base.go
Normal file
7
pkg/config/parser/base.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import "github.com/aykhans/dodo/pkg/config"
|
||||||
|
|
||||||
|
type IParser interface {
|
||||||
|
Parse() (*config.Config, error)
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package config
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/aykhans/dodo/pkg/config"
|
||||||
"github.com/aykhans/dodo/pkg/types"
|
"github.com/aykhans/dodo/pkg/types"
|
||||||
"github.com/aykhans/dodo/pkg/utils"
|
"github.com/aykhans/dodo/pkg/utils"
|
||||||
)
|
)
|
||||||
@@ -52,6 +53,8 @@ Flags:
|
|||||||
-x, -proxy [string] Proxy for the request (e.g. "http://proxy.example.com:8080")
|
-x, -proxy [string] Proxy for the request (e.g. "http://proxy.example.com:8080")
|
||||||
-skip-verify bool Skip SSL/TLS certificate verification (default %v)`
|
-skip-verify bool Skip SSL/TLS certificate verification (default %v)`
|
||||||
|
|
||||||
|
var _ IParser = ConfigCLIParser{}
|
||||||
|
|
||||||
type ConfigCLIParser struct {
|
type ConfigCLIParser struct {
|
||||||
args []string
|
args []string
|
||||||
}
|
}
|
||||||
@@ -79,13 +82,13 @@ func (arg *stringSliceArg) Set(value string) error {
|
|||||||
// - types.ErrCLINoArgs
|
// - types.ErrCLINoArgs
|
||||||
// - types.CLIUnexpectedArgsError
|
// - types.CLIUnexpectedArgsError
|
||||||
// - types.FieldParseErrors
|
// - types.FieldParseErrors
|
||||||
func (parser *ConfigCLIParser) Parse() (*Config, error) {
|
func (parser ConfigCLIParser) Parse() (*config.Config, error) {
|
||||||
flagSet := flag.NewFlagSet("dodo", flag.ExitOnError)
|
flagSet := flag.NewFlagSet("dodo", flag.ExitOnError)
|
||||||
|
|
||||||
flagSet.Usage = func() { parser.PrintHelp() }
|
flagSet.Usage = func() { parser.PrintHelp() }
|
||||||
|
|
||||||
var (
|
var (
|
||||||
config = &Config{}
|
config = &config.Config{}
|
||||||
configFiles = stringSliceArg{}
|
configFiles = stringSliceArg{}
|
||||||
yes bool
|
yes bool
|
||||||
skipVerify bool
|
skipVerify bool
|
||||||
@@ -259,14 +262,14 @@ func (parser *ConfigCLIParser) Parse() (*Config, error) {
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *ConfigCLIParser) PrintHelp() {
|
func (parser ConfigCLIParser) PrintHelp() {
|
||||||
fmt.Printf(
|
fmt.Printf(
|
||||||
cliUsageText+"\n",
|
cliUsageText+"\n",
|
||||||
Defaults.Yes,
|
config.Defaults.Yes,
|
||||||
Defaults.DodosCount,
|
config.Defaults.DodosCount,
|
||||||
Defaults.RequestTimeout,
|
config.Defaults.RequestTimeout,
|
||||||
Defaults.Method,
|
config.Defaults.Method,
|
||||||
Defaults.SkipVerify,
|
config.Defaults.SkipVerify,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
package config
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/aykhans/dodo/pkg/config"
|
||||||
"github.com/aykhans/dodo/pkg/types"
|
"github.com/aykhans/dodo/pkg/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -485,7 +486,7 @@ func TestConfigCLIParser_PrintHelp(t *testing.T) {
|
|||||||
assert.Contains(t, output, "-f, -config-file")
|
assert.Contains(t, output, "-f, -config-file")
|
||||||
|
|
||||||
// Verify default values are included
|
// Verify default values are included
|
||||||
assert.Contains(t, output, Defaults.Method)
|
assert.Contains(t, output, config.Defaults.Method)
|
||||||
assert.Contains(t, output, "1") // DodosCount default
|
assert.Contains(t, output, "1") // DodosCount default
|
||||||
assert.Contains(t, output, "10s") // RequestTimeout default
|
assert.Contains(t, output, "10s") // RequestTimeout default
|
||||||
assert.Contains(t, output, "false") // Yes default
|
assert.Contains(t, output, "false") // Yes default
|
236
pkg/config/parser/env.go
Normal file
236
pkg/config/parser/env.go
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aykhans/dodo/pkg/config"
|
||||||
|
"github.com/aykhans/dodo/pkg/types"
|
||||||
|
"github.com/aykhans/dodo/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ IParser = ConfigENVParser{}
|
||||||
|
|
||||||
|
type ConfigENVParser struct {
|
||||||
|
envPrefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfigENVParser(envPrefix string) *ConfigENVParser {
|
||||||
|
return &ConfigENVParser{envPrefix}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses env arguments into a Config object.
|
||||||
|
// It can return the following errors:
|
||||||
|
// - types.FieldParseErrors
|
||||||
|
func (parser ConfigENVParser) Parse() (*config.Config, error) {
|
||||||
|
var (
|
||||||
|
config = &config.Config{}
|
||||||
|
fieldParseErrors []types.FieldParseError
|
||||||
|
)
|
||||||
|
|
||||||
|
if configFile := parser.getEnv("CONFIG_FILE"); configFile != "" {
|
||||||
|
configFileParsed, err := types.ParseConfigFile(configFile)
|
||||||
|
|
||||||
|
_ = utils.HandleErrorOrDie(err,
|
||||||
|
utils.OnSentinelError(types.ErrConfigFileExtensionNotFound, func(err error) error {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("CONFIG_FILE"),
|
||||||
|
configFile,
|
||||||
|
errors.New("file extension not found"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
utils.OnCustomError(func(err types.RemoteConfigFileParseError) error {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("CONFIG_FILE"),
|
||||||
|
configFile,
|
||||||
|
fmt.Errorf("parse error: %w", err),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
utils.OnCustomError(func(err types.UnknownConfigFileTypeError) error {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("CONFIG_FILE"),
|
||||||
|
configFile,
|
||||||
|
fmt.Errorf("file type '%s' not supported (supported types: %s)", err.Type, types.ConfigFileTypeYAML),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
config.Files = append(config.Files, *configFileParsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if yes := parser.getEnv("YES"); yes != "" {
|
||||||
|
yesParsed, err := utils.ParseString[bool](yes)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("YES"),
|
||||||
|
yes,
|
||||||
|
errors.New("invalid value for boolean, expected 'true' or 'false'"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.Yes = &yesParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipVerify := parser.getEnv("SKIP_VERIFY"); skipVerify != "" {
|
||||||
|
skipVerifyParsed, err := utils.ParseString[bool](skipVerify)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("SKIP_VERIFY"),
|
||||||
|
skipVerify,
|
||||||
|
errors.New("invalid value for boolean, expected 'true' or 'false'"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.SkipVerify = &skipVerifyParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if method := parser.getEnv("METHOD"); method != "" {
|
||||||
|
config.Method = &method
|
||||||
|
}
|
||||||
|
|
||||||
|
if urlEnv := parser.getEnv("URL"); urlEnv != "" {
|
||||||
|
urlEnvParsed, err := url.Parse(urlEnv)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(parser.getFullEnvName("URL"), urlEnv, err),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.URL = urlEnvParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dodos := parser.getEnv("DODOS"); dodos != "" {
|
||||||
|
dodosParsed, err := utils.ParseString[uint](dodos)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("DODOS"),
|
||||||
|
dodos,
|
||||||
|
errors.New("invalid value for unsigned integer"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.DodosCount = &dodosParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if requests := parser.getEnv("REQUESTS"); requests != "" {
|
||||||
|
requestsParsed, err := utils.ParseString[uint](requests)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("REQUESTS"),
|
||||||
|
requests,
|
||||||
|
errors.New("invalid value for unsigned integer"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.RequestCount = &requestsParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration := parser.getEnv("DURATION"); duration != "" {
|
||||||
|
durationParsed, err := utils.ParseString[time.Duration](duration)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("DURATION"),
|
||||||
|
duration,
|
||||||
|
errors.New("invalid value duration, expected a duration string (e.g., '10s', '1h30m')"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.Duration = &durationParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if timeout := parser.getEnv("TIMEOUT"); timeout != "" {
|
||||||
|
timeoutParsed, err := utils.ParseString[time.Duration](timeout)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("TIMEOUT"),
|
||||||
|
timeout,
|
||||||
|
errors.New("invalid value duration, expected a duration string (e.g., '10s', '1h30m')"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.Timeout = &timeoutParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if param := parser.getEnv("PARAM"); param != "" {
|
||||||
|
config.Params.Parse(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header := parser.getEnv("HEADER"); header != "" {
|
||||||
|
config.Headers.Parse(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cookie := parser.getEnv("COOKIE"); cookie != "" {
|
||||||
|
config.Cookies.Parse(cookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
if body := parser.getEnv("BODY"); body != "" {
|
||||||
|
config.Bodies.Parse(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if proxy := parser.getEnv("PROXY"); proxy != "" {
|
||||||
|
err := config.Proxies.Parse(proxy)
|
||||||
|
if err != nil {
|
||||||
|
fieldParseErrors = append(
|
||||||
|
fieldParseErrors,
|
||||||
|
*types.NewFieldParseError(
|
||||||
|
parser.getFullEnvName("PROXY"),
|
||||||
|
proxy,
|
||||||
|
err,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fieldParseErrors) > 0 {
|
||||||
|
return nil, types.NewFieldParseErrors(fieldParseErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (parser ConfigENVParser) getFullEnvName(envName string) string {
|
||||||
|
if parser.envPrefix == "" {
|
||||||
|
return envName
|
||||||
|
}
|
||||||
|
return parser.envPrefix + "_" + envName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (parser ConfigENVParser) getEnv(envName string) string {
|
||||||
|
return os.Getenv(parser.getFullEnvName(envName))
|
||||||
|
}
|
1166
pkg/config/parser/env_test.go
Normal file
1166
pkg/config/parser/env_test.go
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user