@@ -2,12 +2,16 @@ package cmd
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"log"
6
7
"os"
7
8
8
9
"github.com/gatewayd-io/gatewayd/config"
10
+ jsonSchemaGenerator "github.com/invopop/jsonschema"
9
11
"github.com/knadh/koanf"
12
+ koanfJson "github.com/knadh/koanf/parsers/json"
10
13
"github.com/knadh/koanf/parsers/yaml"
14
+ jsonSchemaV5 "github.com/santhosh-tekuri/jsonschema/v5"
11
15
"github.com/spf13/cobra"
12
16
)
13
17
16
20
)
17
21
18
22
var (
19
- Global configFileType = "global"
20
- Plugin configFileType = "plugin "
23
+ Global configFileType = "global"
24
+ Plugins configFileType = "plugins "
21
25
)
22
26
23
27
// generateConfig generates a config file of the given type.
@@ -36,7 +40,7 @@ func generateConfig(cmd *cobra.Command, fileType configFileType, configFile stri
36
40
switch fileType {
37
41
case Global :
38
42
konfig = conf .GlobalKoanf
39
- case Plugin :
43
+ case Plugins :
40
44
konfig = conf .PluginKoanf
41
45
default :
42
46
logger .Fatal ("Invalid config file type" )
@@ -65,3 +69,77 @@ func generateConfig(cmd *cobra.Command, fileType configFileType, configFile stri
65
69
}
66
70
logger .Printf ("Config file '%s' was %s successfully." , configFile , verb )
67
71
}
72
+
73
+ func lintConfig (cmd * cobra.Command , fileType configFileType , configFile string ) {
74
+ logger := log .New (cmd .OutOrStdout (), "" , 0 )
75
+
76
+ // Load the config file and check it for errors.
77
+ var conf * config.Config
78
+ switch fileType {
79
+ case Global :
80
+ conf = config .NewConfig (context .TODO (), configFile , "" )
81
+ conf .LoadDefaults (context .TODO ())
82
+ conf .LoadGlobalConfigFile (context .TODO ())
83
+ conf .UnmarshalGlobalConfig (context .TODO ())
84
+ case Plugins :
85
+ conf = config .NewConfig (context .TODO (), "" , configFile )
86
+ conf .LoadDefaults (context .TODO ())
87
+ conf .LoadPluginConfigFile (context .TODO ())
88
+ conf .UnmarshalPluginConfig (context .TODO ())
89
+ default :
90
+ logger .Fatal ("Invalid config file type" )
91
+ }
92
+
93
+ // Marshal the config to JSON.
94
+ var jsonData []byte
95
+ var err error
96
+ switch fileType {
97
+ case Global :
98
+ jsonData , err = conf .GlobalKoanf .Marshal (koanfJson .Parser ())
99
+ case Plugins :
100
+ jsonData , err = conf .PluginKoanf .Marshal (koanfJson .Parser ())
101
+ default :
102
+ logger .Fatal ("Invalid config file type" )
103
+ }
104
+ if err != nil {
105
+ logger .Fatalf ("Error marshalling %s config to JSON: %s\n " , string (fileType ), err )
106
+ }
107
+
108
+ // Unmarshal the JSON data into a map.
109
+ var jsonBytes map [string ]interface {}
110
+ err = json .Unmarshal (jsonData , & jsonBytes )
111
+ if err != nil {
112
+ logger .Fatal ("Error unmarshalling schema to JSON:\n " , err )
113
+ }
114
+
115
+ // Generate a JSON schema from the config struct.
116
+ var generatedSchema * jsonSchemaGenerator.Schema
117
+ switch fileType {
118
+ case Global :
119
+ generatedSchema = jsonSchemaGenerator .Reflect (& config.GlobalConfig {})
120
+ case Plugins :
121
+ generatedSchema = jsonSchemaGenerator .Reflect (& config.PluginConfig {})
122
+ default :
123
+ logger .Fatal ("Invalid config file type" )
124
+ }
125
+
126
+ // Marshal the schema to JSON.
127
+ schemaBytes , err := json .Marshal (generatedSchema )
128
+ if err != nil {
129
+ logger .Fatal ("Error marshalling schema to JSON:\n " , err )
130
+ }
131
+
132
+ // Compile the schema for validation.
133
+ schema , err := jsonSchemaV5 .CompileString ("" , string (schemaBytes ))
134
+ if err != nil {
135
+ logger .Fatal ("Error compiling schema:\n " , err )
136
+ }
137
+
138
+ // Validate the config against the schema.
139
+ err = schema .Validate (jsonBytes )
140
+ if err != nil {
141
+ logger .Fatalf ("Error validating %s config: %s\n " , string (fileType ), err )
142
+ }
143
+
144
+ logger .Printf ("%s config is valid\n " , fileType )
145
+ }
0 commit comments