mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
remove dup pkg and update reference
This commit is contained in:
parent
006f80e35d
commit
93be3f7735
@ -203,7 +203,6 @@ go_test(
|
|||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubectl/cmd/testing:go_default_library",
|
"//pkg/kubectl/cmd/testing:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
|
||||||
"//pkg/kubectl/plugins:go_default_library",
|
"//pkg/kubectl/plugins:go_default_library",
|
||||||
"//pkg/kubectl/resource:go_default_library",
|
"//pkg/kubectl/resource:go_default_library",
|
||||||
"//pkg/kubectl/util/i18n:go_default_library",
|
"//pkg/kubectl/util/i18n:go_default_library",
|
||||||
@ -237,6 +236,7 @@ go_test(
|
|||||||
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest/watch:go_default_library",
|
"//vendor/k8s.io/client-go/rest/watch:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
"//vendor/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
"//vendor/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -578,7 +578,7 @@ func outputOptsForMappingFromOpenAPI(f cmdutil.Factory, mapping *meta.RESTMappin
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
// Found openapi metadata for this resource
|
// Found openapi metadata for this resource
|
||||||
schema := api.LookupResource(mapping.GroupVersionKind)
|
schema := api.LookupResource(mapping.GroupVersionKind.String())
|
||||||
if schema == nil {
|
if schema == nil {
|
||||||
// Schema not found, return empty columns
|
// Schema not found, return empty columns
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -38,11 +38,11 @@ import (
|
|||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
restclientwatch "k8s.io/client-go/rest/watch"
|
restclientwatch "k8s.io/client-go/rest/watch"
|
||||||
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) {
|
func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) {
|
||||||
@ -217,10 +217,10 @@ func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FakeResources struct {
|
type FakeResources struct {
|
||||||
resources map[schema.GroupVersionKind]openapi.Schema
|
resources map[string]openapi.Schema
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FakeResources) LookupResource(s schema.GroupVersionKind) openapi.Schema {
|
func (f FakeResources) LookupResource(s string) openapi.Schema {
|
||||||
return f.resources[s]
|
return f.resources[s]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,11 +228,11 @@ var _ openapi.Resources = &FakeResources{}
|
|||||||
|
|
||||||
func testOpenAPISchemaData() (openapi.Resources, error) {
|
func testOpenAPISchemaData() (openapi.Resources, error) {
|
||||||
return &FakeResources{
|
return &FakeResources{
|
||||||
resources: map[schema.GroupVersionKind]openapi.Schema{
|
resources: map[string]openapi.Schema{
|
||||||
{
|
schema.GroupVersionKind{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
}: &openapi.Primitive{
|
}.String(): &openapi.Primitive{
|
||||||
BaseSchema: openapi.BaseSchema{
|
BaseSchema: openapi.BaseSchema{
|
||||||
Extensions: map[string]interface{}{
|
Extensions: map[string]interface{}{
|
||||||
"x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion",
|
"x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion",
|
||||||
|
@ -19,7 +19,6 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
|
||||||
"//pkg/kubectl/plugins:go_default_library",
|
"//pkg/kubectl/plugins:go_default_library",
|
||||||
"//pkg/kubectl/resource:go_default_library",
|
"//pkg/kubectl/resource:go_default_library",
|
||||||
"//pkg/kubectl/validation:go_default_library",
|
"//pkg/kubectl/validation:go_default_library",
|
||||||
@ -38,6 +37,7 @@ go_library(
|
|||||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,13 +37,13 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/plugins"
|
"k8s.io/kubernetes/pkg/kubectl/plugins"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/validation"
|
"k8s.io/kubernetes/pkg/kubectl/validation"
|
||||||
|
@ -71,6 +71,7 @@ go_library(
|
|||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/util/homedir:go_default_library",
|
"//vendor/k8s.io/client-go/util/homedir:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -46,13 +46,13 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/plugins"
|
"k8s.io/kubernetes/pkg/kubectl/plugins"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/validation"
|
"k8s.io/kubernetes/pkg/kubectl/validation"
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
|
oapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
"k8s.io/kubernetes/federation/apis/federation"
|
"k8s.io/kubernetes/federation/apis/federation"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/apps"
|
"k8s.io/kubernetes/pkg/apis/apps"
|
||||||
@ -453,7 +454,7 @@ func (f *ring1Factory) SwaggerSchema(gvk schema.GroupVersionKind) (*swagger.ApiD
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OpenAPISchema returns metadata and structural information about Kubernetes object definitions.
|
// OpenAPISchema returns metadata and structural information about Kubernetes object definitions.
|
||||||
func (f *ring1Factory) OpenAPISchema() (openapi.Resources, error) {
|
func (f *ring1Factory) OpenAPISchema() (oapi.Resources, error) {
|
||||||
discovery, err := f.clientAccessFactory.DiscoveryClient()
|
discovery, err := f.clientAccessFactory.DiscoveryClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -10,17 +10,16 @@ go_library(
|
|||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"document.go",
|
|
||||||
"extensions.go",
|
"extensions.go",
|
||||||
"openapi.go",
|
"gvk.go",
|
||||||
"openapi_getter.go",
|
"openapi_getter.go",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//vendor/github.com/go-openapi/spec:go_default_library",
|
"//vendor/github.com/go-openapi/spec:go_default_library",
|
||||||
"//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
|
"//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
|
||||||
"//vendor/gopkg.in/yaml.v2:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,17 +29,16 @@ go_test(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"openapi_getter_test.go",
|
"openapi_getter_test.go",
|
||||||
"openapi_suite_test.go",
|
"openapi_suite_test.go",
|
||||||
"openapi_test.go",
|
|
||||||
],
|
],
|
||||||
data = ["//api/openapi-spec:swagger-spec"],
|
data = ["//api/openapi-spec:swagger-spec"],
|
||||||
deps = [
|
deps = [
|
||||||
":go_default_library",
|
":go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
|
|
||||||
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
||||||
"//vendor/github.com/onsi/ginkgo/config:go_default_library",
|
"//vendor/github.com/onsi/ginkgo/config:go_default_library",
|
||||||
"//vendor/github.com/onsi/ginkgo/types:go_default_library",
|
"//vendor/github.com/onsi/ginkgo/types:go_default_library",
|
||||||
"//vendor/github.com/onsi/gomega:go_default_library",
|
"//vendor/github.com/onsi/gomega:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,7 +53,6 @@ filegroup(
|
|||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [
|
srcs = [
|
||||||
":package-srcs",
|
":package-srcs",
|
||||||
"//pkg/kubectl/cmd/util/openapi/testing:all-srcs",
|
|
||||||
"//pkg/kubectl/cmd/util/openapi/validation:all-srcs",
|
"//pkg/kubectl/cmd/util/openapi/validation:all-srcs",
|
||||||
],
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
|
@ -1,330 +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 openapi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newSchemaError(path *Path, format string, a ...interface{}) error {
|
|
||||||
err := fmt.Sprintf(format, a...)
|
|
||||||
if path.Len() == 0 {
|
|
||||||
return fmt.Errorf("SchemaError: %v", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("SchemaError(%v): %v", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// groupVersionKindExtensionKey is the key used to lookup the
|
|
||||||
// GroupVersionKind value for an object definition from the
|
|
||||||
// definition's "extensions" map.
|
|
||||||
const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind"
|
|
||||||
|
|
||||||
func vendorExtensionToMap(e []*openapi_v2.NamedAny) map[string]interface{} {
|
|
||||||
values := map[string]interface{}{}
|
|
||||||
|
|
||||||
for _, na := range e {
|
|
||||||
if na.GetName() == "" || na.GetValue() == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if na.GetValue().GetYaml() == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var value interface{}
|
|
||||||
err := yaml.Unmarshal([]byte(na.GetValue().GetYaml()), &value)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
values[na.GetName()] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get and parse GroupVersionKind from the extension. Returns empty if it doesn't have one.
|
|
||||||
func parseGroupVersionKind(s *openapi_v2.Schema) schema.GroupVersionKind {
|
|
||||||
extensionMap := vendorExtensionToMap(s.GetVendorExtension())
|
|
||||||
|
|
||||||
// Get the extensions
|
|
||||||
gvkExtension, ok := extensionMap[groupVersionKindExtensionKey]
|
|
||||||
if !ok {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// gvk extension must be a list of 1 element.
|
|
||||||
gvkList, ok := gvkExtension.([]interface{})
|
|
||||||
if !ok {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
}
|
|
||||||
if len(gvkList) != 1 {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
|
|
||||||
}
|
|
||||||
gvk := gvkList[0]
|
|
||||||
|
|
||||||
// gvk extension list must be a map with group, version, and
|
|
||||||
// kind fields
|
|
||||||
gvkMap, ok := gvk.(map[interface{}]interface{})
|
|
||||||
if !ok {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
}
|
|
||||||
group, ok := gvkMap["group"].(string)
|
|
||||||
if !ok {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
}
|
|
||||||
version, ok := gvkMap["version"].(string)
|
|
||||||
if !ok {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
}
|
|
||||||
kind, ok := gvkMap["kind"].(string)
|
|
||||||
if !ok {
|
|
||||||
return schema.GroupVersionKind{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return schema.GroupVersionKind{
|
|
||||||
Group: group,
|
|
||||||
Version: version,
|
|
||||||
Kind: kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Definitions is an implementation of `Resources`. It looks for
|
|
||||||
// resources in an openapi Schema.
|
|
||||||
type Definitions struct {
|
|
||||||
models map[string]Schema
|
|
||||||
resources map[schema.GroupVersionKind]string
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Resources = &Definitions{}
|
|
||||||
|
|
||||||
// NewOpenAPIData creates a new `Resources` out of the openapi document.
|
|
||||||
func NewOpenAPIData(doc *openapi_v2.Document) (Resources, error) {
|
|
||||||
definitions := Definitions{
|
|
||||||
models: map[string]Schema{},
|
|
||||||
resources: map[schema.GroupVersionKind]string{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the list of all models first. This will allow us to
|
|
||||||
// validate that we don't have any dangling reference.
|
|
||||||
for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() {
|
|
||||||
definitions.models[namedSchema.GetName()] = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, parse each model. We can validate that references exists.
|
|
||||||
for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() {
|
|
||||||
path := NewPath(namedSchema.GetName())
|
|
||||||
schema, err := definitions.ParseSchema(namedSchema.GetValue(), &path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
definitions.models[namedSchema.GetName()] = schema
|
|
||||||
gvk := parseGroupVersionKind(namedSchema.GetValue())
|
|
||||||
if len(gvk.Kind) > 0 {
|
|
||||||
definitions.resources[gvk] = namedSchema.GetName()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &definitions, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We believe the schema is a reference, verify that and returns a new
|
|
||||||
// Schema
|
|
||||||
func (d *Definitions) parseReference(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
|
||||||
if len(s.GetProperties().GetAdditionalProperties()) > 0 {
|
|
||||||
return nil, newSchemaError(path, "unallowed embedded type definition")
|
|
||||||
}
|
|
||||||
if len(s.GetType().GetValue()) > 0 {
|
|
||||||
return nil, newSchemaError(path, "definition reference can't have a type")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasPrefix(s.GetXRef(), "#/definitions/") {
|
|
||||||
return nil, newSchemaError(path, "unallowed reference to non-definition %q", s.GetXRef())
|
|
||||||
}
|
|
||||||
reference := strings.TrimPrefix(s.GetXRef(), "#/definitions/")
|
|
||||||
if _, ok := d.models[reference]; !ok {
|
|
||||||
return nil, newSchemaError(path, "unknown model in reference: %q", reference)
|
|
||||||
}
|
|
||||||
return &Ref{
|
|
||||||
BaseSchema: d.parseBaseSchema(s, path),
|
|
||||||
reference: reference,
|
|
||||||
definitions: d,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Definitions) parseBaseSchema(s *openapi_v2.Schema, path *Path) BaseSchema {
|
|
||||||
return BaseSchema{
|
|
||||||
Description: s.GetDescription(),
|
|
||||||
Extensions: vendorExtensionToMap(s.GetVendorExtension()),
|
|
||||||
Path: *path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We believe the schema is a map, verify and return a new schema
|
|
||||||
func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
|
||||||
if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object {
|
|
||||||
return nil, newSchemaError(path, "invalid object type")
|
|
||||||
}
|
|
||||||
if s.GetAdditionalProperties().GetSchema() == nil {
|
|
||||||
return nil, newSchemaError(path, "invalid object doesn't have additional properties")
|
|
||||||
}
|
|
||||||
sub, err := d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Map{
|
|
||||||
BaseSchema: d.parseBaseSchema(s, path),
|
|
||||||
SubType: sub,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
|
||||||
var t string
|
|
||||||
if len(s.GetType().GetValue()) > 1 {
|
|
||||||
return nil, newSchemaError(path, "primitive can't have more than 1 type")
|
|
||||||
}
|
|
||||||
if len(s.GetType().GetValue()) == 1 {
|
|
||||||
t = s.GetType().GetValue()[0]
|
|
||||||
}
|
|
||||||
switch t {
|
|
||||||
case String:
|
|
||||||
case Number:
|
|
||||||
case Integer:
|
|
||||||
case Boolean:
|
|
||||||
case "": // Some models are completely empty, and can be safely ignored.
|
|
||||||
// Do nothing
|
|
||||||
default:
|
|
||||||
return nil, newSchemaError(path, "Unknown primitive type: %q", t)
|
|
||||||
}
|
|
||||||
return &Primitive{
|
|
||||||
BaseSchema: d.parseBaseSchema(s, path),
|
|
||||||
Type: t,
|
|
||||||
Format: s.GetFormat(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Definitions) parseArray(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
|
||||||
if len(s.GetType().GetValue()) != 1 {
|
|
||||||
return nil, newSchemaError(path, "array should have exactly one type")
|
|
||||||
}
|
|
||||||
if s.GetType().GetValue()[0] != array {
|
|
||||||
return nil, newSchemaError(path, `array should have type "array"`)
|
|
||||||
}
|
|
||||||
if len(s.GetItems().GetSchema()) != 1 {
|
|
||||||
return nil, newSchemaError(path, "array should have exactly one sub-item")
|
|
||||||
}
|
|
||||||
sub, err := d.ParseSchema(s.GetItems().GetSchema()[0], path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Array{
|
|
||||||
BaseSchema: d.parseBaseSchema(s, path),
|
|
||||||
SubType: sub,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
|
||||||
if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object {
|
|
||||||
return nil, newSchemaError(path, "invalid object type")
|
|
||||||
}
|
|
||||||
if s.GetProperties() == nil {
|
|
||||||
return nil, newSchemaError(path, "object doesn't have properties")
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := map[string]Schema{}
|
|
||||||
|
|
||||||
for _, namedSchema := range s.GetProperties().GetAdditionalProperties() {
|
|
||||||
var err error
|
|
||||||
path := path.FieldPath(namedSchema.GetName())
|
|
||||||
fields[namedSchema.GetName()], err = d.ParseSchema(namedSchema.GetValue(), &path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Kind{
|
|
||||||
BaseSchema: d.parseBaseSchema(s, path),
|
|
||||||
RequiredFields: s.GetRequired(),
|
|
||||||
Fields: fields,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSchema creates a walkable Schema from an openapi schema. While
|
|
||||||
// this function is public, it doesn't leak through the interface.
|
|
||||||
func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
|
||||||
if len(s.GetType().GetValue()) == 1 {
|
|
||||||
t := s.GetType().GetValue()[0]
|
|
||||||
switch t {
|
|
||||||
case object:
|
|
||||||
return d.parseMap(s, path)
|
|
||||||
case array:
|
|
||||||
return d.parseArray(s, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if s.GetXRef() != "" {
|
|
||||||
return d.parseReference(s, path)
|
|
||||||
}
|
|
||||||
if s.GetProperties() != nil {
|
|
||||||
return d.parseKind(s, path)
|
|
||||||
}
|
|
||||||
return d.parsePrimitive(s, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupResource is public through the interface of Resources. It
|
|
||||||
// returns a visitable schema from the given group-version-kind.
|
|
||||||
func (d *Definitions) LookupResource(gvk schema.GroupVersionKind) Schema {
|
|
||||||
modelName, found := d.resources[gvk]
|
|
||||||
if !found {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
model, found := d.models[modelName]
|
|
||||||
if !found {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ref struct {
|
|
||||||
BaseSchema
|
|
||||||
|
|
||||||
reference string
|
|
||||||
definitions *Definitions
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Reference = &Ref{}
|
|
||||||
|
|
||||||
func (r *Ref) Reference() string {
|
|
||||||
return r.reference
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Ref) SubSchema() Schema {
|
|
||||||
return r.definitions.models[r.reference]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Ref) Accept(v SchemaVisitor) {
|
|
||||||
v.VisitReference(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Ref) GetName() string {
|
|
||||||
return fmt.Sprintf("Reference to %q", r.reference)
|
|
||||||
}
|
|
73
pkg/kubectl/cmd/util/openapi/gvk.go
Normal file
73
pkg/kubectl/cmd/util/openapi/gvk.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
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 openapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind"
|
||||||
|
|
||||||
|
// Get and parse GroupVersionKind from the extension. Returns empty if it doesn't have one.
|
||||||
|
func ParseGroupVersionKind(s *openapi_v2.Schema) string {
|
||||||
|
extensionMap := openapi.VendorExtensionToMap(s.GetVendorExtension())
|
||||||
|
|
||||||
|
// Get the extensions
|
||||||
|
gvkExtension, ok := extensionMap[groupVersionKindExtensionKey]
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// gvk extension must be a list of 1 element.
|
||||||
|
gvkList, ok := gvkExtension.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(gvkList) != 1 {
|
||||||
|
return ""
|
||||||
|
|
||||||
|
}
|
||||||
|
gvk := gvkList[0]
|
||||||
|
|
||||||
|
// gvk extension list must be a map with group, version, and
|
||||||
|
// kind fields
|
||||||
|
gvkMap, ok := gvk.(map[interface{}]interface{})
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
group, ok := gvkMap["group"].(string)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
version, ok := gvkMap["version"].(string)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
kind, ok := gvkMap["kind"].(string)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema.GroupVersionKind{
|
||||||
|
Group: group,
|
||||||
|
Version: version,
|
||||||
|
Kind: kind,
|
||||||
|
}.String()
|
||||||
|
}
|
@ -1,231 +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 openapi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Defines openapi types.
|
|
||||||
const (
|
|
||||||
Integer = "integer"
|
|
||||||
Number = "number"
|
|
||||||
String = "string"
|
|
||||||
Boolean = "boolean"
|
|
||||||
|
|
||||||
// These types are private as they should never leak, and are
|
|
||||||
// represented by actual structs.
|
|
||||||
array = "array"
|
|
||||||
object = "object"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Resources interface describe a resources provider, that can give you
|
|
||||||
// resource based on group-version-kind.
|
|
||||||
type Resources interface {
|
|
||||||
LookupResource(gvk schema.GroupVersionKind) Schema
|
|
||||||
}
|
|
||||||
|
|
||||||
// SchemaVisitor is an interface that you need to implement if you want
|
|
||||||
// to "visit" an openapi schema. A dispatch on the Schema type will call
|
|
||||||
// the appropriate function based on its actual type:
|
|
||||||
// - Array is a list of one and only one given subtype
|
|
||||||
// - Map is a map of string to one and only one given subtype
|
|
||||||
// - Primitive can be string, integer, number and boolean.
|
|
||||||
// - Kind is an object with specific fields mapping to specific types.
|
|
||||||
// - Reference is a link to another definition.
|
|
||||||
type SchemaVisitor interface {
|
|
||||||
VisitArray(*Array)
|
|
||||||
VisitMap(*Map)
|
|
||||||
VisitPrimitive(*Primitive)
|
|
||||||
VisitKind(*Kind)
|
|
||||||
VisitReference(Reference)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schema is the base definition of an openapi type.
|
|
||||||
type Schema interface {
|
|
||||||
// Giving a visitor here will let you visit the actual type.
|
|
||||||
Accept(SchemaVisitor)
|
|
||||||
|
|
||||||
// Pretty print the name of the type.
|
|
||||||
GetName() string
|
|
||||||
// Describes how to access this field.
|
|
||||||
GetPath() *Path
|
|
||||||
// Describes the field.
|
|
||||||
GetDescription() string
|
|
||||||
// Returns type extensions.
|
|
||||||
GetExtensions() map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path helps us keep track of type paths
|
|
||||||
type Path struct {
|
|
||||||
parent *Path
|
|
||||||
key string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPath(key string) Path {
|
|
||||||
return Path{key: key}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) Get() []string {
|
|
||||||
if p == nil {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
if p.key == "" {
|
|
||||||
return p.parent.Get()
|
|
||||||
}
|
|
||||||
return append(p.parent.Get(), p.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) Len() int {
|
|
||||||
return len(p.Get())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) String() string {
|
|
||||||
return strings.Join(p.Get(), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayPath appends an array index and creates a new path
|
|
||||||
func (p *Path) ArrayPath(i int) Path {
|
|
||||||
return Path{
|
|
||||||
parent: p,
|
|
||||||
key: fmt.Sprintf("[%d]", i),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FieldPath appends a field name and creates a new path
|
|
||||||
func (p *Path) FieldPath(field string) Path {
|
|
||||||
return Path{
|
|
||||||
parent: p,
|
|
||||||
key: fmt.Sprintf(".%s", field),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BaseSchema holds data used by each types of schema.
|
|
||||||
type BaseSchema struct {
|
|
||||||
Description string
|
|
||||||
Extensions map[string]interface{}
|
|
||||||
|
|
||||||
Path Path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BaseSchema) GetDescription() string {
|
|
||||||
return b.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BaseSchema) GetExtensions() map[string]interface{} {
|
|
||||||
return b.Extensions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BaseSchema) GetPath() *Path {
|
|
||||||
return &b.Path
|
|
||||||
}
|
|
||||||
|
|
||||||
// Array must have all its element of the same `SubType`.
|
|
||||||
type Array struct {
|
|
||||||
BaseSchema
|
|
||||||
|
|
||||||
SubType Schema
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Schema = &Array{}
|
|
||||||
|
|
||||||
func (a *Array) Accept(v SchemaVisitor) {
|
|
||||||
v.VisitArray(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Array) GetName() string {
|
|
||||||
return fmt.Sprintf("Array of %s", a.SubType.GetName())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kind is a complex object. It can have multiple different
|
|
||||||
// subtypes for each field, as defined in the `Fields` field. Mandatory
|
|
||||||
// fields are listed in `RequiredFields`. The key of the object is
|
|
||||||
// always of type `string`.
|
|
||||||
type Kind struct {
|
|
||||||
BaseSchema
|
|
||||||
|
|
||||||
// Lists names of required fields.
|
|
||||||
RequiredFields []string
|
|
||||||
// Maps field names to types.
|
|
||||||
Fields map[string]Schema
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Schema = &Kind{}
|
|
||||||
|
|
||||||
func (k *Kind) Accept(v SchemaVisitor) {
|
|
||||||
v.VisitKind(k)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *Kind) GetName() string {
|
|
||||||
properties := []string{}
|
|
||||||
for key := range k.Fields {
|
|
||||||
properties = append(properties, key)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("Kind(%v)", properties)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map is an object who values must all be of the same `SubType`.
|
|
||||||
// The key of the object is always of type `string`.
|
|
||||||
type Map struct {
|
|
||||||
BaseSchema
|
|
||||||
|
|
||||||
SubType Schema
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Schema = &Map{}
|
|
||||||
|
|
||||||
func (m *Map) Accept(v SchemaVisitor) {
|
|
||||||
v.VisitMap(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Map) GetName() string {
|
|
||||||
return fmt.Sprintf("Map of %s", m.SubType.GetName())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Primitive is a literal. There can be multiple types of primitives,
|
|
||||||
// and this subtype can be visited through the `subType` field.
|
|
||||||
type Primitive struct {
|
|
||||||
BaseSchema
|
|
||||||
|
|
||||||
// Type of a primitive must be one of: integer, number, string, boolean.
|
|
||||||
Type string
|
|
||||||
Format string
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Schema = &Primitive{}
|
|
||||||
|
|
||||||
func (p *Primitive) Accept(v SchemaVisitor) {
|
|
||||||
v.VisitPrimitive(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Primitive) GetName() string {
|
|
||||||
if p.Format == "" {
|
|
||||||
return p.Type
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s (%s)", p.Type, p.Format)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference implementation depends on the type of document.
|
|
||||||
type Reference interface {
|
|
||||||
Schema
|
|
||||||
|
|
||||||
Reference() string
|
|
||||||
SubSchema() Schema
|
|
||||||
}
|
|
@ -20,13 +20,14 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// synchronizedOpenAPIGetter fetches the openapi schema once and then caches it in memory
|
// synchronizedOpenAPIGetter fetches the openapi schema once and then caches it in memory
|
||||||
type synchronizedOpenAPIGetter struct {
|
type synchronizedOpenAPIGetter struct {
|
||||||
// Cached results
|
// Cached results
|
||||||
sync.Once
|
sync.Once
|
||||||
openAPISchema Resources
|
openAPISchema openapi.Resources
|
||||||
err error
|
err error
|
||||||
|
|
||||||
openAPIClient discovery.OpenAPISchemaInterface
|
openAPIClient discovery.OpenAPISchemaInterface
|
||||||
@ -37,7 +38,7 @@ var _ Getter = &synchronizedOpenAPIGetter{}
|
|||||||
// Getter is an interface for fetching openapi specs and parsing them into an Resources struct
|
// Getter is an interface for fetching openapi specs and parsing them into an Resources struct
|
||||||
type Getter interface {
|
type Getter interface {
|
||||||
// OpenAPIData returns the parsed OpenAPIData
|
// OpenAPIData returns the parsed OpenAPIData
|
||||||
Get() (Resources, error)
|
Get() (openapi.Resources, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOpenAPIGetter returns an object to return OpenAPIDatas which reads
|
// NewOpenAPIGetter returns an object to return OpenAPIDatas which reads
|
||||||
@ -49,7 +50,7 @@ func NewOpenAPIGetter(openAPIClient discovery.OpenAPISchemaInterface) Getter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resources implements Getter
|
// Resources implements Getter
|
||||||
func (g *synchronizedOpenAPIGetter) Get() (Resources, error) {
|
func (g *synchronizedOpenAPIGetter) Get() (openapi.Resources, error) {
|
||||||
g.Do(func() {
|
g.Do(func() {
|
||||||
s, err := g.openAPIClient.OpenAPISchema()
|
s, err := g.openAPIClient.OpenAPISchema()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,7 +58,7 @@ func (g *synchronizedOpenAPIGetter) Get() (Resources, error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
g.openAPISchema, g.err = NewOpenAPIData(s)
|
g.openAPISchema, g.err = openapi.NewOpenAPIData(s, ParseGroupVersionKind)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Return the save result
|
// Return the save result
|
||||||
|
@ -18,17 +18,21 @@ package openapi_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
oapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
|
tst "k8s.io/kube-openapi/pkg/util/proto/testing"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||||
tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var fakeSchema = tst.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")}
|
||||||
|
|
||||||
var _ = Describe("Getting the Resources", func() {
|
var _ = Describe("Getting the Resources", func() {
|
||||||
var client *tst.FakeClient
|
var client *tst.FakeClient
|
||||||
var expectedData openapi.Resources
|
var expectedData oapi.Resources
|
||||||
var instance openapi.Getter
|
var instance openapi.Getter
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -36,7 +40,7 @@ var _ = Describe("Getting the Resources", func() {
|
|||||||
d, err := fakeSchema.OpenAPISchema()
|
d, err := fakeSchema.OpenAPISchema()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
expectedData, err = openapi.NewOpenAPIData(d)
|
expectedData, err = oapi.NewOpenAPIData(d, openapi.ParseGroupVersionKind)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
instance = openapi.NewOpenAPIGetter(client)
|
instance = openapi.NewOpenAPIGetter(client)
|
||||||
|
@ -1,218 +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 openapi_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
|
||||||
tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var fakeSchema = tst.Fake{Path: filepath.Join("..", "..", "..", "..", "..", "api", "openapi-spec", "swagger.json")}
|
|
||||||
|
|
||||||
var _ = Describe("Reading apps/v1beta1/Deployment from openAPIData", func() {
|
|
||||||
var resources openapi.Resources
|
|
||||||
BeforeEach(func() {
|
|
||||||
s, err := fakeSchema.OpenAPISchema()
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
resources, err = openapi.NewOpenAPIData(s)
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
})
|
|
||||||
|
|
||||||
gvk := schema.GroupVersionKind{
|
|
||||||
Kind: "Deployment",
|
|
||||||
Version: "v1beta1",
|
|
||||||
Group: "apps",
|
|
||||||
}
|
|
||||||
|
|
||||||
var schema openapi.Schema
|
|
||||||
It("should lookup the Schema by its GroupVersionKind", func() {
|
|
||||||
schema = resources.LookupResource(gvk)
|
|
||||||
Expect(schema).ToNot(BeNil())
|
|
||||||
})
|
|
||||||
|
|
||||||
var deployment *openapi.Kind
|
|
||||||
It("should be a Kind", func() {
|
|
||||||
deployment = schema.(*openapi.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"].(*openapi.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"].(*openapi.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"].(openapi.Reference)
|
|
||||||
Expect(key).ToNot(BeNil())
|
|
||||||
Expect(key.Reference()).To(Equal("io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"))
|
|
||||||
subSchema := key.SubSchema().(*openapi.Kind)
|
|
||||||
Expect(subSchema).ToNot(BeNil())
|
|
||||||
})
|
|
||||||
|
|
||||||
var status *openapi.Kind
|
|
||||||
It("should have a status key of type Reference", func() {
|
|
||||||
Expect(deployment.Fields).To(HaveKey("status"))
|
|
||||||
key := deployment.Fields["status"].(openapi.Reference)
|
|
||||||
Expect(key).ToNot(BeNil())
|
|
||||||
Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentStatus"))
|
|
||||||
status = key.SubSchema().(*openapi.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"].(*openapi.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"].(*openapi.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.(openapi.Reference)
|
|
||||||
Expect(condition.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentCondition"))
|
|
||||||
})
|
|
||||||
|
|
||||||
var spec *openapi.Kind
|
|
||||||
It("should have a spec key of type Reference", func() {
|
|
||||||
Expect(deployment.Fields).To(HaveKey("spec"))
|
|
||||||
key := deployment.Fields["spec"].(openapi.Reference)
|
|
||||||
Expect(key).ToNot(BeNil())
|
|
||||||
Expect(key.Reference()).To(Equal("io.k8s.api.apps.v1beta1.DeploymentSpec"))
|
|
||||||
spec = key.SubSchema().(*openapi.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"].(openapi.Reference)
|
|
||||||
Expect(key).ToNot(BeNil())
|
|
||||||
Expect(key.Reference()).To(Equal("io.k8s.api.core.v1.PodTemplateSpec"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
var _ = Describe("Reading authorization.k8s.io/v1/SubjectAccessReview from openAPIData", func() {
|
|
||||||
var resources openapi.Resources
|
|
||||||
BeforeEach(func() {
|
|
||||||
s, err := fakeSchema.OpenAPISchema()
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
resources, err = openapi.NewOpenAPIData(s)
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
})
|
|
||||||
|
|
||||||
gvk := schema.GroupVersionKind{
|
|
||||||
Kind: "SubjectAccessReview",
|
|
||||||
Version: "v1",
|
|
||||||
Group: "authorization.k8s.io",
|
|
||||||
}
|
|
||||||
|
|
||||||
var schema openapi.Schema
|
|
||||||
It("should lookup the Schema by its GroupVersionKind", func() {
|
|
||||||
schema = resources.LookupResource(gvk)
|
|
||||||
Expect(schema).ToNot(BeNil())
|
|
||||||
})
|
|
||||||
|
|
||||||
var sarspec *openapi.Kind
|
|
||||||
It("should be a Kind and have a spec", func() {
|
|
||||||
sar := schema.(*openapi.Kind)
|
|
||||||
Expect(sar).ToNot(BeNil())
|
|
||||||
Expect(sar.Fields).To(HaveKey("spec"))
|
|
||||||
specRef := sar.Fields["spec"].(openapi.Reference)
|
|
||||||
Expect(specRef).ToNot(BeNil())
|
|
||||||
Expect(specRef.Reference()).To(Equal("io.k8s.api.authorization.v1.SubjectAccessReviewSpec"))
|
|
||||||
sarspec = specRef.SubSchema().(*openapi.Kind)
|
|
||||||
Expect(sarspec).ToNot(BeNil())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should have a valid SubjectAccessReviewSpec", func() {
|
|
||||||
Expect(sarspec.Fields).To(HaveKey("extra"))
|
|
||||||
extra := sarspec.Fields["extra"].(*openapi.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.(*openapi.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.(*openapi.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 := openapi.NewPath("key")
|
|
||||||
Expect(path.String()).To(Equal("key"))
|
|
||||||
})
|
|
||||||
It("can create and print complex paths", func() {
|
|
||||||
key := openapi.NewPath("key")
|
|
||||||
array := key.ArrayPath(12)
|
|
||||||
field := array.FieldPath("subKey")
|
|
||||||
|
|
||||||
Expect(field.String()).To(Equal("key[12].subKey"))
|
|
||||||
})
|
|
||||||
It("has a length", func() {
|
|
||||||
key := openapi.NewPath("key")
|
|
||||||
array := key.ArrayPath(12)
|
|
||||||
field := array.FieldPath("subKey")
|
|
||||||
|
|
||||||
Expect(field.Len()).To(Equal(3))
|
|
||||||
})
|
|
||||||
It("can look like an array", func() {
|
|
||||||
key := openapi.NewPath("key")
|
|
||||||
array := key.ArrayPath(12)
|
|
||||||
field := array.FieldPath("subKey")
|
|
||||||
|
|
||||||
Expect(field.Get()).To(Equal([]string{"key", "[12]", ".subKey"}))
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,32 +0,0 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
licenses(["notice"])
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = ["openapi.go"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
|
|
||||||
"//vendor/github.com/googleapis/gnostic/compiler:go_default_library",
|
|
||||||
"//vendor/gopkg.in/yaml.v2:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
@ -1,89 +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
|
|
||||||
}
|
|
||||||
|
|
||||||
// FakeClient implements a dummy OpenAPISchemaInterface that uses the
|
|
||||||
// fake OpenAPI schema given as a parameter, and count the number of
|
|
||||||
// call to the function.
|
|
||||||
type FakeClient struct {
|
|
||||||
Calls int
|
|
||||||
Err error
|
|
||||||
|
|
||||||
fake *Fake
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFakeClient creates a new FakeClient from the given Fake.
|
|
||||||
func NewFakeClient(f *Fake) *FakeClient {
|
|
||||||
return &FakeClient{fake: f}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenAPISchema returns a OpenAPI Document as returned by the fake, but
|
|
||||||
// it also counts the number of calls.
|
|
||||||
func (f *FakeClient) OpenAPISchema() (*openapi_v2.Document, error) {
|
|
||||||
f.Calls = f.Calls + 1
|
|
||||||
|
|
||||||
if f.Err != nil {
|
|
||||||
return nil, f.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.fake.OpenAPISchema()
|
|
||||||
}
|
|
@ -19,11 +19,11 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/util:go_default_library",
|
"//pkg/api/util:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,12 +39,13 @@ go_test(
|
|||||||
":go_default_library",
|
":go_default_library",
|
||||||
"//pkg/api/testapi:go_default_library",
|
"//pkg/api/testapi:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
|
|
||||||
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
||||||
"//vendor/github.com/onsi/ginkgo/config:go_default_library",
|
"//vendor/github.com/onsi/ginkgo/config:go_default_library",
|
||||||
"//vendor/github.com/onsi/ginkgo/types:go_default_library",
|
"//vendor/github.com/onsi/ginkgo/types:go_default_library",
|
||||||
"//vendor/github.com/onsi/gomega:go_default_library",
|
"//vendor/github.com/onsi/gomega:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidationItem interface {
|
type ValidationItem interface {
|
||||||
|
@ -25,9 +25,9 @@ import (
|
|||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
"k8s.io/apimachinery/pkg/util/yaml"
|
"k8s.io/apimachinery/pkg/util/yaml"
|
||||||
|
openapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
apiutil "k8s.io/kubernetes/pkg/api/util"
|
apiutil "k8s.io/kubernetes/pkg/api/util"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SchemaValidation struct {
|
type SchemaValidation struct {
|
||||||
@ -82,7 +82,7 @@ func (v *SchemaValidation) validateResource(obj interface{}, gvk schema.GroupVer
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
resource := v.resources.LookupResource(gvk)
|
resource := v.resources.LookupResource(gvk.String())
|
||||||
if resource == nil {
|
if resource == nil {
|
||||||
return []error{fmt.Errorf("unknown object type %#v", gvk)}
|
return []error{fmt.Errorf("unknown object type %#v", gvk)}
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,10 @@ import (
|
|||||||
|
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
// This dependency is needed to register API types.
|
// This dependency is needed to register API types.
|
||||||
|
oapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||||
|
tst "k8s.io/kube-openapi/pkg/util/proto/testing"
|
||||||
_ "k8s.io/kubernetes/pkg/api/testapi"
|
_ "k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||||
tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ var _ = Describe("resource validation using OpenAPI Schema", func() {
|
|||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
s, err := fakeSchema.OpenAPISchema()
|
s, err := fakeSchema.OpenAPISchema()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
resources, err := openapi.NewOpenAPIData(s)
|
resources, err := oapi.NewOpenAPIData(s, openapi.ParseGroupVersionKind)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
validator = validation.NewSchemaValidation(resources)
|
validator = validation.NewSchemaValidation(resources)
|
||||||
Expect(validator).ToNot(BeNil())
|
Expect(validator).ToNot(BeNil())
|
||||||
|
Loading…
Reference in New Issue
Block a user