config: remove remote config files (#1877)

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
Signed-off-by: Jan-Otto Kröpke <github@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2025-03-13 16:45:39 +01:00
committed by GitHub
parent 3f2633d0b0
commit eceec10237
3 changed files with 58 additions and 110 deletions

View File

@@ -71,10 +71,6 @@ func run() int {
"config.file", "config.file",
"YAML configuration file to use. Values set in this file will be overridden by CLI flags.", "YAML configuration file to use. Values set in this file will be overridden by CLI flags.",
).String() ).String()
insecureSkipVerify = app.Flag(
"config.file.insecure-skip-verify",
"Skip TLS verification in loading YAML configuration.",
).Default("false").Bool()
webConfig = webflag.AddFlags(app, ":9182") webConfig = webflag.AddFlags(app, ":9182")
metricsPath = app.Flag( metricsPath = app.Flag(
"telemetry.path", "telemetry.path",
@@ -122,11 +118,9 @@ func run() int {
// Initialize collectors before loading and parsing CLI arguments // Initialize collectors before loading and parsing CLI arguments
collectors := collector.NewWithFlags(app) collectors := collector.NewWithFlags(app)
// Load values from configuration file(s). Executable flags must first be parsed, in order if err := config.Parse(app, os.Args[1:]); err != nil {
// to load the specified file(s).
if _, err := app.Parse(os.Args[1:]); err != nil {
//nolint:sloglint // we do not have an logger yet //nolint:sloglint // we do not have an logger yet
slog.Error("Failed to parse CLI args", slog.Error("Failed to load configuration",
slog.Any("err", err), slog.Any("err", err),
) )
@@ -145,52 +139,12 @@ func run() int {
return 1 return 1
} }
if *configFile != "" {
resolver, err := config.NewResolver(ctx, *configFile, logger, *insecureSkipVerify)
if err != nil {
logger.Error("could not load config file",
slog.Any("err", err),
)
return 1
}
if err = resolver.Bind(app, os.Args[1:]); err != nil {
logger.ErrorContext(ctx, "failed to bind configuration",
slog.Any("err", err),
)
return 1
}
// Parse flags once more to include those discovered in configuration file(s).
if _, err = app.Parse(os.Args[1:]); err != nil {
logger.ErrorContext(ctx, "failed to parse CLI args from YAML file",
slog.Any("err", err),
)
return 1
}
// NOTE: This is temporary fix for issue #1092, calling kingpin.Parse
// twice makes slices flags duplicate its value, this clean up
// the first parse before the second call.
slices.Sort(*webConfig.WebListenAddresses)
*webConfig.WebListenAddresses = slices.Clip(slices.Compact(*webConfig.WebListenAddresses))
logger, err = log.New(logConfig)
if err != nil {
//nolint:sloglint // we do not have an logger yet
slog.Error("failed to create logger",
slog.Any("err", err),
)
return 1
}
}
logger.LogAttrs(ctx, slog.LevelDebug, "logging has Started") logger.LogAttrs(ctx, slog.LevelDebug, "logging has Started")
if configFile != nil && *configFile != "" {
logger.InfoContext(ctx, "using configuration file: "+*configFile)
}
if err = setPriorityWindows(logger, os.Getpid(), *processPriority); err != nil { if err = setPriorityWindows(logger, os.Getpid(), *processPriority); err != nil {
logger.Error("failed to set process priority", logger.Error("failed to set process priority",
slog.Any("err", err), slog.Any("err", err),

View File

@@ -115,10 +115,9 @@
<SetProperty Id="ExtraFlags" After="InstallFiles" Sequence="execute" Value="[EXTRA_FLAGS]" Condition="EXTRA_FLAGS" /> <SetProperty Id="ExtraFlags" After="InstallFiles" Sequence="execute" Value="[EXTRA_FLAGS]" Condition="EXTRA_FLAGS" />
<Property Id="CONFIG_FILE" Secure="yes" Value="config.yaml" /> <Property Id="CONFIG_FILE" Secure="yes" Value="config.yaml" />
<SetProperty Id="ConfigFile_Remote" After="InstallFiles" Sequence="execute" Value="[CONFIG_FILE]" Condition="CONFIG_FILE AND (CONFIG_FILE&lt;&lt;&quot;http://&quot; OR CONFIG_FILE&lt;&lt;&quot;https://&quot;)" /> <SetProperty Id="ConfigFile_NonDefault" After="InstallFiles" Sequence="execute" Value="[CONFIG_FILE]" Condition="CONFIG_FILE AND CONFIG_FILE&lt;&gt;&quot;config.yaml&quot;" />
<SetProperty Id="ConfigFile_NonDefault" After="InstallFiles" Sequence="execute" Value="[CONFIG_FILE]" Condition="CONFIG_FILE AND CONFIG_FILE&lt;&gt;&quot;config.yaml&quot; AND NOT (CONFIG_FILE&lt;&lt;&quot;http://&quot; OR CONFIG_FILE&lt;&lt;&quot;https://&quot;)" />
<SetProperty Id="ConfigFile_Default" After="InstallFiles" Sequence="execute" Value="[APPLICATIONFOLDER]config.yaml" Condition="CONFIG_FILE=&quot;config.yaml&quot;" /> <SetProperty Id="ConfigFile_Default" After="InstallFiles" Sequence="execute" Value="[APPLICATIONFOLDER]config.yaml" Condition="CONFIG_FILE=&quot;config.yaml&quot;" />
<SetProperty Id="ConfigFileFlag" After="InstallFiles" Sequence="execute" Value="--config.file=&quot;[ConfigFile_Remote][ConfigFile_NonDefault][ConfigFile_Default]&quot;" Condition="ConfigFile_Remote OR ConfigFile_NonDefault OR ConfigFile_Default" /> <SetProperty Id="ConfigFileFlag" After="InstallFiles" Sequence="execute" Value="--config.file=&quot;[ConfigFile_NonDefault][ConfigFile_Default]&quot;" Condition="ConfigFile_NonDefault OR ConfigFile_Default" />
<Property Id="LISTEN_PORT" Secure="yes" Value="9182" /> <Property Id="LISTEN_PORT" Secure="yes" Value="9182" />
<SetProperty Id="ListenFlag" After="InstallFiles" Sequence="execute" Value="--web.listen-address [LISTEN_ADDR]:[LISTEN_PORT]" Condition="LISTEN_ADDR&lt;&gt;&quot;&quot; OR LISTEN_PORT&lt;&gt;9182" /> <SetProperty Id="ListenFlag" After="InstallFiles" Sequence="execute" Value="--web.listen-address [LISTEN_ADDR]:[LISTEN_PORT]" Condition="LISTEN_ADDR&lt;&gt;&quot;&quot; OR LISTEN_PORT&lt;&gt;9182" />

View File

@@ -16,12 +16,7 @@
package config package config
import ( import (
"context"
"crypto/tls"
"fmt" "fmt"
"io"
"log/slog"
"net/http"
"os" "os"
"strings" "strings"
@@ -38,8 +33,52 @@ type Resolver struct {
flags map[string]string flags map[string]string
} }
// NewResolver returns a Resolver structure. // Parse parses the command line arguments and configuration files.
func NewResolver(ctx context.Context, file string, logger *slog.Logger, insecureSkipVerify bool) (*Resolver, error) { func Parse(app *kingpin.Application, args []string) error {
configFile := ParseConfigFile(args)
if configFile != "" {
resolver, err := NewConfigFileResolver(configFile)
if err != nil {
return fmt.Errorf("failed to load configuration file: %w", err)
}
if err = resolver.Bind(app, args); err != nil {
return fmt.Errorf("failed to bind configuration: %w", err)
}
}
if _, err := app.Parse(args); err != nil {
return fmt.Errorf("failed to parse flags: %w", err)
}
return nil
}
// ParseConfigFile manually parses the configuration file from the command line arguments.
func ParseConfigFile(args []string) string {
for i, cliFlag := range args {
if strings.HasPrefix(cliFlag, "--config.file=") {
return strings.TrimPrefix(cliFlag, "--config.file=")
}
if strings.HasPrefix(cliFlag, "-config.file=") {
return strings.TrimPrefix(cliFlag, "-config.file=")
}
if strings.HasSuffix(cliFlag, "-config.file") {
if len(os.Args) <= i+1 {
return ""
}
return os.Args[i+1]
}
}
return ""
}
// NewConfigFileResolver returns a Resolver structure.
func NewConfigFileResolver(file string) (*Resolver, error) {
flags := map[string]string{} flags := map[string]string{}
var ( var (
@@ -47,18 +86,9 @@ func NewResolver(ctx context.Context, file string, logger *slog.Logger, insecure
fileBytes []byte fileBytes []byte
) )
if strings.HasPrefix(file, "http://") || strings.HasPrefix(file, "https://") { fileBytes, err = readFromFile(file)
logger.WarnContext(ctx, "Loading configuration file from URL is deprecated and will be removed in 0.31.0. Use a local file instead.") if err != nil {
return nil, err
fileBytes, err = readFromURL(ctx, file, logger, insecureSkipVerify)
if err != nil {
return nil, err
}
} else {
fileBytes, err = readFromFile(ctx, file, logger)
if err != nil {
return nil, err
}
} }
var rawValues map[string]interface{} var rawValues map[string]interface{}
@@ -79,9 +109,7 @@ func NewResolver(ctx context.Context, file string, logger *slog.Logger, insecure
return &Resolver{flags: flags}, nil return &Resolver{flags: flags}, nil
} }
func readFromFile(ctx context.Context, file string, logger *slog.Logger) ([]byte, error) { func readFromFile(file string) ([]byte, error) {
logger.InfoContext(ctx, "loading configuration file: "+file)
if _, err := os.Stat(file); err != nil { if _, err := os.Stat(file); err != nil {
return nil, fmt.Errorf("failed to read configuration file: %w", err) return nil, fmt.Errorf("failed to read configuration file: %w", err)
} }
@@ -94,39 +122,6 @@ func readFromFile(ctx context.Context, file string, logger *slog.Logger) ([]byte
return fileBytes, nil return fileBytes, nil
} }
func readFromURL(ctx context.Context, file string, logger *slog.Logger, insecureSkipVerify bool) ([]byte, error) {
logger.InfoContext(ctx, "loading configuration file from URL: "+file)
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify}, //nolint:gosec
}
if insecureSkipVerify {
logger.WarnContext(ctx, "Loading configuration file with TLS verification disabled")
}
client := &http.Client{Transport: tr}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, file, nil)
if err != nil {
return nil, fmt.Errorf("failed to create HTTP request: %w", err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to read configuration file from URL: %w", err)
}
defer resp.Body.Close()
fileBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return fileBytes, nil
}
func (c *Resolver) setDefault(v getFlagger) { func (c *Resolver) setDefault(v getFlagger) {
for name, value := range c.flags { for name, value := range c.flags {
f := v.GetFlag(name) f := v.GetFlag(name)