add prune and remove unused packages

This commit is contained in:
Michelle Au
2019-03-08 14:54:43 -08:00
parent f59b58d164
commit 8c0accad66
17240 changed files with 27 additions and 4750030 deletions

View File

@@ -1,49 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proto_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/config"
. "github.com/onsi/ginkgo/types"
. "github.com/onsi/gomega"
"fmt"
"testing"
)
func TestOpenapi(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecsWithDefaultAndCustomReporters(t, "Openapi Suite", []Reporter{newlineReporter{}})
}
// Print a newline after the default newlineReporter due to issue
// https://github.com/jstemmer/go-junit-report/issues/31
type newlineReporter struct{}
func (newlineReporter) SpecSuiteWillBegin(config GinkgoConfigType, summary *SuiteSummary) {}
func (newlineReporter) BeforeSuiteDidRun(setupSummary *SetupSummary) {}
func (newlineReporter) AfterSuiteDidRun(setupSummary *SetupSummary) {}
func (newlineReporter) SpecWillRun(specSummary *SpecSummary) {}
func (newlineReporter) SpecDidComplete(specSummary *SpecSummary) {}
// SpecSuiteDidEnd Prints a newline between "35 Passed | 0 Failed | 0 Pending | 0 Skipped" and "--- PASS:"
func (newlineReporter) SpecSuiteDidEnd(summary *SuiteSummary) { fmt.Printf("\n") }

View File

