Files
dodo/pkg/config/parser/env.go
2025-09-04 22:43:52 +04:00

237 lines
5.6 KiB
Go

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))
}