add support for local schemas

This commit is contained in:
Yann Hamon 2020-05-30 18:28:04 +02:00
parent f82baa834c
commit 5f3504724f
3 changed files with 16 additions and 67 deletions

View file

@ -13,6 +13,8 @@ Usage of ./bin/kubeconform:
version of Kubernetes to test against (default "1.18.0") version of Kubernetes to test against (default "1.18.0")
-output string -output string
output format - text, json (default "text") output format - text, json (default "text")
-schema value
file containing an additional Schema (can be specified multiple times)
-skipKinds string -skipKinds string
comma-separated list of kinds to ignore comma-separated list of kinds to ignore
``` ```

17
main.go
View file

@ -24,7 +24,7 @@ type validationResult struct {
// filter returns true if the file should be skipped // filter returns true if the file should be skipped
// Returning an array, this Reader might container multiple resources // Returning an array, this Reader might container multiple resources
func validateFile(f io.Reader, regs []*registry.KubernetesRegistry, k8sVersion string, skip func(signature resource.Signature)bool) []validationResult { func validateFile(f io.Reader, regs []registry.Registry, k8sVersion string, skip func(signature resource.Signature)bool) []validationResult {
rawResource, err := ioutil.ReadAll(f) rawResource, err := ioutil.ReadAll(f)
if err != nil { if err != nil {
return []validationResult{{err: fmt.Errorf("failed reading file: %s", err)}} return []validationResult{{err: fmt.Errorf("failed reading file: %s", err)}}
@ -74,10 +74,11 @@ func (i *arrayFiles) Set(value string) error {
func realMain() int { func realMain() int {
var files, dirs arrayFiles var files, dirs, schemas arrayFiles
var skipKinds, k8sVersion, outputFormat string var skipKinds, k8sVersion, outputFormat string
flag.Var(&files, "file", "file to validate (can be specified multiple times)") flag.Var(&files, "file", "file to validate (can be specified multiple times)")
flag.Var(&dirs, "dir", "directory to validate (can be specified multiple times)") flag.Var(&dirs, "dir", "directory to validate (can be specified multiple times)")
flag.Var(&schemas, "schema", "file containing an additional Schema")
flag.StringVar(&k8sVersion, "k8sversion", "1.18.0", "version of Kubernetes to test against") flag.StringVar(&k8sVersion, "k8sversion", "1.18.0", "version of Kubernetes to test against")
flag.StringVar(&skipKinds, "skipKinds", "", "comma-separated list of kinds to ignore") flag.StringVar(&skipKinds, "skipKinds", "", "comma-separated list of kinds to ignore")
flag.StringVar(&outputFormat, "output", "text", "output format - text, json") flag.StringVar(&outputFormat, "output", "text", "output format - text, json")
@ -119,7 +120,15 @@ func realMain() int {
close(fileBatches) close(fileBatches)
}() }()
r := registry.NewKubernetesRegistry(false) registries := []registry.Registry{}
registries = append(registries, registry.NewKubernetesRegistry(false))
if len(schemas) > 0 {
localRegistry, err := registry.NewLocalSchemas(schemas)
if err != nil {
log.Fatalf("%s", err)
}
registries = append(registries, localRegistry)
}
for fileBatch := range fileBatches { for fileBatch := range fileBatches {
for _, filename := range fileBatch { for _, filename := range fileBatch {
@ -129,7 +138,7 @@ func realMain() int {
continue continue
} }
res := validateFile(f, []*registry.KubernetesRegistry{r}, k8sVersion, filter) res := validateFile(f, registries, k8sVersion, filter)
f.Close() f.Close()

View file

@ -1,71 +1,9 @@
package registry package registry
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
type Manifest struct { type Manifest struct {
Kind, Version string Kind, Version string
} }
type Registry interface { type Registry interface {
DownloadSchema(kind, apiVersion string) error DownloadSchema(resourceKind, resourceAPIVersion, k8sVersion string) ([]byte, error)
} }
type KubernetesRegistry struct {
baseURL string
strict bool
}
func NewKubernetesRegistry(strict bool) *KubernetesRegistry {
return &KubernetesRegistry{
baseURL: "https://kubernetesjsonschema.dev",
strict: strict,
}
}
func (r KubernetesRegistry) schemaURL(resourceKind, resourceAPIVersion, k8sVersion string) string {
normalisedVersion := k8sVersion
if normalisedVersion != "master" {
normalisedVersion = "v" + normalisedVersion
}
strictSuffix := ""
if r.strict {
strictSuffix = "-strict"
}
groupParts := strings.Split(resourceAPIVersion, "/")
versionParts := strings.Split(groupParts[0], ".")
kindSuffix := "-" + strings.ToLower(versionParts[0])
if len(groupParts) > 1 {
kindSuffix += "-" + strings.ToLower(groupParts[1])
}
return fmt.Sprintf("%s/%s-standalone%s/%s%s.json", r.baseURL, normalisedVersion, strictSuffix, strings.ToLower(resourceKind), kindSuffix)
}
func (r KubernetesRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVersion string) ([]byte, error) {
url := r.schemaURL(resourceKind, resourceAPIVersion, k8sVersion)
resp, err := http.Get(url)
if err != nil {
return []byte{}, fmt.Errorf("failed downloading schema at %s: %s", url, err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return []byte{}, fmt.Errorf("failed downloading schema at %s: %s", url, err)
}
fmt.Printf("downloaded %s\n", url)
return body, nil
}