Skip to content

Commit

Permalink
Merge pull request #331 from gatewayd-io/lint-on-run
Browse files Browse the repository at this point in the history
Lint on run
  • Loading branch information
mostafa authored Sep 24, 2023
2 parents 5732a59 + ea6cf0e commit 97723e4
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 17 deletions.
6 changes: 5 additions & 1 deletion cmd/config_lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
},
}

Expand Down
6 changes: 5 additions & 1 deletion cmd/plugin_lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
},
}

Expand Down
19 changes: 19 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
// https://github.com/gatewayd-io/gatewayd/issues/324
var (
enableTracing bool
enableLinting bool
collectorURL string
enableSentry bool
devMode bool
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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")
}
23 changes: 11 additions & 12 deletions cmd/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const (
ErrCodeDuplicateMetricsCollector
ErrCodeInvalidMetricType
ErrCodeValidationFailed
ErrCodeLintingFailed
)

var (
Expand Down Expand Up @@ -104,6 +105,8 @@ var (

ErrValidationFailed = NewGatewayDError(
ErrCodeValidationFailed, "validation failed", nil)
ErrLintingFailed = NewGatewayDError(
ErrCodeLintingFailed, "linting failed", nil)
)

const (
Expand Down
4 changes: 2 additions & 2 deletions network/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})

Expand Down Expand Up @@ -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,
})

Expand Down
2 changes: 1 addition & 1 deletion network/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
})
Expand Down

0 comments on commit 97723e4

Please sign in to comment.