mirror of https://github.com/k3s-io/k3s
Merge pull request #6849 from nikhiljindal/validation
Updating api/validation/schema_test to test testapi.Version rather than just v1beta1pull/6/head
commit
775787bb4c
|
@ -78,7 +78,14 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatalf("Couldn't read from input: %q", err)
|
||||
}
|
||||
isYAML := isYAML(data)
|
||||
|
||||
if isYAML {
|
||||
data, err = yaml.YAMLToJSON(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to convert YAML to JSON: %q", err)
|
||||
}
|
||||
}
|
||||
obj, err := api.Scheme.Decode(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't decode input: %q", err)
|
||||
|
@ -89,7 +96,7 @@ func main() {
|
|||
log.Fatalf("Failed to encode to version %q: %q", *outputVersion, err)
|
||||
}
|
||||
|
||||
if isYAML(data) {
|
||||
if isYAML {
|
||||
outData, err = yaml.JSONToYAML(outData)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to convert to YAML: %q", err)
|
||||
|
|
|
@ -73,7 +73,10 @@ func (s *SwaggerSchema) ValidateBytes(data []byte) error {
|
|||
if err := json.Unmarshal(data, &obj); err != nil {
|
||||
return err
|
||||
}
|
||||
fields := obj.(map[string]interface{})
|
||||
fields, ok := obj.(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("error in unmarshaling data %s", string(data))
|
||||
}
|
||||
apiVersion := fields["apiVersion"].(string)
|
||||
kind := fields["kind"].(string)
|
||||
return s.ValidateObject(obj, apiVersion, "", apiVersion+"."+kind)
|
||||
|
@ -84,25 +87,37 @@ func (s *SwaggerSchema) ValidateObject(obj interface{}, apiVersion, fieldName, t
|
|||
// TODO: handle required fields here too.
|
||||
model, ok := models[typeName]
|
||||
if !ok {
|
||||
glog.V(2).Infof("couldn't find type: %s, skipping validation", typeName)
|
||||
return nil
|
||||
return fmt.Errorf("couldn't find type: %s", typeName)
|
||||
}
|
||||
properties := model.Properties
|
||||
fields := obj.(map[string]interface{})
|
||||
if len(properties) == 0 {
|
||||
// The object does not have any sub-fields.
|
||||
return nil
|
||||
}
|
||||
fields, ok := obj.(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("expected object of type map[string]interface{} as value of %s field", fieldName)
|
||||
}
|
||||
if len(fieldName) > 0 {
|
||||
fieldName = fieldName + "."
|
||||
}
|
||||
for key, value := range fields {
|
||||
details, ok := properties[key]
|
||||
if !ok {
|
||||
glog.V(2).Infof("couldn't find properties for %s, skipping", key)
|
||||
// Some properties can be missing because of
|
||||
// https://github.com/GoogleCloudPlatform/kubernetes/issues/6842.
|
||||
glog.V(2).Infof("couldn't find properties for %s", key)
|
||||
continue
|
||||
}
|
||||
if details.Type == nil {
|
||||
glog.V(2).Infof("nil details for %s, skipping", key)
|
||||
continue
|
||||
if details.Type == nil && details.Ref == nil {
|
||||
return fmt.Errorf("could not find the type of %s from object: %v", key, details)
|
||||
}
|
||||
var fieldType string
|
||||
if details.Type != nil {
|
||||
fieldType = *details.Type
|
||||
} else {
|
||||
fieldType = *details.Ref
|
||||
}
|
||||
fieldType := *details.Type
|
||||
if value == nil {
|
||||
glog.V(2).Infof("Skipping nil field: %s", key)
|
||||
continue
|
||||
|
@ -134,7 +149,15 @@ func (s *SwaggerSchema) validateField(value interface{}, apiVersion, fieldName,
|
|||
if !ok {
|
||||
return NewInvalidTypeError(reflect.Array, reflect.TypeOf(value).Kind(), fieldName)
|
||||
}
|
||||
arrType := *fieldDetails.Items.Ref
|
||||
var arrType string
|
||||
if fieldDetails.Items.Ref == nil && fieldDetails.Items.Type == nil {
|
||||
return NewInvalidTypeError(reflect.Array, reflect.TypeOf(value).Kind(), fieldName)
|
||||
}
|
||||
if fieldDetails.Items.Ref != nil {
|
||||
arrType = *fieldDetails.Items.Ref
|
||||
} else {
|
||||
arrType = *fieldDetails.Items.Type
|
||||
}
|
||||
for ix := range arr {
|
||||
err := s.validateField(arr[ix], apiVersion, fmt.Sprintf("%s[%d]", fieldName, ix), arrType, nil)
|
||||
if err != nil {
|
||||
|
@ -156,6 +179,7 @@ func (s *SwaggerSchema) validateField(value interface{}, apiVersion, fieldName,
|
|||
if _, ok := value.(bool); !ok {
|
||||
return NewInvalidTypeError(reflect.Bool, reflect.TypeOf(value).Kind(), fieldName)
|
||||
}
|
||||
case "any":
|
||||
default:
|
||||
return fmt.Errorf("unexpected type: %v", fieldType)
|
||||
}
|
||||
|
|
|
@ -22,13 +22,22 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
|
||||
apitesting "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testing"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func LoadSchemaForTest(file string) (Schema, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
func readPod(filename string) (string, error) {
|
||||
data, err := ioutil.ReadFile("testdata/" + testapi.Version() + "/" + filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func loadSchemaForTest() (Schema, error) {
|
||||
pathToSwaggerSpec := "../../../api/swagger-spec/" + testapi.Version() + ".json"
|
||||
data, err := ioutil.ReadFile(pathToSwaggerSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -36,14 +45,14 @@ func LoadSchemaForTest(file string) (Schema, error) {
|
|||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
_, err := LoadSchemaForTest("v1beta1-swagger.json")
|
||||
_, err := loadSchemaForTest()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to load: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateOk(t *testing.T) {
|
||||
schema, err := LoadSchemaForTest("v1beta1-swagger.json")
|
||||
schema, err := loadSchemaForTest()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to load: %v", err)
|
||||
}
|
||||
|
@ -62,7 +71,7 @@ func TestValidateOk(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
testObj := test.obj
|
||||
apiObjectFuzzer.Fuzz(testObj)
|
||||
data, err := v1beta1.Codec.Encode(testObj)
|
||||
data, err := testapi.Codec().Encode(testObj)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -74,150 +83,45 @@ func TestValidateOk(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var invalidPod = `{
|
||||
"id": "name",
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1beta1",
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"version": "v1beta1",
|
||||
"id": "redis-master",
|
||||
"containers": [{
|
||||
"name": "master",
|
||||
"image": "dockerfile/redis",
|
||||
"command": "this is a bad command",
|
||||
}]
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"name": "redis-master"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var invalidPod2 = `{
|
||||
"apiVersion": "v1beta1",
|
||||
"kind": "Pod",
|
||||
"id": "apache-php",
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"version": "v1beta1",
|
||||
"id": "apache-php",
|
||||
"containers": [{
|
||||
"name": "apache-php",
|
||||
"image": "php:5.6.2-apache",
|
||||
"ports": [{ "name": "apache", "containerPort": 80, "hostPort":"13380", "protocol":"TCP" }],
|
||||
"volumeMounts": [{"name": "shared-disk","mountPath": "/var/www/html", "readOnly": false}]
|
||||
}]
|
||||
}
|
||||
},
|
||||
"labels": { "name": "apache-php" },
|
||||
"restartPolicy": {"always": {}},
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"volumes": [
|
||||
"name": "shared-disk",
|
||||
"source": {
|
||||
"GCEPersistentDisk": {
|
||||
"path": "shared-disk"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
var invalidPod3 = `{
|
||||
"apiVersion": "v1beta1",
|
||||
"kind": "Pod",
|
||||
"id": "apache-php",
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"version": "v1beta1",
|
||||
"id": "apache-php",
|
||||
"containers": [{
|
||||
"name": "apache-php",
|
||||
"image": "php:5.6.2-apache",
|
||||
"ports": [{ "name": "apache", "containerPort": 80, "hostPort":"13380", "protocol":"TCP" }],
|
||||
"volumeMounts": [{"name": "shared-disk","mountPath": "/var/www/html", "readOnly": false}]
|
||||
}]
|
||||
}
|
||||
},
|
||||
"labels": { "name": "apache-php" },
|
||||
"restartPolicy": {"always": {}},
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"volumes": [
|
||||
{
|
||||
"name": "shared-disk",
|
||||
"source": {
|
||||
"GCEPersistentDisk": {
|
||||
"path": "shared-disk"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
var invalidYaml = `
|
||||
id: name
|
||||
kind: Pod
|
||||
apiVersion: v1beta1
|
||||
desiredState:
|
||||
manifest:
|
||||
version: v1beta1
|
||||
id: redis-master
|
||||
containers:
|
||||
- name: "master"
|
||||
image: "dockerfile/redis"
|
||||
command: "this is a bad command"
|
||||
labels:
|
||||
name: "redis-master"
|
||||
`
|
||||
|
||||
func TestInvalid(t *testing.T) {
|
||||
schema, err := LoadSchemaForTest("v1beta1-swagger.json")
|
||||
schema, err := loadSchemaForTest()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to load: %v", err)
|
||||
}
|
||||
tests := []string{invalidPod, invalidPod2, invalidPod3, invalidYaml}
|
||||
tests := []string{
|
||||
"invalidPod1.json", // command is a string, instead of []string.
|
||||
"invalidPod2.json", // hostPort if of type string, instead of int.
|
||||
"invalidPod3.json", // volumes is not an array of objects.
|
||||
"invalidPod.yaml", // command is a string, instead of []string.
|
||||
}
|
||||
for _, test := range tests {
|
||||
err = schema.ValidateBytes([]byte(test))
|
||||
pod, err := readPod(test)
|
||||
if err != nil {
|
||||
t.Errorf("could not read file: %s", pod)
|
||||
}
|
||||
err = schema.ValidateBytes([]byte(pod))
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error\n%s", test)
|
||||
t.Errorf("unexpected non-error, err: %s for pod: %s", err, pod)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var validYaml = `
|
||||
id: name
|
||||
kind: Pod
|
||||
apiVersion: v1beta1
|
||||
desiredState:
|
||||
manifest:
|
||||
version: v1beta1
|
||||
id: redis-master
|
||||
containers:
|
||||
- name: "master"
|
||||
image: "dockerfile/redis"
|
||||
command:
|
||||
- this
|
||||
- is
|
||||
- an
|
||||
- ok
|
||||
- command
|
||||
labels:
|
||||
name: "redis-master"
|
||||
`
|
||||
|
||||
func TestValid(t *testing.T) {
|
||||
schema, err := LoadSchemaForTest("v1beta1-swagger.json")
|
||||
schema, err := loadSchemaForTest()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to load: %v", err)
|
||||
}
|
||||
tests := []string{validYaml}
|
||||
tests := []string{
|
||||
"validPod.yaml",
|
||||
}
|
||||
for _, test := range tests {
|
||||
err = schema.ValidateBytes([]byte(test))
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error\n%s", test)
|
||||
pod, err := readPod(test)
|
||||
if err != nil {
|
||||
t.Errorf("could not read file: %s", test)
|
||||
}
|
||||
err = schema.ValidateBytes([]byte(pod))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %s, for pod %s", err, pod)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
kind: Pod
|
||||
apiVersion: v1beta1
|
||||
id: name
|
||||
desiredState:
|
||||
manifest:
|
||||
version: v1beta1
|
||||
id: redis-master
|
||||
containers:
|
||||
- name: "master"
|
||||
image: "dockerfile/redis"
|
||||
command: "this is a bad command"
|
||||
labels:
|
||||
name: "redis-master"
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"id": "name",
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1beta1",
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"version": "v1beta1",
|
||||
"id": "redis-master",
|
||||
"containers": [{
|
||||
"name": "master",
|
||||
"image": "dockerfile/redis",
|
||||
"command": "this is a bad command"
|
||||
}]
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"name": "redis-master"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"apiVersion": "v1beta1",
|
||||
"kind": "Pod",
|
||||
"id": "apache-php",
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"version": "v1beta1",
|
||||
"id": "apache-php",
|
||||
"containers": [{
|
||||
"name": "apache-php",
|
||||
"image": "php:5.6.2-apache",
|
||||
"ports": [{ "name": "apache", "containerPort": 80, "hostPort":"13380", "protocol":"TCP" }],
|
||||
"volumeMounts": [{"name": "shared-disk","mountPath": "/var/www/html", "readOnly": false}]
|
||||
}],
|
||||
"restartPolicy": {"always": {}},
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"volumes": [{
|
||||
"name": "shared-disk",
|
||||
"source": {
|
||||
"GCEPersistentDisk": {
|
||||
"path": "shared-disk"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
"labels": { "name": "apache-php" }
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"apiVersion": "v1beta1",
|
||||
"kind": "Pod",
|
||||
"id": "apache-php",
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"version": "v1beta1",
|
||||
"id": "apache-php",
|
||||
"containers": [{
|
||||
"name": "apache-php",
|
||||
"image": "php:5.6.2-apache",
|
||||
"ports": [{ "name": "apache", "containerPort": 80, "hostPort":13380, "protocol":"TCP" }],
|
||||
"volumeMounts": [{"name": "shared-disk","mountPath": "/var/www/html", "readOnly": false}]
|
||||
}],
|
||||
"restartPolicy": {"always": {}},
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"volumes": [
|
||||
"name": "shared-disk",
|
||||
"source": {
|
||||
"GCEPersistentDisk": {
|
||||
"path": "shared-disk"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"labels": { "name": "apache-php" }
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
id: name
|
||||
kind: Pod
|
||||
apiVersion: v1beta1
|
||||
desiredState:
|
||||
manifest:
|
||||
version: v1beta1
|
||||
id: redis-master
|
||||
containers:
|
||||
- name: "master"
|
||||
image: "dockerfile/redis"
|
||||
command:
|
||||
- this
|
||||
- is
|
||||
- an
|
||||
- ok
|
||||
- command
|
||||
labels:
|
||||
name: "redis-master"
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1beta3
|
||||
kind: Pod
|
||||
metadata:
|
||||
labels:
|
||||
name: redis-master
|
||||
name: name
|
||||
spec:
|
||||
containers:
|
||||
- args: "this is a bad command"
|
||||
image: dockerfile/redis
|
||||
name: master
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1beta3",
|
||||
"metadata": {
|
||||
"name": "name",
|
||||
"labels": {
|
||||
"name": "redis-master"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "master",
|
||||
"image": "dockerfile/redis",
|
||||
"args": "this is a bad command"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1beta3",
|
||||
"metadata": {
|
||||
"name": "apache-php",
|
||||
"labels": {
|
||||
"name": "apache-php"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [{
|
||||
"name": "shared-disk"
|
||||
}],
|
||||
"containers": [
|
||||
{
|
||||
"name": "apache-php",
|
||||
"image": "php:5.6.2-apache",
|
||||
"ports": [
|
||||
{
|
||||
"name": "apache",
|
||||
"hostPort": "13380",
|
||||
"containerPort": 80,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "shared-disk",
|
||||
"mountPath": "/var/www/html"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1beta3",
|
||||
"metadata": {
|
||||
"name": "apache-php",
|
||||
"labels": {
|
||||
"name": "apache-php"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
"name": "shared-disk"
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "apache-php",
|
||||
"image": "php:5.6.2-apache",
|
||||
"ports": [
|
||||
{
|
||||
"name": "apache",
|
||||
"hostPort": 13380,
|
||||
"containerPort": 80,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "shared-disk",
|
||||
"mountPath": "/var/www/html"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1beta3
|
||||
kind: Pod
|
||||
metadata:
|
||||
labels:
|
||||
name: redis-master
|
||||
name: name
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- this
|
||||
- is
|
||||
- an
|
||||
- ok
|
||||
- command
|
||||
image: dockerfile/redis
|
||||
name: master
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue