From 903519468862f58269e4184181a09f0a0690df9a Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Sun, 24 Sep 2023 12:08:41 +0200 Subject: [PATCH 1/3] Increase log level to disable logging when testing --- network/proxy_test.go | 4 ++-- network/server_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/network/proxy_test.go b/network/proxy_test.go index 770cada6..6b680193 100644 --- a/network/proxy_test.go +++ b/network/proxy_test.go @@ -19,7 +19,7 @@ func TestNewProxy(t *testing.T) { Output: []config.LogOutput{config.Console}, TimeFormat: zerolog.TimeFormatUnix, ConsoleTimeFormat: time.RFC3339, - Level: zerolog.DebugLevel, + Level: zerolog.WarnLevel, NoColor: true, }) @@ -82,7 +82,7 @@ func TestNewProxyElastic(t *testing.T) { Output: []config.LogOutput{config.Console}, TimeFormat: zerolog.TimeFormatUnix, ConsoleTimeFormat: time.RFC3339, - Level: zerolog.DebugLevel, + Level: zerolog.WarnLevel, NoColor: true, }) diff --git a/network/server_test.go b/network/server_test.go index 94a85139..676e9cb6 100644 --- a/network/server_test.go +++ b/network/server_test.go @@ -31,7 +31,7 @@ func TestRunServer(t *testing.T) { }, TimeFormat: zerolog.TimeFormatUnix, ConsoleTimeFormat: time.RFC3339, - Level: zerolog.DebugLevel, + Level: zerolog.WarnLevel, NoColor: true, FileName: "server_test.log", }) From 2c8dde6f2dd751cca56171bf950cb3ad5a66c353 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Sun, 24 Sep 2023 12:10:27 +0200 Subject: [PATCH 2/3] Refactor lintConfig to return an error --- cmd/config_lint.go | 6 +++++- cmd/plugin_lint.go | 6 +++++- cmd/utils.go | 23 +++++++++++------------ errors/errors.go | 3 +++ 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/cmd/config_lint.go b/cmd/config_lint.go index a4a18fb5..9c4eb5d2 100644 --- a/cmd/config_lint.go +++ b/cmd/config_lint.go @@ -31,7 +31,11 @@ var configLintCmd = &cobra.Command{ defer sentry.Recover() } - lintConfig(cmd, Global, globalConfigFile) + if err := lintConfig(Global, globalConfigFile); err != nil { + log.Fatal(err) + } + + cmd.Println("global config is valid") }, } diff --git a/cmd/plugin_lint.go b/cmd/plugin_lint.go index d86b968b..b0dfae26 100644 --- a/cmd/plugin_lint.go +++ b/cmd/plugin_lint.go @@ -31,7 +31,11 @@ var pluginLintCmd = &cobra.Command{ defer sentry.Recover() } - lintConfig(cmd, Plugins, pluginConfigFile) + if err := lintConfig(Plugins, pluginConfigFile); err != nil { + log.Fatal(err) + } + + cmd.Println("plugins config is valid") }, } diff --git a/cmd/utils.go b/cmd/utils.go index 05e459b8..fc304348 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -16,6 +16,7 @@ import ( "strings" "github.com/gatewayd-io/gatewayd/config" + gerr "github.com/gatewayd-io/gatewayd/errors" "github.com/google/go-github/v53/github" jsonSchemaGenerator "github.com/invopop/jsonschema" "github.com/knadh/koanf" @@ -92,9 +93,7 @@ func generateConfig( cmd.Printf("Config file '%s' was %s successfully.", configFile, verb) } -func lintConfig(cmd *cobra.Command, fileType configFileType, configFile string) { - logger := log.New(cmd.OutOrStdout(), "", 0) - +func lintConfig(fileType configFileType, configFile string) error { // Load the config file and check it for errors. var conf *config.Config switch fileType { @@ -109,7 +108,7 @@ func lintConfig(cmd *cobra.Command, fileType configFileType, configFile string) conf.LoadPluginConfigFile(context.TODO()) conf.UnmarshalPluginConfig(context.TODO()) default: - logger.Fatal("Invalid config file type") + return gerr.ErrLintingFailed } // Marshal the config to JSON. @@ -121,17 +120,17 @@ func lintConfig(cmd *cobra.Command, fileType configFileType, configFile string) case Plugins: jsonData, err = conf.PluginKoanf.Marshal(koanfJson.Parser()) default: - logger.Fatal("Invalid config file type") + return gerr.ErrLintingFailed } if err != nil { - logger.Fatalf("Error marshalling %s config to JSON: %s\n", string(fileType), err) + return gerr.ErrLintingFailed.Wrap(err) } // Unmarshal the JSON data into a map. var jsonBytes map[string]interface{} err = json.Unmarshal(jsonData, &jsonBytes) if err != nil { - logger.Fatal("Error unmarshalling schema to JSON:\n", err) + return gerr.ErrLintingFailed.Wrap(err) } // Generate a JSON schema from the config struct. @@ -142,28 +141,28 @@ func lintConfig(cmd *cobra.Command, fileType configFileType, configFile string) case Plugins: generatedSchema = jsonSchemaGenerator.Reflect(&config.PluginConfig{}) default: - logger.Fatal("Invalid config file type") + return gerr.ErrLintingFailed } // Marshal the schema to JSON. schemaBytes, err := json.Marshal(generatedSchema) if err != nil { - logger.Fatal("Error marshalling schema to JSON:\n", err) + return gerr.ErrLintingFailed.Wrap(err) } // Compile the schema for validation. schema, err := jsonSchemaV5.CompileString("", string(schemaBytes)) if err != nil { - logger.Fatal("Error compiling schema:\n", err) + return gerr.ErrLintingFailed.Wrap(err) } // Validate the config against the schema. err = schema.Validate(jsonBytes) if err != nil { - logger.Fatalf("Error validating %s config: %s\n", string(fileType), err) + return gerr.ErrLintingFailed.Wrap(err) } - cmd.Printf("%s config is valid\n", fileType) + return nil } func listPlugins(cmd *cobra.Command, pluginConfigFile string, onlyEnabled bool) { diff --git a/errors/errors.go b/errors/errors.go index 89f6c69d..d884d184 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -32,6 +32,7 @@ const ( ErrCodeDuplicateMetricsCollector ErrCodeInvalidMetricType ErrCodeValidationFailed + ErrCodeLintingFailed ) var ( @@ -104,6 +105,8 @@ var ( ErrValidationFailed = NewGatewayDError( ErrCodeValidationFailed, "validation failed", nil) + ErrLintingFailed = NewGatewayDError( + ErrCodeLintingFailed, "linting failed", nil) ) const ( From ea6cf0ec5dbc98bf0f3f8fefb6485cb41c93bd19 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian Date: Sun, 24 Sep 2023 12:11:04 +0200 Subject: [PATCH 3/3] Lint global and plugins config on run --- cmd/run.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cmd/run.go b/cmd/run.go index 8f006040..052fd8f9 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -45,6 +45,7 @@ import ( // https://github.com/gatewayd-io/gatewayd/issues/324 var ( enableTracing bool + enableLinting bool collectorURL string enableSentry bool devMode bool @@ -168,6 +169,22 @@ var runCmd = &cobra.Command{ defer sentry.Recover() } + // Lint the configuration files before loading them. + if enableLinting { + _, span := otel.Tracer(config.TracerName).Start(runCtx, "Lint configuration files") + defer span.End() + + // Lint the global configuration file and fail if it's not valid. + if err := lintConfig(Global, globalConfigFile); err != nil { + log.Fatal(err) + } + + // Lint the plugin configuration file and fail if it's not valid. + if err := lintConfig(Plugins, pluginConfigFile); err != nil { + log.Fatal(err) + } + } + // Load global and plugin configuration. conf = config.NewConfig(runCtx, globalConfigFile, pluginConfigFile) conf.InitConfig(runCtx) @@ -775,4 +792,6 @@ func init() { &enableSentry, "sentry", true, "Enable Sentry") runCmd.Flags().BoolVar( &enableUsageReport, "usage-report", true, "Enable usage report") + runCmd.Flags().BoolVar( + &enableLinting, "lint", true, "Enable linting of configuration files") }