Merge pull request #46317 from monopole/kubectlValidator

Automatic merge from submit-queue

Remove kubectl's dependence on schema file in pkg/api/validation.

**What this PR does / why we need it**:

Makes functions in validation/schema.go private to kubectl,
further isolating kubectl.  This move revealed a "hidden" dependence
(a dependence not expressed in a BUILD or make file) from a feature
level test in /hack/make-rules on a kubectl test data file.  So this
PR also adds some BUILD rules around the relevant hack targets, to make the
dependence official.  A later PR will move the kubectl aspect of this "hack"
test into a kubectl test directory.  Leaving it in place for now after establishing 
and "official" dependency, since moving the test beyond PR scope.  The
test also depends on a small sh file in //cluster, which makes no sense.

**Which issue this PR fixes**

Part of a series of PRs to address kubernetes/community#598

**Release note**:
```release-note
NONE
```
pull/6/head
Kubernetes Submit Queue 2017-08-16 19:06:17 -07:00 committed by GitHub
commit 225b9119d6
30 changed files with 320 additions and 69 deletions

View File

@ -525,7 +525,7 @@ bazel-build:
@echo "$$BAZEL_BUILD_HELP_INFO" @echo "$$BAZEL_BUILD_HELP_INFO"
else else
bazel-build: bazel-build:
bazel build //cmd/... //pkg/... //federation/... //plugin/... //third_party/... //examples/... //test/... //vendor/k8s.io/... bazel build //cmd/... //hack/... //pkg/... //federation/... //plugin/... //third_party/... //examples/... //test/... //vendor/k8s.io/...
endif endif

View File

