Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validate ObjectMeta #291

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions acceptance.bats
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,56 @@ resetCacheFolder() {
[ "$status" -eq 1 ]
}

@test "Fail when annotation key is invalid" {
run bin/kubeconform fixtures/annotation_key_invalid.yaml
[ "$status" -eq 1 ]
}

@test "Fail when annotation value is missing" {
run bin/kubeconform fixtures/annotation_missing_value.yaml
[ "$status" -eq 1 ]
}

@test "Fail when annotation value is null" {
run bin/kubeconform fixtures/annotation_null_value.yaml
[ "$status" -eq 1 ]
}

@test "Fail when label name is too long" {
run bin/kubeconform fixtures/label_name_length.yaml
[ "$status" -eq 1 ]
}

@test "Fail when label namespace is invalid domain" {
run bin/kubeconform fixtures/label_namespace.yaml
[ "$status" -eq 1 ]
}

@test "Fail when label value is too long" {
run bin/kubeconform fixtures/label_value_length.yaml
[ "$status" -eq 1 ]
}

@test "Fail when metadata name is missing" {
run bin/kubeconform fixtures/metadata_name_missing.yaml
[ "$status" -eq 1 ]
}

@test "Pass if skip-metadata added" {
run bin/kubeconform -skip-metadata fixtures/metadata_name_missing.yaml
[ "$status" -eq 0 ]
}

@test "Pass with extra metadata fields" {
run bin/kubeconform fixtures/metadata_extra.yaml
[ "$status" -eq 0 ]
}

@test "Fail extra metadata fields when strict" {
run bin/kubeconform -strict fixtures/metadata_extra.yaml
[ "$status" -eq 1 ]
}

