@@ -15,14 +15,21 @@ import (
1515
1616var validateCmd = & cobra.Command {
1717 Use : "validate [cluster configs]" ,
18- Short : "validate checks the cluster configs using kubeval " ,
18+ Short : "validate checks the cluster configs using kubeconform and (optionally) opa policies " ,
1919 Args : cobra .MinimumNArgs (1 ),
2020 RunE : validateRun ,
2121}
2222
2323type validateFlags struct {
2424 // Expand before validating.
2525 expand bool
26+
27+ // Number of worker goroutines to use for validation.
28+ numWorkers int
29+
30+ // Paths to OPA policy rego files that will be run against kube resources.
31+ // See https://www.openpolicyagent.org/ for more details.
32+ policies []string
2633}
2734
2835var validateFlagValues validateFlags
@@ -34,6 +41,18 @@ func init() {
3441 false ,
3542 "Expand before validating" ,
3643 )
44+ validateCmd .Flags ().IntVar (
45+ & validateFlagValues .numWorkers ,
46+ "num-workers" ,
47+ 4 ,
48+ "Number of workers to use for validation" ,
49+ )
50+ validateCmd .Flags ().StringArrayVar (
51+ & validateFlagValues .policies ,
52+ "policy" ,
53+ []string {},
54+ "Paths to OPA policies" ,
55+ )
3756
3857 RootCmd .AddCommand (validateCmd )
3958}
@@ -88,43 +107,75 @@ func validateClusterPath(ctx context.Context, path string) error {
88107func execValidation (ctx context.Context , clusterConfig * config.ClusterConfig ) error {
89108 log .Infof ("Validating cluster %s" , clusterConfig .DescriptiveName ())
90109
91- kubeValidator , err := validation .NewKubeValidator ()
110+ kubeconformChecker , err := validation .NewKubeconformChecker ()
92111 if err != nil {
93112 return err
94113 }
95114
115+ policies , err := validation .DefaultPoliciesFromGlobs (ctx , validateFlagValues .policies )
116+ if err != nil {
117+ return err
118+ }
119+
120+ checkers := []validation.Checker {kubeconformChecker }
121+ for _ , policy := range policies {
122+ checkers = append (checkers , policy )
123+ }
124+
125+ validator := validation .NewKubeValidator (
126+ validation.KubeValidatorConfig {
127+ NumWorkers : validateFlagValues .numWorkers ,
128+ Checkers : checkers ,
129+ },
130+ )
131+
96132 log .Infof ("Running kubeconform on configs in %+v" , clusterConfig .AbsSubpaths ())
97- results , err := kubeValidator . RunValidation (ctx , clusterConfig .AbsSubpaths ()[0 ])
133+ results , err := validator . RunChecks (ctx , clusterConfig .AbsSubpaths ()[0 ])
98134 if err != nil {
99135 return err
100136 }
101137
102138 numInvalidResources := 0
103139
104140 for _ , result := range results {
105- switch result .SchemaStatus {
106- case validation .StatusValid :
107- log .Infof ("Resource %s in file %s OK" , result .PrettyName (), result .Filename )
108- case validation .StatusSkipped :
109- log .Debugf ("Resource %s in file %s was skipped" , result .PrettyName (), result .Filename )
110- case validation .StatusError :
111- numInvalidResources ++
112- log .Errorf (
113- "File %s could not be validated: %+v" ,
114- result .Filename ,
115- result .SchemaMessage ,
116- )
117- case validation .StatusInvalid :
118- numInvalidResources ++
119- log .Errorf (
120- "Resource %s in file %s is invalid: %s" ,
121- result .PrettyName (),
122- result .Filename ,
123- result .SchemaMessage ,
124- )
125- case validation .StatusEmpty :
126- default :
127- log .Infof ("Unrecognized result type: %+v" , result )
141+ for _ , checkResult := range result .CheckResults {
142+ switch checkResult .Status {
143+ case validation .StatusValid :
144+ log .Debugf (
145+ "Resource %s in file %s OK according to check %s" ,
146+ result .Resource .PrettyName (),
147+ result .Resource .Path ,
148+ checkResult .CheckName ,
149+ )
150+ case validation .StatusSkipped :
151+ log .Debugf (
152+ "Resource %s in file %s was skipped by check %s" ,
153+ result .Resource .PrettyName (),
154+ result .Resource .Path ,
155+ checkResult .CheckName ,
156+ )
157+ case validation .StatusError :
158+ numInvalidResources ++
159+ log .Errorf (
160+ "Resource %s in file %s could not be processed by check %s: %s" ,
161+ result .Resource .PrettyName (),
162+ result .Resource .Path ,
163+ checkResult .CheckName ,
164+ checkResult .Message ,
165+ )
166+ case validation .StatusInvalid :
167+ numInvalidResources ++
168+ log .Errorf (
169+ "Resource %s in file %s is invalid according to check %s: %s" ,
170+ result .Resource .PrettyName (),
171+ result .Resource .Path ,
172+ checkResult .CheckName ,
173+ checkResult .Message ,
174+ )
175+ case validation .StatusEmpty :
176+ default :
177+ log .Infof ("Unrecognized result type: %+v" , result )
178+ }
128179 }
129180 }
130181
0 commit comments