mirror of
https://github.com/FairwindsOps/polaris.git
synced 2026-05-20 08:04:58 +00:00
more progress
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user