@test "Return relevant error for non-existent file" {
run bin/kubeconform fixtures/not-here
[ "$status" -eq 1 ]
Expand Down
1 change: 1 addition & 0 deletions cmd/kubeconform/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func kubeconform(cfg config.Config) int {
SkipKinds: cfg.SkipKinds,
RejectKinds: cfg.RejectKinds,
KubernetesVersion: cfg.KubernetesVersion.String(),
SkipMetadata: cfg.SkipMetadata,
Strict: cfg.Strict,
IgnoreMissingSchemas: cfg.IgnoreMissingSchemas,
})
Expand Down
8 changes: 8 additions & 0 deletions fixtures/annotation_key_invalid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
annotations:
cert(manager.io/cluster-issuer": issue #275
data:
file.name: "a value"
8 changes: 8 additions & 0 deletions fixtures/annotation_missing_value.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
annotations:
some.domain/some-key:
data:
file.name: "a value"
8 changes: 8 additions & 0 deletions fixtures/annotation_null_value.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
annotations:
some.domain/some-key: null
data:
file.name: "a value"
8 changes: 8 additions & 0 deletions fixtures/label_name_length.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
labels:
abcdefghijklmnopqrstuvwxyz-01234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ: "123456789_123456789_123456789_123456789_123456789_123456789_123"
data:
file.name: "a value"
8 changes: 8 additions & 0 deletions fixtures/label_namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
labels:
abcdefghijklmnopqrstuvwxyz-01234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ.example.com/ABCDEFGHIJKLMNOPQRSTUVWXYZ: "123456789_123456789_123456789_123456789_123456789_123456789_123"
data:
file.name: "a value"
8 changes: 8 additions & 0 deletions fixtures/label_value_length.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
labels:
some.domain/some-key: "123456789_123456789_123456789_123456789_123456789_123456789_1234"
data:
file.name: "a value"
9 changes: 9 additions & 0 deletions fixtures/metadata_extra.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: some-values
namespace: my-namespace
annotation:
flub: annotation should be annotations
data:
file.name: "a value"
4 changes: 4 additions & 0 deletions fixtures/metadata_missing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: ConfigMap
data:
file.name: "a value"
6 changes: 6 additions & 0 deletions fixtures/metadata_name_missing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:

data:
file.name: "a value"
6 changes: 6 additions & 0 deletions fixtures/object_name-max_length.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: abcdefghijklmnopqrstuvwxyz-01234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ
data:
file.name: "a value"
2 changes: 2 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Config struct {
RejectKinds map[string]struct{} `yaml:"reject" json:"reject"`
SchemaLocations []string `yaml:"schemaLocations" json:"schemaLocations"`
SkipKinds map[string]struct{} `yaml:"skip" json:"skip"`
SkipMetadata bool `yaml:"skipMetadata" json:"skipMetadata"`
SkipTLS bool `yaml:"insecureSkipTLSVerify" json:"insecureSkipTLSVerify"`
Strict bool `yaml:"strict" json:"strict"`
Summary bool `yaml:"summary" json:"summary"`
Expand Down Expand Up @@ -97,6 +98,7 @@ func FromFlags(progName string, args []string) (Config, string, error) {
flags.StringVar(&c.OutputFormat, "output", "text", "output format - json, junit, pretty, tap, text")
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.BoolVar(&c.SkipMetadata, "skip-metadata", false, "skip extra validations of metadata section")
flags.StringVar(&c.Cache, "cache", "", "cache schemas downloaded via HTTP to this folder")
flags.BoolVar(&c.Help, "h", false, "show help information")
flags.BoolVar(&c.Version, "v", false, "show version information")
Expand Down
35 changes: 35 additions & 0 deletions pkg/registry/embeded.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package registry

import (
"embed"
)

//go:embed *.json
var content embed.FS

type EmbeddedRegistry struct {
debug bool
strict bool
}

// NewEmbeddedRegistry creates a new "registry", that will serve schemas from embedded resource
func NewEmbeddedRegistry(debug bool, strict bool) *EmbeddedRegistry {
return &EmbeddedRegistry{
debug, strict,
}
}

// DownloadSchema retrieves the schema from a file for the resource
func (r EmbeddedRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVersion string) (string, []byte, error) {
var fileName string
if r.strict {
fileName = resourceKind + "-strict.json"
} else {
fileName = resourceKind + ".json"
}
bytes, err := content.ReadFile(fileName)
if err != nil {
return resourceKind, nil, nil
}
return "embedded:" + resourceKind, bytes, nil
}
110 changes: 110 additions & 0 deletions pkg/registry/metadata-strict.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"apiVersion": {
"$ref": "#/$defs/PREFIXED"
},
"kind": {
"$ref": "#/$defs/NAME"
},
"metadata": {
"type": "object",
"additionalProperties": false,
"properties": {
"annotations": {
"type": "object",
"propertyNames": {
"$ref": "#/$defs/PREFIXED"
},
"patternProperties": {
"^.+$": {
"type": "string",
"minLength": 1
}
}
},
"finalizers": {
"type": "array",
"items": {
"type": "string"
}
},
"generateName": {
"$ref": "#/$defs/RFC-1123-prefix"
},
"labels": {
"type": "object",
"propertyNames": {
"$ref": "#/$defs/PREFIXED"
},
"patternProperties": {
"^.+$": {
"$ref": "#/$defs/NAME"
}
}
},
"managedFields": {
"type": "array",
"items": {
"type": "object"
}
},
"name": {
"$ref": "#/$defs/RFC-1123"
},
"namespace": {
"$ref": "#/$defs/RFC-1123"
}
},
"oneOf": [
{
"required": [
"name"
]
},
{
"required": [
"generateName"
]
}
]
}
},
"required": [
"apiVersion",
"kind",
"metadata"
],
"$defs": {
"PREFIXED": {
"allOf": [
{
"pattern": "^(.{0,253}/)?.{1,63}$",
"type": "string"
},
{
"pattern": "^([a-z0-9-]{1,63}(\\.[a-z0-9-]{1,63})*/)?[a-z0-9A-Z]+([_.-][a-z0-9A-Z]+)*$"
}
]
},
"NAME": {
"type": "string",
"minLength": 1,
"maxLength": 63,
"pattern": "^[a-z0-9A-Z]+([_.-][a-z0-9A-Z]+)*$"
},
"RFC-1123": {
"type": "string",
"minLength": 1,
"maxLength": 63,
"pattern": "^[a-z0-9]+(-+[a-z0-9]+)*$"
},
"RFC-1123-prefix": {
"type": "string",
"minLength": 1,
"maxLength": 58,
"pattern": "^[a-z0-9]+[a-z0-9-]*$"
}
}
}
Loading