@@ -1,265 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proto_test
import (
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/kube-openapi/pkg/util/proto"
"k8s.io/kube-openapi/pkg/util/proto/testing"
)
var fakeSchema = testing.Fake{Path: filepath.Join("testdata", "swagger.json")}
var fakeSchemaNext = testing.Fake{Path: filepath.Join("testdata", "swagger_next.json")}
var _ = Describe("Reading apps/v1beta1/Deployment from v1.8 openAPIData", func() {
var models proto.Models
BeforeEach(func() {
s, err := fakeSchema.OpenAPISchema()
Expect(err).To(BeNil())
models, err = proto.NewOpenAPIData(s)
Expect(err).To(BeNil())
})
model := "io.k8s.api.apps.v1beta1.Deployment"
var schema proto.Schema
It("should lookup the Schema by its model name", func() {
schema = models.LookupModel(model)
Expect(schema).ToNot(BeNil())
})
var deployment *proto.Kind
It("should be a Kind", func() {
deployment = schema.(*proto.Kind)
Expect(deployment).ToNot(BeNil())
})
It("should have a path", func() {
Expect(deployment.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment"}))
})
It("should have a kind key of type string", func() {
Expect(deployment.Fields).To(HaveKey("kind"))
key := deployment.Fields["kind"].(*proto.Primitive)
Expect(key).ToNot(BeNil())
Expect(key.Type).To(Equal("string"))
Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment", ".kind"}))
})
It("should have a apiVersion key of type string", func() {
Expect(deployment.Fields).To(HaveKey("apiVersion"))
key := deployment.Fields["apiVersion"].(*proto.Primitive)
Expect(key).ToNot(BeNil())
Expect(key.Type).To(Equal("string"))
Expect(key.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.Deployment", ".apiVersion"}))
})
It("should have a metadata key of type Reference", func() {
Expect(deployment.Fields).To(HaveKey("metadata"))
key := deployment.Fields["metadata"].(proto.Reference)
Expect(key).ToNot(BeNil())
Expect(key.Reference()).To(Equal("io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"))
subSchema := key.SubSchema().(*proto.Kind)
Expect(subSchema).ToNot(BeNil())
})
var status *proto.Kind
It("should have a status key of type Reference", func() {
Expect(deployment.Fields).To(HaveKey("status"))
key := deployment.Fields["status"].(proto.Reference)
Expect(key).ToNot(BeNil())
Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentStatus"))
status = key.SubSchema().(*proto.Kind)
Expect(status).ToNot(BeNil())
})
It("should have a valid DeploymentStatus", func() {
By("having availableReplicas key")
Expect(status.Fields).To(HaveKey("availableReplicas"))
replicas := status.Fields["availableReplicas"].(*proto.Primitive)
Expect(replicas).ToNot(BeNil())
Expect(replicas.Type).To(Equal("integer"))
By("having conditions key")
Expect(status.Fields).To(HaveKey("conditions"))
conditions := status.Fields["conditions"].(*proto.Array)
Expect(conditions).ToNot(BeNil())
Expect(conditions.GetName()).To(Equal(`Array of Reference to "io.k8s.api.apps.v1beta1.DeploymentCondition"`))
Expect(conditions.GetExtensions()).To(Equal(map[string]interface{}{
"x-kubernetes-patch-merge-key": "type",
"x-kubernetes-patch-strategy": "merge",
}))
condition := conditions.SubType.(proto.Reference)
Expect(condition.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentCondition"))
})
var spec *proto.Kind
It("should have a spec key of type Reference", func() {
Expect(deployment.Fields).To(HaveKey("spec"))
key := deployment.Fields["spec"].(proto.Reference)
Expect(key).ToNot(BeNil())
Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentSpec"))
spec = key.SubSchema().(*proto.Kind)
Expect(spec).ToNot(BeNil())
})
It("should have a spec with no gvk", func() {
_, found := spec.GetExtensions()["x-kubernetes-group-version-kind"]
Expect(found).To(BeFalse())
})
It("should have a spec with a PodTemplateSpec sub-field", func() {
Expect(spec.Fields).To(HaveKey("template"))
key := spec.Fields["template"].(proto.Reference)
Expect(key).ToNot(BeNil())
Expect(key.Reference()).To(Equal("io.k8s.api.core.v1.PodTemplateSpec"))
})
})
var _ = Describe("Reading apps/v1beta1/Deployment from v1.11 openAPIData", func() {
var models proto.Models
BeforeEach(func() {
s, err := fakeSchemaNext.OpenAPISchema()
Expect(err).To(BeNil())
models, err = proto.NewOpenAPIData(s)
Expect(err).To(BeNil())
})
model := "io.k8s.api.apps.v1beta1.Deployment"
var schema proto.Schema
It("should lookup the Schema by its model name", func() {
schema = models.LookupModel(model)
Expect(schema).ToNot(BeNil())
})
var deployment *proto.Kind
It("should be a Kind", func() {
deployment = schema.(*proto.Kind)
Expect(deployment).ToNot(BeNil())
})
})
var _ = Describe("Reading apps/v1beta1/ControllerRevision from v1.11 openAPIData", func() {
var models proto.Models
BeforeEach(func() {
s, err := fakeSchemaNext.OpenAPISchema()
Expect(err).To(BeNil())
models, err = proto.NewOpenAPIData(s)
Expect(err).To(BeNil())
})
model := "io.k8s.api.apps.v1beta1.ControllerRevision"
var schema proto.Schema
It("should lookup the Schema by its model name", func() {
schema = models.LookupModel(model)
Expect(schema).ToNot(BeNil())
})
var cr *proto.Kind
It("data property should be map[string]Arbitrary", func() {
cr = schema.(*proto.Kind)
Expect(cr).ToNot(BeNil())
Expect(cr.Fields).To(HaveKey("data"))
data := cr.Fields["data"].(*proto.Map)
Expect(data).ToNot(BeNil())
Expect(data.GetName()).To(Equal("Map of Arbitrary value (primitive, object or array)"))
Expect(data.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.ControllerRevision", ".data"}))
arbitrary := data.SubType.(*proto.Arbitrary)
Expect(arbitrary).ToNot(BeNil())
Expect(arbitrary.GetName()).To(Equal("Arbitrary value (primitive, object or array)"))
Expect(arbitrary.GetPath().Get()).To(Equal([]string{"io.k8s.api.apps.v1beta1.ControllerRevision", ".data"}))
})
})
var _ = Describe("Reading authorization.k8s.io/v1/SubjectAccessReview from openAPIData", func() {
var models proto.Models
BeforeEach(func() {
s, err := fakeSchema.OpenAPISchema()
Expect(err).To(BeNil())
models, err = proto.NewOpenAPIData(s)
Expect(err).To(BeNil())
})
model := "io.k8s.api.authorization.v1.LocalSubjectAccessReview"
var schema proto.Schema
It("should lookup the Schema by its model", func() {
schema = models.LookupModel(model)
Expect(schema).ToNot(BeNil())
})
var sarspec *proto.Kind
It("should be a Kind and have a spec", func() {
sar := schema.(*proto.Kind)
Expect(sar).ToNot(BeNil())
Expect(sar.Fields).To(HaveKey("spec"))
specRef := sar.Fields["spec"].(proto.Reference)
Expect(specRef).ToNot(BeNil())
Expect(specRef.Reference()).To(Equal("io.k8s.api.authorization.v1.SubjectAccessReviewSpec"))
sarspec = specRef.SubSchema().(*proto.Kind)
Expect(sarspec).ToNot(BeNil())
})
It("should have a valid SubjectAccessReviewSpec", func() {
Expect(sarspec.Fields).To(HaveKey("extra"))
extra := sarspec.Fields["extra"].(*proto.Map)
Expect(extra).ToNot(BeNil())
Expect(extra.GetName()).To(Equal("Map of Array of string"))
Expect(extra.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"}))
array := extra.SubType.(*proto.Array)
Expect(array).ToNot(BeNil())
Expect(array.GetName()).To(Equal("Array of string"))
Expect(array.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"}))
str := array.SubType.(*proto.Primitive)
Expect(str).ToNot(BeNil())
Expect(str.Type).To(Equal("string"))
Expect(str.GetName()).To(Equal("string"))
Expect(str.GetPath().Get()).To(Equal([]string{"io.k8s.api.authorization.v1.SubjectAccessReviewSpec", ".extra"}))
})
})
var _ = Describe("Path", func() {
It("can be created by NewPath", func() {
path := proto.NewPath("key")
Expect(path.String()).To(Equal("key"))
})
It("can create and print complex paths", func() {
key := proto.NewPath("key")
array := key.ArrayPath(12)
field := array.FieldPath("subKey")
Expect(field.String()).To(Equal("key[12].subKey"))
})
It("has a length", func() {
key := proto.NewPath("key")
array := key.ArrayPath(12)
field := array.FieldPath("subKey")
Expect(field.Len()).To(Equal(3))
})
It("can look like an array", func() {
key := proto.NewPath("key")
array := key.ArrayPath(12)
field := array.FieldPath("subKey")
Expect(field.Get()).To(Equal([]string{"key", "[12]", ".subKey"}))
})
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"io/ioutil"
"os"
"sync"
yaml "gopkg.in/yaml.v2"
"github.com/googleapis/gnostic/OpenAPIv2"
"github.com/googleapis/gnostic/compiler"
)
// Fake opens and returns a openapi swagger from a file Path. It will
// parse only once and then return the same copy everytime.
type Fake struct {
Path string
once sync.Once
document *openapi_v2.Document
err error
}
// OpenAPISchema returns the openapi document and a potential error.
func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) {
f.once.Do(func() {
_, err := os.Stat(f.Path)
if err != nil {
f.err = err
return
}
spec, err := ioutil.ReadFile(f.Path)
if err != nil {
f.err = err
return
}
var info yaml.MapSlice
err = yaml.Unmarshal(spec, &info)
if err != nil {
f.err = err
return
}
f.document, f.err = openapi_v2.NewDocument(info, compiler.NewContext("$root", nil))
})
return f.document, f.err
}
type Empty struct{}
func (Empty) OpenAPISchema() (*openapi_v2.Document, error) {
return nil, nil
}

View File

@@ -1,79 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"fmt"
)
type errors struct {
errors []error
}
func (e *errors) Errors() []error {
return e.errors
}
func (e *errors) AppendErrors(err ...error) {
e.errors = append(e.errors, err...)
}
type ValidationError struct {
Path string
Err error
}
func (e ValidationError) Error() string {
return fmt.Sprintf("ValidationError(%s): %v", e.Path, e.Err)
}
type InvalidTypeError struct {
Path string
Expected string
Actual string
}
func (e InvalidTypeError) Error() string {
return fmt.Sprintf("invalid type for %s: got %q, expected %q", e.Path, e.Actual, e.Expected)
}
type MissingRequiredFieldError struct {
Path string
Field string
}
func (e MissingRequiredFieldError) Error() string {
return fmt.Sprintf("missing required field %q in %s", e.Field, e.Path)
}
type UnknownFieldError struct {
Path string
Field string
}
func (e UnknownFieldError) Error() string {
return fmt.Sprintf("unknown field %q in %s", e.Field, e.Path)
}
type InvalidObjectTypeError struct {
Path string
Type string
}
func (e InvalidObjectTypeError) Error() string {
return fmt.Sprintf("unknown object type %q in %s", e.Type, e.Path)
}

View File

@@ -1,298 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"reflect"
"sort"
"k8s.io/kube-openapi/pkg/util/proto"
)
type validationItem interface {
proto.SchemaVisitor
Errors() []error
Path() *proto.Path
}
type baseItem struct {
errors errors
path proto.Path
}
// Errors returns the list of errors found for this item.
func (item *baseItem) Errors() []error {
return item.errors.Errors()
}
// AddValidationError wraps the given error into a ValidationError and
// attaches it to this item.
func (item *baseItem) AddValidationError(err error) {
item.errors.AppendErrors(ValidationError{Path: item.path.String(), Err: err})
}
// AddError adds a regular (non-validation related) error to the list.
func (item *baseItem) AddError(err error) {
item.errors.AppendErrors(err)
}
// CopyErrors adds a list of errors to this item. This is useful to copy
// errors from subitems.
func (item *baseItem) CopyErrors(errs []error) {
item.errors.AppendErrors(errs...)
}
// Path returns the path of this item, helps print useful errors.
func (item *baseItem) Path() *proto.Path {
return &item.path
}
// mapItem represents a map entry in the yaml.
type mapItem struct {
baseItem
Map map[string]interface{}
}
func (item *mapItem) sortedKeys() []string {
sortedKeys := []string{}
for key := range item.Map {
sortedKeys = append(sortedKeys, key)
}
sort.Strings(sortedKeys)
return sortedKeys
}
var _ validationItem = &mapItem{}
func (item *mapItem) VisitPrimitive(schema *proto.Primitive) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: "map"})
}
func (item *mapItem) VisitArray(schema *proto.Array) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "array", Actual: "map"})
}
func (item *mapItem) VisitMap(schema *proto.Map) {
for _, key := range item.sortedKeys() {
subItem, err := itemFactory(item.Path().FieldPath(key), item.Map[key])
if err != nil {
item.AddError(err)
continue
}
schema.SubType.Accept(subItem)
item.CopyErrors(subItem.Errors())
}
}
func (item *mapItem) VisitKind(schema *proto.Kind) {
// Verify each sub-field.
for _, key := range item.sortedKeys() {
if item.Map[key] == nil {
continue
}
subItem, err := itemFactory(item.Path().FieldPath(key), item.Map[key])
if err != nil {
item.AddError(err)
continue
}
if _, ok := schema.Fields[key]; !ok {
item.AddValidationError(UnknownFieldError{Path: schema.GetPath().String(), Field: key})
continue
}
schema.Fields[key].Accept(subItem)
item.CopyErrors(subItem.Errors())
}
// Verify that all required fields are present.
for _, required := range schema.RequiredFields {
if v, ok := item.Map[required]; !ok || v == nil {
item.AddValidationError(MissingRequiredFieldError{Path: schema.GetPath().String(), Field: required})
}
}
}
func (item *mapItem) VisitArbitrary(schema *proto.Arbitrary) {
}
func (item *mapItem) VisitReference(schema proto.Reference) {
// passthrough
schema.SubSchema().Accept(item)
}
// arrayItem represents a yaml array.
type arrayItem struct {
baseItem
Array []interface{}
}
var _ validationItem = &arrayItem{}
func (item *arrayItem) VisitPrimitive(schema *proto.Primitive) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: "array"})
}
func (item *arrayItem) VisitArray(schema *proto.Array) {
for i, v := range item.Array {
path := item.Path().ArrayPath(i)
if v == nil {
item.AddValidationError(InvalidObjectTypeError{Type: "nil", Path: path.String()})
continue
}
subItem, err := itemFactory(path, v)
if err != nil {
item.AddError(err)
continue
}
schema.SubType.Accept(subItem)
item.CopyErrors(subItem.Errors())
}
}
func (item *arrayItem) VisitMap(schema *proto.Map) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: "array"})
}
func (item *arrayItem) VisitKind(schema *proto.Kind) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: "array"})
}
func (item *arrayItem) VisitArbitrary(schema *proto.Arbitrary) {
}
func (item *arrayItem) VisitReference(schema proto.Reference) {
// passthrough
schema.SubSchema().Accept(item)
}
// primitiveItem represents a yaml value.
type primitiveItem struct {
baseItem
Value interface{}
Kind string
}
var _ validationItem = &primitiveItem{}
func (item *primitiveItem) VisitPrimitive(schema *proto.Primitive) {
// Some types of primitives can match more than one (a number
// can be a string, but not the other way around). Return from
// the switch if we have a valid possible type conversion
// NOTE(apelisse): This logic is blindly copied from the
// existing swagger logic, and I'm not sure I agree with it.
switch schema.Type {
case proto.Boolean:
switch item.Kind {
case proto.Boolean:
return
}
case proto.Integer:
switch item.Kind {
case proto.Integer, proto.Number:
return
}
case proto.Number:
switch item.Kind {
case proto.Number:
return
}
case proto.String:
return
}
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: item.Kind})
}
func (item *primitiveItem) VisitArray(schema *proto.Array) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "array", Actual: item.Kind})
}
func (item *primitiveItem) VisitMap(schema *proto.Map) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: item.Kind})
}
func (item *primitiveItem) VisitKind(schema *proto.Kind) {
item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: item.Kind})
}
func (item *primitiveItem) VisitArbitrary(schema *proto.Arbitrary) {
}
func (item *primitiveItem) VisitReference(schema proto.Reference) {
// passthrough
schema.SubSchema().Accept(item)
}
// itemFactory creates the relevant item type/visitor based on the current yaml type.
func itemFactory(path proto.Path, v interface{}) (validationItem, error) {
// We need to special case for no-type fields in yaml (e.g. empty item in list)
if v == nil {
return nil, InvalidObjectTypeError{Type: "nil", Path: path.String()}
}
kind := reflect.TypeOf(v).Kind()
switch kind {
case reflect.Bool:
return &primitiveItem{
baseItem: baseItem{path: path},
Value: v,
Kind: proto.Boolean,
}, nil
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64,
reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64:
return &primitiveItem{
baseItem: baseItem{path: path},
Value: v,
Kind: proto.Integer,
}, nil
case reflect.Float32,
reflect.Float64:
return &primitiveItem{
baseItem: baseItem{path: path},
Value: v,
Kind: proto.Number,
}, nil
case reflect.String:
return &primitiveItem{
baseItem: baseItem{path: path},
Value: v,
Kind: proto.String,
}, nil
case reflect.Array,
reflect.Slice:
return &arrayItem{
baseItem: baseItem{path: path},
Array: v.([]interface{}),
}, nil
case reflect.Map:
return &mapItem{
baseItem: baseItem{path: path},
Map: v.(map[string]interface{}),
}, nil
}
return nil, InvalidObjectTypeError{Type: kind.String(), Path: path.String()}
}