@ -47,6 +47,9 @@ package_group(
package_group( package_group(
name = "COMMON_testing", name = "COMMON_testing",
packages = [ packages = [
"//hack",
"//hack/lib",
"//hack/make-rules",
"//test/e2e", "//test/e2e",
"//test/e2e/framework", "//test/e2e/framework",
"//test/e2e/kubectl", "//test/e2e/kubectl",
@ -69,6 +72,13 @@ package_group(
], ],
) )
package_group(
name = "cluster",
packages = [
"//cluster/...",
],
)
package_group( package_group(
name = "KUBEADM_BAD", name = "KUBEADM_BAD",
packages = [ packages = [
@ -363,6 +373,16 @@ package_group(
], ],
) )
package_group(
name = "pkg_kubectl_validation_CONSUMERS",
packages = [
"//pkg/kubectl",
"//pkg/kubectl/cmd/testing",
"//pkg/kubectl/cmd/util",
"//pkg/kubectl/resource",
],
)
# Added by ./hack/verify-bazel.sh; should be excluded from # Added by ./hack/verify-bazel.sh; should be excluded from
# that script since it makes no sense here. # that script since it makes no sense here.
filegroup( filegroup(

View File

@ -18,6 +18,7 @@ filegroup(
"//cluster/images/etcd-version-monitor:all-srcs", "//cluster/images/etcd-version-monitor:all-srcs",
"//cluster/images/etcd/attachlease:all-srcs", "//cluster/images/etcd/attachlease:all-srcs",
"//cluster/images/etcd/rollback:all-srcs", "//cluster/images/etcd/rollback:all-srcs",
"//cluster/lib:all-srcs",
"//cluster/saltbase:all-srcs", "//cluster/saltbase:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],

25
cluster/lib/BUILD Normal file
View File

@ -0,0 +1,25 @@
sh_library(
name = "lib",
srcs = [
"logging.sh",
],
visibility = [
"//build/visible_to:COMMON_testing",
"//build/visible_to:cluster",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = [
"//build/visible_to:cluster",
],
)

View File

@ -22,6 +22,7 @@ filegroup(
"//hack/cmd/teststale:all-srcs", "//hack/cmd/teststale:all-srcs",
"//hack/e2e-internal:all-srcs", "//hack/e2e-internal:all-srcs",
"//hack/lib:all-srcs", "//hack/lib:all-srcs",
"//hack/make-rules:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],
) )

View File

@ -1,5 +1,21 @@
package(default_visibility = ["//visibility:public"]) package(default_visibility = ["//visibility:public"])
sh_library(
name = "lib",
srcs = [
"etcd.sh",
"golang.sh",
"init.sh",
"swagger.sh",
"test.sh",
"util.sh",
"version.sh",
],
deps = [
"//cluster/lib",
],
)
filegroup( filegroup(
name = "package-srcs", name = "package-srcs",
srcs = glob(["**"]), srcs = glob(["**"]),

121
hack/make-rules/BUILD Normal file
View File

@ -0,0 +1,121 @@
# Scripts runnable from make, e.g.
#
# cd $GOPATH/src/k8s.io/kubernetes
# make test-e2e-node
#
# The sh_binary rules below exist only to validate
# dependencies; if a shell dependency is accidentally
# deleted, a presubmit BUILD will fail.
#
# If the scripts sourced their dependencies from
# $RUNFILES (rather than $BASH_SOURCE/../.. or
# whatever), then bazel build hack/... would install
# runnable, hermetically sealed shell "binaries".
# E.g. the following command would work:
#
# ./bazel-bin/hack/make-rules/test-e2e-node
#
# TODO(#47064): Should be a sh_test instead of sh_binary
sh_binary(
name = "test-cmd",
srcs = ["test-cmd.sh"],
deps = [
":test-cmd-util",
"//hack/lib",
],
)
sh_binary(
name = "test-e2e-node",
srcs = ["test-e2e-node.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "test-federation-cmd",
srcs = ["test-federation-cmd.sh"],
deps = [
":test-cmd-util",
"//hack/lib",
],
)
sh_binary(
name = "test-integration",
srcs = ["test-cmd.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "test-kubeadm-cmd",
srcs = ["test-kubeadm-cmd.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "build",
srcs = ["build.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "cross",
srcs = ["cross.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "test",
srcs = ["test.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "vet",
srcs = ["vet.sh"],
deps = [
"//hack/lib",
],
)
sh_binary(
name = "verify",
srcs = ["verify.sh"],
deps = [
"//hack/lib",
],
)
sh_library(
name = "test-cmd-util",
srcs = [
"test-cmd-util.sh",
],
data = ["//pkg/kubectl/validation:testdata/v1/validPod.yaml"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

2
hack/make-rules/test-cmd-util.sh Normal file → Executable file
View File

@ -687,7 +687,7 @@ run_pod_tests() {
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
## Patch can modify a local object ## Patch can modify a local object
kubectl patch --local -f pkg/api/validation/testdata/v1/validPod.yaml --patch='{"spec": {"restartPolicy":"Never"}}' -o jsonpath='{.spec.restartPolicy}' | grep -q "Never" kubectl patch --local -f pkg/kubectl/validation/testdata/v1/validPod.yaml --patch='{"spec": {"restartPolicy":"Never"}}' -o jsonpath='{.spec.restartPolicy}' | grep -q "Never"
## Patch pod can change image ## Patch pod can change image
# Command # Command

View File

@ -1,5 +1,3 @@
package(default_visibility = ["//visibility:public"])
load( load(
"@io_bazel_rules_go//go:def.bzl", "@io_bazel_rules_go//go:def.bzl",
"go_library", "go_library",
@ -11,9 +9,9 @@ go_library(
srcs = [ srcs = [
"doc.go", "doc.go",
"events.go", "events.go",
"schema.go",
"validation.go", "validation.go",
], ],
visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/helper:go_default_library", "//pkg/api/helper:go_default_library",
@ -24,8 +22,6 @@ go_library(
"//pkg/capabilities:go_default_library", "//pkg/capabilities:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/security/apparmor:go_default_library", "//pkg/security/apparmor:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/exponent-io/jsonpath:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
@ -33,16 +29,13 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels: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/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
], ],
) )
@ -51,38 +44,22 @@ go_test(
name = "go_default_test", name = "go_default_test",
srcs = [ srcs = [
"events_test.go", "events_test.go",
"schema_test.go",
"validation_test.go", "validation_test.go",
], ],
data = [
"testdata/v1/invalidPod.yaml",
"testdata/v1/invalidPod1.json",
"testdata/v1/invalidPod2.json",
"testdata/v1/invalidPod3.json",
"testdata/v1/invalidPod4.yaml",
"testdata/v1/validPod.yaml",
"//api/swagger-spec",
],
library = ":go_default_library", library = ":go_default_library",
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/helper:go_default_library", "//pkg/api/helper:go_default_library",
"//pkg/api/testapi:go_default_library", "//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//pkg/capabilities:go_default_library", "//pkg/capabilities:go_default_library",
"//pkg/security/apparmor:go_default_library", "//pkg/security/apparmor:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
], ],
) )
@ -91,11 +68,11 @@ filegroup(
name = "package-srcs", name = "package-srcs",
srcs = glob(["**"]), srcs = glob(["**"]),
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:private"],
) )
filegroup( filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [":package-srcs"], srcs = [":package-srcs"],
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"],
) )

View File

@ -32,6 +32,7 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/helper" "k8s.io/kubernetes/pkg/api/helper"
_ "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/security/apparmor" "k8s.io/kubernetes/pkg/security/apparmor"
) )

View File

@ -1,15 +1,5 @@
package(default_visibility = ["//visibility:public"]) package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["doc.go"],
)
filegroup( filegroup(
name = "package-srcs", name = "package-srcs",
srcs = glob(["**"]), srcs = glob(["**"]),
@ -22,3 +12,10 @@ filegroup(
srcs = [":package-srcs"], srcs = [":package-srcs"],
tags = ["automanaged"], tags = ["automanaged"],
) )
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["doc.go"],
)

View File

@ -191,6 +191,7 @@ filegroup(
"//pkg/kubectl/resource:all-srcs", "//pkg/kubectl/resource:all-srcs",
"//pkg/kubectl/testing:all-srcs", "//pkg/kubectl/testing:all-srcs",
"//pkg/kubectl/util:all-srcs", "//pkg/kubectl/util:all-srcs",
"//pkg/kubectl/validation:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],
) )

View File

@ -16,13 +16,13 @@ go_library(
"//federation/client/clientset_generated/federation_clientset:go_default_library", "//federation/client/clientset_generated/federation_clientset:go_default_library",
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library", "//pkg/api/testapi:go_default_library",
"//pkg/api/validation:go_default_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/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/printers:go_default_library", "//pkg/printers:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",

View File

@ -39,13 +39,13 @@ import (
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/api/validation"
"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/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/printers" "k8s.io/kubernetes/pkg/printers"
) )

View File

@ -25,7 +25,6 @@ go_library(
"//federation/client/clientset_generated/federation_clientset:go_default_library", "//federation/client/clientset_generated/federation_clientset:go_default_library",
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/api/validation:go_default_library",
"//pkg/apis/apps:go_default_library", "//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library", "//pkg/apis/batch:go_default_library",
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
@ -37,6 +36,7 @@ go_library(
"//pkg/kubectl/cmd/util/openapi: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/printers:go_default_library", "//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library", "//pkg/printers/internalversion:go_default_library",
"//pkg/version:go_default_library", "//pkg/version:go_default_library",
@ -93,7 +93,6 @@ go_test(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library", "//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library", "//pkg/api/testing:go_default_library",
"//pkg/api/validation:go_default_library",
"//pkg/apis/apps:go_default_library", "//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library", "//pkg/apis/batch:go_default_library",
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
@ -102,6 +101,7 @@ go_test(
"//pkg/controller:go_default_library", "//pkg/controller:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/validation:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",

View File

@ -29,7 +29,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/emicklei/go-restful-swagger12" swagger "github.com/emicklei/go-restful-swagger12"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -48,13 +48,13 @@ import (
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/api/validation"
"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/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/printers" "k8s.io/kubernetes/pkg/printers"
) )

View File

@ -40,7 +40,6 @@ import (
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"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/api/validation"
"k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
@ -49,6 +48,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/validation"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
) )

View File

@ -45,12 +45,12 @@ import (
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"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/api/validation"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/validation"
) )
func TestNewFactoryDefaultFlagBindings(t *testing.T) { func TestNewFactoryDefaultFlagBindings(t *testing.T) {

View File

@ -22,7 +22,7 @@ go_library(
], ],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/validation:go_default_library", "//pkg/kubectl/validation:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/text/encoding/unicode:go_default_library", "//vendor/golang.org/x/text/encoding/unicode:go_default_library",
"//vendor/golang.org/x/text/transform:go_default_library", "//vendor/golang.org/x/text/transform:go_default_library",

View File

@ -30,7 +30,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/kubectl/validation"
) )
var FileExtensions = []string{".json", ".yaml", ".yml"} var FileExtensions = []string{".json", ".yaml", ".yml"}

View File

@ -38,7 +38,7 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/kubectl/validation"
) )
const ( const (

View File

@ -0,0 +1,78 @@
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
exports_files(
srcs = [
"testdata/v1/validPod.yaml",
],
visibility = ["//build/visible_to:COMMON_testing"],
)
filegroup(
name = "testdata",
srcs = [
"testdata/v1/invalidPod.yaml",
"testdata/v1/invalidPod1.json",
"testdata/v1/invalidPod2.json",
"testdata/v1/invalidPod3.json",
"testdata/v1/invalidPod4.yaml",
"testdata/v1/validPod.yaml",
],
visibility = ["//build/visible_to:COMMON_testing"],
)
go_test(
name = "go_default_test",
srcs = ["schema_test.go"],
data = [
":testdata",
"//api/swagger-spec",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["schema.go"],
tags = ["automanaged"],
visibility = ["//build/visible_to:pkg_kubectl_validation_CONSUMERS"],
deps = [
"//pkg/api/util:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/exponent-io/jsonpath:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//build/visible_to:pkg_kubectl_validation_CONSUMERS"],
)

View File

@ -24,7 +24,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/emicklei/go-restful-swagger12" swagger "github.com/emicklei/go-restful-swagger12"
ejson "github.com/exponent-io/jsonpath" ejson "github.com/exponent-io/jsonpath"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -33,6 +33,7 @@ import (
apiutil "k8s.io/kubernetes/pkg/api/util" apiutil "k8s.io/kubernetes/pkg/api/util"
) )
// InvalidTypeError records information about an invalid type.
type InvalidTypeError struct { type InvalidTypeError struct {
ExpectedKind reflect.Kind ExpectedKind reflect.Kind
ObservedKind reflect.Kind ObservedKind reflect.Kind
@ -43,6 +44,7 @@ func (i *InvalidTypeError) Error() string {
return fmt.Sprintf("expected type %s, for field %s, got %s", i.ExpectedKind.String(), i.FieldName, i.ObservedKind.String()) return fmt.Sprintf("expected type %s, for field %s, got %s", i.ExpectedKind.String(), i.FieldName, i.ObservedKind.String())
} }
// NewInvalidTypeError returns an instance of NewInvalidTypeError.
func NewInvalidTypeError(expected reflect.Kind, observed reflect.Kind, fieldName string) error { func NewInvalidTypeError(expected reflect.Kind, observed reflect.Kind, fieldName string) error {
return &InvalidTypeError{expected, observed, fieldName} return &InvalidTypeError{expected, observed, fieldName}
} }
@ -60,14 +62,18 @@ type Schema interface {
ValidateBytes(data []byte) error ValidateBytes(data []byte) error
} }
// NullSchema always validates bytes.
type NullSchema struct{} type NullSchema struct{}
// ValidateBytes never fails for NullSchema.
func (NullSchema) ValidateBytes(data []byte) error { return nil } func (NullSchema) ValidateBytes(data []byte) error { return nil }
// NoDoubleKeySchema is a schema that disallows double keys.
type NoDoubleKeySchema struct{} type NoDoubleKeySchema struct{}
// ValidateBytes validates bytes.
func (NoDoubleKeySchema) ValidateBytes(data []byte) error { func (NoDoubleKeySchema) ValidateBytes(data []byte) error {
var list []error = nil var list []error
if err := validateNoDuplicateKeys(data, "metadata", "labels"); err != nil { if err := validateNoDuplicateKeys(data, "metadata", "labels"); err != nil {
list = append(list, err) list = append(list, err)
} }
@ -107,17 +113,18 @@ func validateNoDuplicateKeys(data []byte, path ...string) error {
case ejson.KeyString: case ejson.KeyString:
if seen[string(t)] { if seen[string(t)] {
return fmt.Errorf("duplicate key: %s", string(t)) return fmt.Errorf("duplicate key: %s", string(t))
} else {
seen[string(t)] = true
} }
seen[string(t)] = true
} }
} }
} }
// ConjunctiveSchema encapsulates a schema list.
type ConjunctiveSchema []Schema type ConjunctiveSchema []Schema
// ValidateBytes validates bytes per a ConjunctiveSchema.
func (c ConjunctiveSchema) ValidateBytes(data []byte) error { func (c ConjunctiveSchema) ValidateBytes(data []byte) error {
var list []error = nil var list []error
schemas := []Schema(c) schemas := []Schema(c)
for ix := range schemas { for ix := range schemas {
if err := schemas[ix].ValidateBytes(data); err != nil { if err := schemas[ix].ValidateBytes(data); err != nil {
@ -127,11 +134,13 @@ func (c ConjunctiveSchema) ValidateBytes(data []byte) error {
return utilerrors.NewAggregate(list) return utilerrors.NewAggregate(list)
} }
// SwaggerSchema is a schema based on an OpenAPI spec.
type SwaggerSchema struct { type SwaggerSchema struct {
api swagger.ApiDeclaration api swagger.ApiDeclaration
delegate Schema // For delegating to other api groups delegate Schema // For delegating to other api groups
} }
// NewSwaggerSchemaFromBytes creates an instance of SwaggerSchema from bytes.
func NewSwaggerSchemaFromBytes(data []byte, factory Schema) (Schema, error) { func NewSwaggerSchemaFromBytes(data []byte, factory Schema) (Schema, error) {
schema := &SwaggerSchema{} schema := &SwaggerSchema{}
err := json.Unmarshal(data, &schema.api) err := json.Unmarshal(data, &schema.api)
@ -201,6 +210,7 @@ func (s *SwaggerSchema) validateItems(items interface{}) []error {
return allErrs return allErrs
} }
// ValidateBytes validates bytes in a SwaggerSchema.
func (s *SwaggerSchema) ValidateBytes(data []byte) error { func (s *SwaggerSchema) ValidateBytes(data []byte) error {
var obj interface{} var obj interface{}
out, err := yaml.ToJSON(data) out, err := yaml.ToJSON(data)
@ -240,6 +250,7 @@ func (s *SwaggerSchema) ValidateBytes(data []byte) error {
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }
// ValidateObject returns no errors for a valid object.
func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) []error { func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) []error {
allErrs := []error{} allErrs := []error{}
models := s.api.Models models := s.api.Models
@ -249,13 +260,13 @@ func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName stri
// s.api only has schema for 1 api version (the parent object type's version). // s.api only has schema for 1 api version (the parent object type's version).
// e.g. an extensions/v1beta1 Template embedding a /v1 Service requires the schema for the extensions/v1beta1 // e.g. an extensions/v1beta1 Template embedding a /v1 Service requires the schema for the extensions/v1beta1
// api to delegate to the schema for the /v1 api. // api to delegate to the schema for the /v1 api.
// Only do this for !ok objects so that cross ApiVersion vendored types take precedence. // Only do this for !ok objects so that cross APIVersion vendored types take precedence.
if !ok && s.delegate != nil { if !ok && s.delegate != nil {
fields, mapOk := obj.(map[string]interface{}) fields, mapOk := obj.(map[string]interface{})
if !mapOk { if !mapOk {
return append(allErrs, fmt.Errorf("field %s for %s: expected object of type map[string]interface{}, but the actual type is %T", fieldName, typeName, obj)) return append(allErrs, fmt.Errorf("field %s for %s: expected object of type map[string]interface{}, but the actual type is %T", fieldName, typeName, obj))
} }
if delegated, err := s.delegateIfDifferentApiVersion(&unstructured.Unstructured{Object: fields}); delegated { if delegated, err := s.delegateIfDifferentAPIVersion(&unstructured.Unstructured{Object: fields}); delegated {
if err != nil { if err != nil {
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
} }
@ -322,13 +333,13 @@ func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName stri
return allErrs return allErrs
} }
// delegateIfDifferentApiVersion delegates the validation of an object if its ApiGroup does not match the // delegateIfDifferentAPIVersion delegates the validation of an object if its ApiGroup does not match the
// current SwaggerSchema. // current SwaggerSchema.
// First return value is true if the validation was delegated (by a different ApiGroup SwaggerSchema) // First return value is true if the validation was delegated (by a different ApiGroup SwaggerSchema)
// Second return value is the result of the delegated validation if performed. // Second return value is the result of the delegated validation if performed.
func (s *SwaggerSchema) delegateIfDifferentApiVersion(obj *unstructured.Unstructured) (bool, error) { func (s *SwaggerSchema) delegateIfDifferentAPIVersion(obj *unstructured.Unstructured) (bool, error) {
// Never delegate objects in the same ApiVersion or we will get infinite recursion // Never delegate objects in the same APIVersion or we will get infinite recursion
if !s.isDifferentApiVersion(obj) { if !s.isDifferentAPIVersion(obj) {
return false, nil return false, nil
} }
@ -342,9 +353,9 @@ func (s *SwaggerSchema) delegateIfDifferentApiVersion(obj *unstructured.Unstruct
return true, s.delegate.ValidateBytes(m) return true, s.delegate.ValidateBytes(m)
} }
// isDifferentApiVersion Returns true if obj lives in a different ApiVersion than the SwaggerSchema does. // isDifferentAPIVersion Returns true if obj lives in a different APIVersion than the SwaggerSchema does.
// The SwaggerSchema will not be able to process objects in different ApiVersions unless they are vendored. // The SwaggerSchema will not be able to process objects in different APIVersions unless they are vendored.
func (s *SwaggerSchema) isDifferentApiVersion(obj *unstructured.Unstructured) bool { func (s *SwaggerSchema) isDifferentAPIVersion(obj *unstructured.Unstructured) bool {
groupVersion := obj.GetAPIVersion() groupVersion := obj.GetAPIVersion()
return len(groupVersion) > 0 && s.api.ApiVersion != groupVersion return len(groupVersion) > 0 && s.api.ApiVersion != groupVersion
} }

View File

@ -42,10 +42,10 @@ func readPod(filename string) ([]byte, error) {
} }
func readSwaggerFile() ([]byte, error) { func readSwaggerFile() ([]byte, error) {
return readSwaggerApiFile(testapi.Default) return readSwaggerAPIFile(testapi.Default)
} }
func readSwaggerApiFile(group testapi.TestGroup) ([]byte, error) { func readSwaggerAPIFile(group testapi.TestGroup) ([]byte, error) {
// TODO: Figure out a better way of finding these files // TODO: Figure out a better way of finding these files
var pathToSwaggerSpec string var pathToSwaggerSpec string
if group.GroupVersion().Group == "" { if group.GroupVersion().Group == "" {
@ -102,7 +102,7 @@ func loadSchemaForTest() (Schema, error) {
} }
func loadSchemaForTestWithFactory(group testapi.TestGroup, factory Schema) (Schema, error) { func loadSchemaForTestWithFactory(group testapi.TestGroup, factory Schema) (Schema, error) {
data, err := readSwaggerApiFile(group) data, err := readSwaggerAPIFile(group)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -187,15 +187,15 @@ func TestValidateDifferentApiVersions(t *testing.T) {
} }
err = schema.ValidateBytes(bytes) err = schema.ValidateBytes(bytes)
if err == nil { if err == nil {
t.Error(fmt.Errorf("Expected error when validating different api version and no delegate exists.")) t.Error(fmt.Errorf("expected error when validating different api version and no delegate exists"))
} }
f, err := NewFactory() f, err := NewFactory()
if err != nil { if err != nil {
t.Error(fmt.Errorf("Failed to create Schema factory %v.", err)) t.Error(fmt.Errorf("failed to create Schema factory %v", err))
} }
err = f.ValidateBytes(bytes) err = f.ValidateBytes(bytes)
if err != nil { if err != nil {
t.Error(fmt.Errorf("Failed to validate object with multiple ApiGroups: %v.", err)) t.Error(fmt.Errorf("failed to validate object with multiple ApiGroups: %v", err))
} }
} }
@ -377,10 +377,12 @@ func TestValidateDuplicateLabelsPassCases(t *testing.T) {
} }
} }
// AlwaysInvalidSchema is always invalid.
type AlwaysInvalidSchema struct{} type AlwaysInvalidSchema struct{}
// ValidateBytes always fails to validate.
func (AlwaysInvalidSchema) ValidateBytes([]byte) error { func (AlwaysInvalidSchema) ValidateBytes([]byte) error {
return fmt.Errorf("Always invalid!") return fmt.Errorf("always invalid")
} }
func TestConjunctiveSchema(t *testing.T) { func TestConjunctiveSchema(t *testing.T) {