From 477feb4de819604367a904f4dffbd39b34d9745b Mon Sep 17 00:00:00 2001 From: Abdalaziz Ali Date: Tue, 16 May 2023 05:58:37 +0200 Subject: [PATCH 1/2] feat: convert the output error to yaml --- main.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 335dc70..bce2131 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" + yamltojson "sigs.k8s.io/yaml" ) // @@ -96,9 +97,11 @@ func (kcv *KubeconformValidator) Filter(rlItems []*yaml.RNode) ([]*yaml.RNode, e kc.loadResourceListItems(rlItems) cfg, out := kc.configure(&kcv.Spec) - // Run Kubeconform validate. + // Run Kubeconform validate + // and convert kc.IO stream to YAML. if err := kubeconform.Validate(cfg, out); err != nil { - return nil, errors.Wrap(errors.Errorf("Kubeconform validation output: %s", kc.IO)) + outYAML, _ := yamltojson.JSONToYAML(kc.IO.(*bytes.Buffer).Bytes()) + return nil, errors.WrapPrefixf(err, "Kubeconform validation failed: %s", string(outYAML)) } return rlItems, nil From 031ad01eb745322a862a12562155275266af99ad Mon Sep 17 00:00:00 2001 From: Abdalaziz Ali Date: Thu, 15 Jun 2023 21:32:35 +0200 Subject: [PATCH 2/2] feat: convert output to framework.Result format --- example/krm-function-input.yaml | 10 ++++++ main.go | 60 +++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/example/krm-function-input.yaml b/example/krm-function-input.yaml index de3a4c0..9a0f9fe 100644 --- a/example/krm-function-input.yaml +++ b/example/krm-function-input.yaml @@ -25,6 +25,16 @@ items: - protocol: TCP port: 8666s targetPort: 8080 +- kind: Service + apiVersion: v1 + metadata: + name: service2-invalid + spec: + type: ClusterIP + ports: + - protocol: TCP + port: 8666x + targetPort: 8080 - kind: Service apiVersion: v1 metadata: diff --git a/main.go b/main.go index bce2131..b0cf2da 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,9 @@ package main import ( "bytes" _ "embed" + "encoding/json" "io" + "io/ioutil" "log" "os" @@ -16,7 +18,6 @@ import ( "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" - yamltojson "sigs.k8s.io/yaml" ) // @@ -92,18 +93,65 @@ func (kcv *KubeconformValidator) Validate() error { // return nil // } +// write Filter fun to validate resource list items and in case if error, +// read the kc.IO json output and map it to results in framework.Results func (kcv *KubeconformValidator) Filter(rlItems []*yaml.RNode) ([]*yaml.RNode, error) { kc := &Kubeconform{IO: &bytes.Buffer{}} kc.loadResourceListItems(rlItems) cfg, out := kc.configure(&kcv.Spec) - // Run Kubeconform validate - // and convert kc.IO stream to YAML. - if err := kubeconform.Validate(cfg, out); err != nil { - outYAML, _ := yamltojson.JSONToYAML(kc.IO.(*bytes.Buffer).Bytes()) - return nil, errors.WrapPrefixf(err, "Kubeconform validation failed: %s", string(outYAML)) + type validationError struct { + Path string `json:"path"` + Msg string `json:"msg"` + } + + type resource struct { + Filename string `json:"filename"` + Kind string `json:"kind"` + Name string `json:"name"` + Version string `json:"version"` + Status string `json:"status"` + Msg string `json:"msg"` + ValidationErrors []validationError `json:"validationErrors"` + } + + type ValidationOutput struct { + Resources []resource `json:"resources"` } + if err := kubeconform.Validate(cfg, out); err != nil { + + // read kc.IO stream and covert it to string + kcIO, _ := ioutil.ReadAll(kc.IO) + // unmarshal kcIO json output to ValidationOutput struct + var vo ValidationOutput + if err := json.Unmarshal(kcIO, &vo); err != nil { + return nil, errors.WrapPrefixf(err, "failed to unmarshal kc.IO json output") + } + var validationResults framework.Results + for _, resource := range vo.Resources { + for errIndex, _ := range resource.ValidationErrors { + + validationResults = append(validationResults, &framework.Result{ + Message: resource.ValidationErrors[0].Msg, + Severity: "error", + ResourceRef: &yaml.ResourceIdentifier{ + TypeMeta: yaml.TypeMeta{ + Kind: resource.Kind, + }, + NameMeta: yaml.NameMeta{ + Name: resource.Name, + }, + }, + Field: &framework.Field{ + Path: resource.ValidationErrors[errIndex].Path, + ProposedValue: 1, + }, + }) + } + } + return nil, validationResults + } return rlItems, nil }