View File

@@ -1,30 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"k8s.io/kube-openapi/pkg/util/proto"
)
func ValidateModel(obj interface{}, schema proto.Schema, name string) []error {
rootValidation, err := itemFactory(proto.NewPath(name), obj)
if err != nil {
return []error{err}
}
schema.Accept(rootValidation)
return rootValidation.Errors()
}

View File

@@ -1,49 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/config"
. "github.com/onsi/ginkgo/types"
. "github.com/onsi/gomega"
"fmt"
"testing"
)
func TestOpenapi(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecsWithDefaultAndCustomReporters(t, "Openapi Suite", []Reporter{newlineReporter{}})
}
// Print a newline after the default newlineReporter due to issue
// https://github.com/jstemmer/go-junit-report/issues/31
type newlineReporter struct{}
func (newlineReporter) SpecSuiteWillBegin(config GinkgoConfigType, summary *SuiteSummary) {}
func (newlineReporter) BeforeSuiteDidRun(setupSummary *SetupSummary) {}
func (newlineReporter) AfterSuiteDidRun(setupSummary *SetupSummary) {}
func (newlineReporter) SpecWillRun(specSummary *SpecSummary) {}
func (newlineReporter) SpecDidComplete(specSummary *SpecSummary) {}
// SpecSuiteDidEnd Prints a newline between "35 Passed | 0 Failed | 0 Pending | 0 Skipped" and "--- PASS:"
func (newlineReporter) SpecSuiteDidEnd(summary *SuiteSummary) { fmt.Printf("\n") }

