Skip to content
This repository has been archived by the owner on Nov 15, 2022. It is now read-only.

Commit

Permalink
Added validation for extra field
Browse files Browse the repository at this point in the history
For validation purpose, we are `gojsonschema` library and json schema for kedge file,
JSON schema are located in `pkg/validation` directory
  • Loading branch information
surajnarwade committed Dec 6, 2017
1 parent 7cf8a4b commit 5cca0e9
Show file tree
Hide file tree
Showing 3 changed files with 14,324 additions and 3 deletions.
79 changes: 76 additions & 3 deletions pkg/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,44 @@ import (
"os/exec"
"path/filepath"

"github.com/kedgeproject/kedge/pkg/spec"

"github.com/ghodss/yaml"
"github.com/kedgeproject/kedge/pkg/spec"
"github.com/kedgeproject/kedge/pkg/validation"
"github.com/pkg/errors"
"github.com/xeipuuv/gojsonschema"
)

// https://github.com/xeipuuv/gojsonschema#formats
type ValidFormat struct{}

// IsFormat always returns true and meets the
// gojsonschema.FormatChecker interface
func (f ValidFormat) IsFormat(input interface{}) bool {
return true
}

// Based on https://stackoverflow.com/questions/40737122/convert-yaml-to-json-without-struct-golang
// We unmarshal yaml into a value of type interface{},
// go through the result recursively, and convert each encountered
// map[interface{}]interface{} to a map[string]interface{} value
// required to marshall to JSON.
// Reference: https://github.com/garethr/kubeval/blob/master/kubeval/utils.go#L8
func convertToStringKeys(i interface{}) interface{} {
switch x := i.(type) {
case map[interface{}]interface{}:
m2 := map[string]interface{}{}
for k, v := range x {
m2[k.(string)] = convertToStringKeys(v)
}
return m2
case []interface{}:
for i, v := range x {
x[i] = convertToStringKeys(v)
}
}
return i
}

// GenerateArtifacts either writes to file or uses kubectl/oc to deploy.
// TODO: Refactor into two separate functions (remove `generate bool`).
func CreateArtifacts(paths []string, generate bool, args ...string) error {
Expand All @@ -53,7 +85,8 @@ func CreateArtifacts(paths []string, generate bool, args ...string) error {
if err != nil {
return errors.Wrap(err, "failed to replace variables")
}

// Validate input kedge file
validate(input.data)
ros, includeResources, err := spec.CoreOperations(kedgeData)
if err != nil {
return errors.Wrap(err, "unable to perform controller operations")
Expand Down Expand Up @@ -180,3 +213,43 @@ func findAbsPath(baseFilePath, path string) string {
}
return filepath.Join(filepath.Dir(baseFilePath), path)
}

// validate function will validate input kedgefile against JSON schema provided in pkg/validation
func validate(p []byte) {
var speco interface{}
err := yaml.Unmarshal(p, &speco)
if err != nil {
fmt.Printf("Error with Unmarhsalling")
}
body := convertToStringKeys(speco)
s := body.(map[string]interface{})
loader := gojsonschema.NewGoLoader(body)
if s["controller"] == nil {
s["controller"] = "deployment"
}

var schema gojsonschema.JSONLoader
// Depend on type of controller, we are fetching jsonschema stored in pkg/validation
if s["controller"] == "deployment" {
schema = gojsonschema.NewStringLoader(validation.DeploymentspecmodJson)
}
if s["controller"] == "job" {
schema = gojsonschema.NewStringLoader(validation.JobspecmodJson)
}

// Without forcing these types the schema fails to load
//Reference: https://github.com/xeipuuv/gojsonschema#formats
gojsonschema.FormatCheckers.Add("int64", ValidFormat{})
gojsonschema.FormatCheckers.Add("byte", ValidFormat{})
gojsonschema.FormatCheckers.Add("int32", ValidFormat{})
gojsonschema.FormatCheckers.Add("int-or-string", ValidFormat{})
result, err := gojsonschema.Validate(schema, loader)
if !result.Valid() {
fmt.Printf("The kedgefile is not valid. see errors :\n")
for _, err := range result.Errors() {
fmt.Printf("- %s\n", err)
// os.Exit(-1)
}
}

}
Loading

0 comments on commit 5cca0e9

Please sign in to comment.