mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-18 17:37:03 +00:00
feat: support set go template delims
This commit is contained in:
parent
84afe70659
commit
74cb3b20fb
8 changed files with 47 additions and 13 deletions
|
|
@ -102,6 +102,8 @@ Usage: ./bin/kubeconform [OPTION]... [FILE OR FOLDER]...
|
|||
cache schemas downloaded via HTTP to this folder
|
||||
-debug
|
||||
print debug information
|
||||
-delims string
|
||||
the delims for go template parsing
|
||||
-exit-on-error
|
||||
immediately stop execution when the first error is encountered
|
||||
-h show help information
|
||||
|
|
@ -211,6 +213,7 @@ in each of them, in order, stopping as soon as a matching file is found.
|
|||
* if the `-schema-location` value ends with `.json` - Kubeconform assumes the value is a **Go templated
|
||||
string** that indicates how to search for JSON schemas.
|
||||
* the `-schema-location` value of `default` is an alias for `https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{.NormalizedKubernetesVersion}}-standalone{{.StrictSuffix}}/{{.ResourceKind}}{{.KindSuffix}}.json`.
|
||||
* the `-delims` could use an alternative delims when parsing the URL. Such as, when you pass `-delims=[[,,]]`, then it could parse `https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/[[.NormalizedKubernetesVersion]]-standalone[[.StrictSuffix]]/[[.ResourceKind]][[.KindSuffix]].json`
|
||||
|
||||
**The following command lines are equivalent:**
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ func realMain() int {
|
|||
KubernetesVersion: cfg.KubernetesVersion,
|
||||
Strict: cfg.Strict,
|
||||
IgnoreMissingSchemas: cfg.IgnoreMissingSchemas,
|
||||
Delims: cfg.Delims,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ type Config struct {
|
|||
Verbose bool
|
||||
IgnoreMissingSchemas bool
|
||||
IgnoreFilenamePatterns []string
|
||||
Delims string
|
||||
Help bool
|
||||
Version bool
|
||||
}
|
||||
|
|
@ -78,6 +79,7 @@ func FromFlags(progName string, args []string) (Config, string, error) {
|
|||
flags.BoolVar(&c.Verbose, "verbose", false, "print results for all resources (ignored for tap and junit output)")
|
||||
flags.BoolVar(&c.SkipTLS, "insecure-skip-tls-verify", false, "disable verification of the server's SSL certificate. This will make your HTTPS connections insecure")
|
||||
flags.StringVar(&c.Cache, "cache", "", "cache schemas downloaded via HTTP to this folder")
|
||||
flags.StringVar(&c.Delims, "delims", "", "the delims for go template parsing")
|
||||
flags.BoolVar(&c.Help, "h", false, "show help information")
|
||||
flags.BoolVar(&c.Version, "v", false, "show version information")
|
||||
flags.Usage = func() {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@ type SchemaRegistry struct {
|
|||
cache cache.Cache
|
||||
strict bool
|
||||
debug bool
|
||||
delims string
|
||||
}
|
||||
|
||||
func newHTTPRegistry(schemaPathTemplate string, cacheFolder string, strict bool, skipTLS bool, debug bool) (*SchemaRegistry, error) {
|
||||
func newHTTPRegistry(schemaPathTemplate string, cacheFolder string, strict bool, skipTLS bool, debug bool, delims string) (*SchemaRegistry, error) {
|
||||
reghttp := &http.Transport{
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 3 * time.Second,
|
||||
|
|
@ -57,12 +58,13 @@ func newHTTPRegistry(schemaPathTemplate string, cacheFolder string, strict bool,
|
|||
cache: filecache,
|
||||
strict: strict,
|
||||
debug: debug,
|
||||
delims: delims,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DownloadSchema downloads the schema for a particular resource from an HTTP server
|
||||
func (r SchemaRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVersion string) ([]byte, error) {
|
||||
url, err := schemaPath(r.schemaPathTemplate, resourceKind, resourceAPIVersion, k8sVersion, r.strict)
|
||||
url, err := schemaPath(r.schemaPathTemplate, resourceKind, resourceAPIVersion, k8sVersion, r.strict, r.delims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,20 +12,22 @@ type LocalRegistry struct {
|
|||
pathTemplate string
|
||||
strict bool
|
||||
debug bool
|
||||
delims string
|
||||
}
|
||||
|
||||
// NewLocalSchemas creates a new "registry", that will serve schemas from files, given a list of schema filenames
|
||||
func newLocalRegistry(pathTemplate string, strict bool, debug bool) (*LocalRegistry, error) {
|
||||
func newLocalRegistry(pathTemplate string, strict bool, debug bool, delims string) (*LocalRegistry, error) {
|
||||
return &LocalRegistry{
|
||||
pathTemplate,
|
||||
strict,
|
||||
debug,
|
||||
delims,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DownloadSchema retrieves the schema from a file for the resource
|
||||
func (r LocalRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVersion string) ([]byte, error) {
|
||||
schemaFile, err := schemaPath(r.pathTemplate, resourceKind, resourceAPIVersion, k8sVersion, r.strict)
|
||||
schemaFile, err := schemaPath(r.pathTemplate, resourceKind, resourceAPIVersion, k8sVersion, r.strict, r.delims)
|
||||
if err != nil {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func newNotFoundError(err error) *NotFoundError {
|
|||
func (e *NotFoundError) Error() string { return e.err.Error() }
|
||||
func (e *NotFoundError) Retryable() bool { return false }
|
||||
|
||||
func schemaPath(tpl, resourceKind, resourceAPIVersion, k8sVersion string, strict bool) (string, error) {
|
||||
func schemaPath(tpl, resourceKind, resourceAPIVersion, k8sVersion string, strict bool, delims string) (string, error) {
|
||||
normalisedVersion := k8sVersion
|
||||
if normalisedVersion != "master" {
|
||||
normalisedVersion = "v" + normalisedVersion
|
||||
|
|
@ -51,7 +51,15 @@ func schemaPath(tpl, resourceKind, resourceAPIVersion, k8sVersion string, strict
|
|||
kindSuffix += "-" + strings.ToLower(groupParts[1])
|
||||
}
|
||||
|
||||
tmpl, err := template.New("tpl").Parse(tpl)
|
||||
tmpl := template.New("tpl")
|
||||
|
||||
// in case of some special cases
|
||||
delimsPairs := strings.Split(delims, ",")
|
||||
if len(delimsPairs) == 2 {
|
||||
tmpl = tmpl.Delims(delimsPairs[0], delimsPairs[1])
|
||||
}
|
||||
|
||||
tmpl, err := tmpl.Parse(tpl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -81,7 +89,7 @@ func schemaPath(tpl, resourceKind, resourceAPIVersion, k8sVersion string, strict
|
|||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func New(schemaLocation string, cache string, strict bool, skipTLS bool, debug bool) (Registry, error) {
|
||||
func New(schemaLocation string, cache string, strict bool, skipTLS bool, debug bool, delims string) (Registry, error) {
|
||||
if schemaLocation == "default" {
|
||||
schemaLocation = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{ .NormalizedKubernetesVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}{{ .KindSuffix }}.json"
|
||||
} else if !strings.HasSuffix(schemaLocation, "json") { // If we dont specify a full templated path, we assume the paths of our fork of kubernetes-json-schema
|
||||
|
|
@ -89,13 +97,13 @@ func New(schemaLocation string, cache string, strict bool, skipTLS bool, debug b
|
|||
}
|
||||
|
||||
// try to compile the schemaLocation template to ensure it is valid
|
||||
if _, err := schemaPath(schemaLocation, "Deployment", "v1", "master", true); err != nil {
|
||||
if _, err := schemaPath(schemaLocation, "Deployment", "v1", "master", true, delims); err != nil {
|
||||
return nil, fmt.Errorf("failed initialising schema location registry: %s", err)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(schemaLocation, "http") {
|
||||
return newHTTPRegistry(schemaLocation, cache, strict, skipTLS, debug)
|
||||
return newHTTPRegistry(schemaLocation, cache, strict, skipTLS, debug, delims)
|
||||
}
|
||||
|
||||
return newLocalRegistry(schemaLocation, strict, debug)
|
||||
return newLocalRegistry(schemaLocation, strict, debug, delims)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ func TestSchemaPath(t *testing.T) {
|
|||
for i, testCase := range []struct {
|
||||
tpl, resourceKind, resourceAPIVersion, k8sVersion, expected string
|
||||
strict bool
|
||||
delims string
|
||||
errExpected error
|
||||
}{
|
||||
{
|
||||
|
|
@ -17,6 +18,7 @@ func TestSchemaPath(t *testing.T) {
|
|||
"1.16.0",
|
||||
"https://kubernetesjsonschema.dev/v1.16.0-standalone-strict/deployment-apps-v1.json",
|
||||
true,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
|
|
@ -26,6 +28,7 @@ func TestSchemaPath(t *testing.T) {
|
|||
"1.16.0",
|
||||
"https://kubernetesjsonschema.dev/v1.16.0-standalone/deployment-apps-v1.json",
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
|
|
@ -35,6 +38,7 @@ func TestSchemaPath(t *testing.T) {
|
|||
"1.18.0",
|
||||
"https://kubernetesjsonschema.dev/v1.18.0-standalone/service-v1.json",
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
|
|
@ -44,10 +48,21 @@ func TestSchemaPath(t *testing.T) {
|
|||
"master",
|
||||
"https://kubernetesjsonschema.dev/master-standalone/service-v1.json",
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"https://kubernetesjsonschema.dev/[[ .NormalizedKubernetesVersion ]]-standalone[[ .StrictSuffix ]]/[[ .ResourceKind ]][[ .KindSuffix ]].json",
|
||||
"Service",
|
||||
"v1",
|
||||
"master",
|
||||
"https://kubernetesjsonschema.dev/master-standalone/service-v1.json",
|
||||
false,
|
||||
"[[,]]",
|
||||
nil,
|
||||
},
|
||||
} {
|
||||
got, err := schemaPath(testCase.tpl, testCase.resourceKind, testCase.resourceAPIVersion, testCase.k8sVersion, testCase.strict)
|
||||
got, err := schemaPath(testCase.tpl, testCase.resourceKind, testCase.resourceAPIVersion, testCase.k8sVersion, testCase.strict, testCase.delims)
|
||||
if err != testCase.errExpected {
|
||||
t.Errorf("%d - got error %s, expected %s", i+1, err, testCase.errExpected)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ type Opts struct {
|
|||
RejectKinds map[string]struct{} // List of resource Kinds to reject
|
||||
KubernetesVersion string // Kubernetes Version - has to match one in https://github.com/instrumenta/kubernetes-json-schema
|
||||
Strict bool // thros an error if resources contain undocumented fields
|
||||
IgnoreMissingSchemas bool // skip a resource if no schema for that resource can be found
|
||||
Delims string
|
||||
IgnoreMissingSchemas bool // skip a resource if no schema for that resource can be found
|
||||
}
|
||||
|
||||
// New returns a new Validator
|
||||
|
|
@ -62,7 +63,7 @@ func New(schemaLocations []string, opts Opts) (Validator, error) {
|
|||
|
||||
registries := []registry.Registry{}
|
||||
for _, schemaLocation := range schemaLocations {
|
||||
reg, err := registry.New(schemaLocation, opts.Cache, opts.Strict, opts.SkipTLS, opts.Debug)
|
||||
reg, err := registry.New(schemaLocation, opts.Cache, opts.Strict, opts.SkipTLS, opts.Debug, opts.Delims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue