Allowing type object in kubectl swagger validation
This commit is contained in:
		@@ -282,7 +282,10 @@ func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType st
 | 
			
		||||
		if _, ok := value.(bool); !ok {
 | 
			
		||||
			return append(allErrs, NewInvalidTypeError(reflect.Bool, reflect.TypeOf(value).Kind(), fieldName))
 | 
			
		||||
		}
 | 
			
		||||
	// API servers before release 1.3 produce swagger spec with `type: "any"` as the fallback type, while newer servers produce spec with `type: "object"`.
 | 
			
		||||
	// We have both here so that kubectl can work with both old and new api servers.
 | 
			
		||||
	case "any":
 | 
			
		||||
	case "object":
 | 
			
		||||
	default:
 | 
			
		||||
		return append(allErrs, fmt.Errorf("unexpected type: %v", fieldType))
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,26 +19,33 @@ package validation
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/testapi"
 | 
			
		||||
	apitesting "k8s.io/kubernetes/pkg/api/testing"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/runtime"
 | 
			
		||||
 | 
			
		||||
	"github.com/ghodss/yaml"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func readPod(filename string) (string, error) {
 | 
			
		||||
func readPod(filename string) ([]byte, error) {
 | 
			
		||||
	data, err := ioutil.ReadFile("testdata/" + testapi.Default.GroupVersion().Version + "/" + filename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return string(data), nil
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readSwaggerFile() ([]byte, error) {
 | 
			
		||||
	// TODO this path is broken
 | 
			
		||||
	pathToSwaggerSpec := "../../../api/swagger-spec/" + testapi.Default.GroupVersion().Version + ".json"
 | 
			
		||||
	return ioutil.ReadFile(pathToSwaggerSpec)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func loadSchemaForTest() (Schema, error) {
 | 
			
		||||
	// TODO this path is broken
 | 
			
		||||
	pathToSwaggerSpec := "../../../api/swagger-spec/" + testapi.Default.GroupVersion().Version + ".json"
 | 
			
		||||
	data, err := ioutil.ReadFile(pathToSwaggerSpec)
 | 
			
		||||
	data, err := readSwaggerFile()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -98,9 +105,9 @@ func TestInvalid(t *testing.T) {
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		pod, err := readPod(test)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("could not read file: %s", pod)
 | 
			
		||||
			t.Errorf("could not read file: %s, err: %v", test, err)
 | 
			
		||||
		}
 | 
			
		||||
		err = schema.ValidateBytes([]byte(pod))
 | 
			
		||||
		err = schema.ValidateBytes(pod)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			t.Errorf("unexpected non-error, err: %s for pod: %s", err, pod)
 | 
			
		||||
		}
 | 
			
		||||
@@ -118,9 +125,9 @@ func TestValid(t *testing.T) {
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		pod, err := readPod(test)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("could not read file: %s", test)
 | 
			
		||||
			t.Errorf("could not read file: %s, err: %v", test, err)
 | 
			
		||||
		}
 | 
			
		||||
		err = schema.ValidateBytes([]byte(pod))
 | 
			
		||||
		err = schema.ValidateBytes(pod)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error %s, for pod %s", err, pod)
 | 
			
		||||
		}
 | 
			
		||||
@@ -154,3 +161,39 @@ func TestVersionRegex(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests that validation works fine when spec contains "type": "object" instead of "type": "any"
 | 
			
		||||
func TestTypeObject(t *testing.T) {
 | 
			
		||||
	data, err := readSwaggerFile()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("failed to read swagger file: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	// Replace type: "any" in the spec by type: "object" and verify that the validation still passes.
 | 
			
		||||
	newData := strings.Replace(string(data), `"type": "any"`, `"type": "object"`, -1)
 | 
			
		||||
	schema, err := NewSwaggerSchemaFromBytes([]byte(newData))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Failed to load: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	tests := []string{
 | 
			
		||||
		"validPod.yaml",
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		podBytes, err := readPod(test)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("could not read file: %s, err: %v", test, err)
 | 
			
		||||
		}
 | 
			
		||||
		// Verify that pod has at least one label (labels are type "any")
 | 
			
		||||
		var pod api.Pod
 | 
			
		||||
		err = yaml.Unmarshal(podBytes, &pod)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("error in unmarshalling pod: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(pod.Labels) == 0 {
 | 
			
		||||
			t.Errorf("invalid test input: the pod should have at least one label")
 | 
			
		||||
		}
 | 
			
		||||
		err = schema.ValidateBytes(podBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error %s, for pod %s", err, string(podBytes))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user