View File

@@ -1,369 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation_test
import (
"fmt"
"path/filepath"
"github.com/ghodss/yaml"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/kube-openapi/pkg/util/proto"
"k8s.io/kube-openapi/pkg/util/proto/testing"
"k8s.io/kube-openapi/pkg/util/proto/validation"
)
var fakeSchema = testing.Fake{Path: filepath.Join("..", "testdata", "swagger.json")}
func Validate(models proto.Models, model string, data string) []error {
var obj interface{}
if err := yaml.Unmarshal([]byte(data), &obj); err != nil {
return []error{fmt.Errorf("pre-validation: failed to parse yaml: %v", err)}
}
schema := models.LookupModel(model)
if schema == nil {
return []error{fmt.Errorf("pre-validation: couldn't find model %s", model)}
}
return validation.ValidateModel(obj, schema, model)
}
var _ = Describe("resource validation using OpenAPI Schema", func() {
var models proto.Models
BeforeEach(func() {
s, err := fakeSchema.OpenAPISchema()
Expect(err).To(BeNil())
models, err = proto.NewOpenAPIData(s)
Expect(err).To(BeNil())
})
It("finds Deployment in Schema and validates it", func() {
err := Validate(models, "io.k8s.api.apps.v1beta1.Deployment", `
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
name: redis-master
name: name
spec:
replicas: 1
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis
name: redis
`)
Expect(err).To(BeNil())
})
It("validates a valid pod", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis-master
name: name
spec:
containers:
- args:
- this
- is
- an
- ok
- command
image: gcr.io/fake_project/fake_image:fake_tag
name: master
`)
Expect(err).To(BeNil())
})
It("finds invalid command (string instead of []string) in Json Pod", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "name",
"labels": {
"name": "redis-master"
}
},
"spec": {
"containers": [
{
"name": "master",
"image": "gcr.io/fake_project/fake_image:fake_tag",
"args": "this is a bad command"
}
]
}
}
`)
Expect(err).To(Equal([]error{
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0].args",
Err: validation.InvalidTypeError{
Path: "io.k8s.api.core.v1.Container.args",
Expected: "array",
Actual: "string",
},
},
}))
})
It("fails because hostPort is string instead of int", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "apache-php",
"labels": {
"name": "apache-php"
}
},
"spec": {
"volumes": [{
"name": "shared-disk"
}],
"containers": [
{
"name": "apache-php",
"image": "gcr.io/fake_project/fake_image:fake_tag",
"ports": [
{
"name": "apache",
"hostPort": "13380",
"containerPort": 80,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"name": "shared-disk",
"mountPath": "/var/www/html"
}
]
}
]
}
}
`)
Expect(err).To(Equal([]error{
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0].ports[0].hostPort",
Err: validation.InvalidTypeError{
Path: "io.k8s.api.core.v1.ContainerPort.hostPort",
Expected: "integer",
Actual: "string",
},
},
}))
})
It("fails because volume is not an array of object", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "apache-php",
"labels": {
"name": "apache-php"
}
},
"spec": {
"volumes": [
"name": "shared-disk"
],
"containers": [
{
"name": "apache-php",
"image": "gcr.io/fake_project/fake_image:fake_tag",
"ports": [
{
"name": "apache",
"hostPort": 13380,
"containerPort": 80,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"name": "shared-disk",
"mountPath": "/var/www/html"
}
]
}
]
}
}
`)
Expect(err).To(BeNil())
})
It("fails because some string lists have empty strings", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis-master
name: name
spec:
containers:
- image: gcr.io/fake_project/fake_image:fake_tag
name: master
args:
-
command:
-
`)
Expect(err).To(Equal([]error{
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0].args",
Err: validation.InvalidObjectTypeError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0].args[0]",
Type: "nil",
},
},
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0].command",
Err: validation.InvalidObjectTypeError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0].command[0]",
Type: "nil",
},
},
}))
})
It("fails if required fields are missing", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis-master
name: name
spec:
containers:
- command: ["my", "command"]
`)
Expect(err).To(Equal([]error{
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0]",
Err: validation.MissingRequiredFieldError{
Path: "io.k8s.api.core.v1.Container",
Field: "name",
},
},
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0]",
Err: validation.MissingRequiredFieldError{
Path: "io.k8s.api.core.v1.Container",
Field: "image",
},
},
}))
})
It("fails if required fields are empty", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis-master
name: name
spec:
containers:
- image:
name:
`)
Expect(err).To(Equal([]error{
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0]",
Err: validation.MissingRequiredFieldError{
Path: "io.k8s.api.core.v1.Container",
Field: "name",
},
},
validation.ValidationError{
Path: "io.k8s.api.core.v1.Pod.spec.containers[0]",
Err: validation.MissingRequiredFieldError{
Path: "io.k8s.api.core.v1.Container",
Field: "image",
},
},
}))
})
It("is fine with empty non-mandatory fields", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis-master
name: name
spec:
containers:
- image: image
name: name
command:
`)
Expect(err).To(BeNil())
})
It("fails because apiVersion is not provided", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
kind: Pod
metadata:
name: name
spec:
containers:
- name: name
image: image
`)
Expect(err).To(BeNil())
})
It("fails because apiVersion type is not string and kind is not provided", func() {
err := Validate(models, "io.k8s.api.core.v1.Pod", `
apiVersion: 1
metadata:
name: name
spec:
containers:
- name: name
image: image
`)
Expect(err).To(BeNil())
})
})