diff --git a/pkg/config/schema.go b/pkg/config/schema.go index 98257d1a..9ddd3463 100644 --- a/pkg/config/schema.go +++ b/pkg/config/schema.go @@ -4,13 +4,16 @@ import ( "bytes" "encoding/json" "fmt" + "io" "strings" "text/template" "github.com/qri-io/jsonschema" "github.com/thoas/go-funk" + "gopkg.in/yaml.v3" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + k8sYaml "k8s.io/apimachinery/pkg/util/yaml" ) // TargetKind represents the part of the config to be validated @@ -49,6 +52,25 @@ type SchemaCheck struct { type resourceMinimum string type resourceMaximum string +func ParseCheck(rawBytes []byte) (SchemaCheck, error) { + fmt.Println("parse", string(rawBytes)) + reader := bytes.NewReader(rawBytes) + check := SchemaCheck{} + d := k8sYaml.NewYAMLOrJSONDecoder(reader, 4096) + for { + if err := d.Decode(&check); err != nil { + if err == io.EOF { + return check, nil + } + return check, fmt.Errorf("Decoding schema check failed: %v", err) + } + } +} + +func (check *SchemaCheck) MarshalYAML() (interface{}, error) { + return nil +} + func init() { jsonschema.RegisterValidator("resourceMinimum", newResourceMinimum) jsonschema.RegisterValidator("resourceMaximum", newResourceMaximum) @@ -127,7 +149,6 @@ func validateRange(path string, limit interface{}, data interface{}, isMinimum b // Initialize sets up the schema func (check *SchemaCheck) Initialize(id string) error { - fmt.Println("init", id, check.JSONSchema, check.Schema) check.ID = id if check.JSONSchema != "" { if err := json.Unmarshal([]byte(check.JSONSchema), &check.Schema); err != nil { @@ -137,29 +158,34 @@ func (check *SchemaCheck) Initialize(id string) error { return nil } -func (check SchemaCheck) TemplateForResource(res interface{}) (SchemaCheck, error) { - newCheck := check - var tmpl *template.Template - var err error - tmpl = template.New(check.ID) - yaml, err := yaml.Marshal() - fmt.Println("json sch", check.JSONSchema) - tmpl, err = tmpl.Parse(check.JSONSchema) +func (check SchemaCheck) TemplateForResource(res interface{}) (*SchemaCheck, error) { + yamlBytes, err := yaml.Marshal(check.Schema) if err != nil { - return newCheck, err + return nil, err } + + tmpl := template.New(check.ID) + tmpl, err = tmpl.Parse(string(yamlBytes)) + if err != nil { + return nil, err + } + w := bytes.Buffer{} err = tmpl.Execute(&w, res) if err != nil { - return newCheck, err + return nil, err + } + newCheck, err := ParseCheck(w.Bytes()) + fmt.Println("parse check") + if err != nil { + fmt.Println("err", err) + return nil, err } - fmt.Println("templated", w.String()) - newCheck.JSONSchema = w.String() err = newCheck.Initialize(check.ID) if err != nil { - return newCheck, err + return nil, err } - return newCheck, nil + return &newCheck, nil } // CheckPod checks a pod spec against the schema diff --git a/pkg/validator/schema.go b/pkg/validator/schema.go index fd32419d..b85cd582 100644 --- a/pkg/validator/schema.go +++ b/pkg/validator/schema.go @@ -1,16 +1,13 @@ package validator import ( - "bytes" "fmt" - "io" "sort" "strings" "github.com/gobuffalo/packr/v2" corev1 "k8s.io/api/core/v1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/yaml" "github.com/fairwindsops/polaris/pkg/config" "github.com/fairwindsops/polaris/pkg/kube" @@ -66,29 +63,15 @@ func init() { if err != nil { panic(err) } - check, err := parseCheck(contents) + check, err := config.ParseCheck(contents) if err != nil { panic(err) } - check.ID = checkID + check.Initialize(checkID) builtInChecks[checkID] = check } } -func parseCheck(rawBytes []byte) (config.SchemaCheck, error) { - reader := bytes.NewReader(rawBytes) - check := config.SchemaCheck{} - d := yaml.NewYAMLOrJSONDecoder(reader, 4096) - for { - if err := d.Decode(&check); err != nil { - if err == io.EOF { - return check, nil - } - return check, fmt.Errorf("Decoding schema check failed: %v", err) - } - } -} - func resolveCheck(conf *config.Configuration, checkID string, test schemaTestCase) (*config.SchemaCheck, error) { if !conf.DisallowExemptions && hasExemptionAnnotation(test.Resource.ObjectMeta, checkID) { return nil, nil @@ -111,11 +94,11 @@ func resolveCheck(conf *config.Configuration, checkID string, test schemaTestCas if !check.IsActionable(test.Target, test.Resource.Kind, test.IsInitContianer) { return nil, nil } - check, err := check.TemplateForResource(test.Resource.Resource.Object) + checkPtr, err := check.TemplateForResource(test.Resource.Resource.Object) if err != nil { return nil, err } - return &check, nil + return checkPtr, nil } func makeResult(conf *config.Configuration, check *config.SchemaCheck, passes bool) ResultMessage { diff --git a/test/checks_test.go b/test/checks_test.go index 741b1148..38086ed3 100644 --- a/test/checks_test.go +++ b/test/checks_test.go @@ -61,9 +61,13 @@ func TestChecks(t *testing.T) { panic(err) } c, err := config.Parse([]byte("checks:\n " + tc.check + ": danger")) - assert.NoError(t, err) + if err != nil { + panic(err) + } result, err := validator.ApplyAllSchemaChecks(&c, res) - assert.NoError(t, err) + if err != nil { + panic(err) + } summary := result.GetSummary() total := summary.Successes + summary.Dangers msg := fmt.Sprintf("Check %s ran %d times instead of 1", tc.check, total)