update etcd to skip kinds, not resources so we can use a live mapping

This commit is contained in:
David Eads 2018-04-30 11:08:13 -04:00
parent 1cb797e355
commit cb4ce3392d
2 changed files with 55 additions and 60 deletions

View File

@ -21,7 +21,6 @@ go_test(
"//cmd/kube-apiserver/app/options:go_default_library", "//cmd/kube-apiserver/app/options:go_default_library",
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library",
"//pkg/master:go_default_library", "//pkg/master:go_default_library",
"//test/integration:go_default_library", "//test/integration:go_default_library",
"//test/integration/framework:go_default_library", "//test/integration/framework:go_default_library",
@ -38,10 +37,10 @@ go_test(
"//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library",
"//vendor/k8s.io/client-go/discovery:go_default_library",
"//vendor/k8s.io/client-go/discovery/cached:go_default_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/tools/clientcmd:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
], ],
) )

View File

@ -43,16 +43,15 @@ import (
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
genericapiserveroptions "k8s.io/apiserver/pkg/server/options" genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
"k8s.io/client-go/discovery"
cacheddiscovery "k8s.io/client-go/discovery/cached"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app"
"k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/cmd/kube-apiserver/app/options"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
kapi "k8s.io/kubernetes/pkg/apis/core" kapi "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration"
"k8s.io/kubernetes/test/integration/framework" "k8s.io/kubernetes/test/integration/framework"
@ -434,84 +433,84 @@ var etcdStorageData = map[schema.GroupVersionResource]struct {
var ephemeralWhiteList = createEphemeralWhiteList( var ephemeralWhiteList = createEphemeralWhiteList(
// k8s.io/kubernetes/pkg/api/v1 // k8s.io/kubernetes/pkg/api/v1
gvr("", "v1", "bindings"), // annotation on pod, not stored in etcd gvk("", "v1", "Binding"), // annotation on pod, not stored in etcd
gvr("", "v1", "rangeallocations"), // stored in various places in etcd but cannot be directly created gvk("", "v1", "RangeAllocation"), // stored in various places in etcd but cannot be directly created
gvr("", "v1", "componentstatuses"), // status info not stored in etcd gvk("", "v1", "ComponentStatus"), // status info not stored in etcd
gvr("", "v1", "serializedreferences"), // used for serilization, not stored in etcd gvk("", "v1", "SerializedReference"), // used for serilization, not stored in etcd
gvr("", "v1", "nodeconfigsources"), // subfield of node.spec, but shouldn't be directly created gvk("", "v1", "NodeConfigSource"), // subfield of node.spec, but shouldn't be directly created
gvr("", "v1", "podstatusresults"), // wrapper object not stored in etcd gvk("", "v1", "PodStatusResult"), // wrapper object not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/authentication/v1beta1 // k8s.io/kubernetes/pkg/apis/authentication/v1beta1
gvr("authentication.k8s.io", "v1beta1", "tokenreviews"), // not stored in etcd gvk("authentication.k8s.io", "v1beta1", "TokenReview"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/authentication/v1 // k8s.io/kubernetes/pkg/apis/authentication/v1
gvr("authentication.k8s.io", "v1", "tokenreviews"), // not stored in etcd gvk("authentication.k8s.io", "v1", "TokenReview"), // not stored in etcd
gvr("authentication.k8s.io", "v1", "tokenrequests"), // not stored in etcd gvk("authentication.k8s.io", "v1", "TokenRequest"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/authorization/v1beta1 // k8s.io/kubernetes/pkg/apis/authorization/v1beta1
// SRR objects that are not stored in etcd // SRR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1beta1", "selfsubjectrulesreviews"), gvk("authorization.k8s.io", "v1beta1", "SelfSubjectRulesReview"),
// SAR objects that are not stored in etcd // SAR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1beta1", "selfsubjectaccessreviews"), gvk("authorization.k8s.io", "v1beta1", "SelfSubjectAccessReview"),
gvr("authorization.k8s.io", "v1beta1", "localsubjectaccessreviews"), gvk("authorization.k8s.io", "v1beta1", "LocalSubjectAccessReview"),
gvr("authorization.k8s.io", "v1beta1", "subjectaccessreviews"), gvk("authorization.k8s.io", "v1beta1", "SubjectAccessReview"),
// -- // --
// k8s.io/kubernetes/pkg/apis/authorization/v1 // k8s.io/kubernetes/pkg/apis/authorization/v1
// SRR objects that are not stored in etcd // SRR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1", "selfsubjectrulesreviews"), gvk("authorization.k8s.io", "v1", "SelfSubjectRulesReview"),
// SAR objects that are not stored in etcd // SAR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1", "selfsubjectaccessreviews"), gvk("authorization.k8s.io", "v1", "SelfSubjectAccessReview"),
gvr("authorization.k8s.io", "v1", "localsubjectaccessreviews"), gvk("authorization.k8s.io", "v1", "LocalSubjectAccessReview"),
gvr("authorization.k8s.io", "v1", "subjectaccessreviews"), gvk("authorization.k8s.io", "v1", "SubjectAccessReview"),
// -- // --
// k8s.io/kubernetes/pkg/apis/autoscaling/v1 // k8s.io/kubernetes/pkg/apis/autoscaling/v1
gvr("autoscaling", "v1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("autoscaling", "v1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
// -- // --
// k8s.io/kubernetes/pkg/apis/apps/v1beta1 // k8s.io/kubernetes/pkg/apis/apps/v1beta1
gvr("apps", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("apps", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
gvr("apps", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd gvk("apps", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/apps/v1beta2 // k8s.io/kubernetes/pkg/apis/apps/v1beta2
gvr("apps", "v1beta2", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("apps", "v1beta2", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
// -- // --
// k8s.io/kubernetes/pkg/apis/batch/v1beta1 // k8s.io/kubernetes/pkg/apis/batch/v1beta1
gvr("batch", "v1beta1", "jobtemplates"), // not stored in etcd gvk("batch", "v1beta1", "JobTemplate"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/batch/v2alpha1 // k8s.io/kubernetes/pkg/apis/batch/v2alpha1
gvr("batch", "v2alpha1", "jobtemplates"), // not stored in etcd gvk("batch", "v2alpha1", "JobTemplate"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1 // k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1
gvr("componentconfig", "v1alpha1", "kubeschedulerconfigurations"), // not stored in etcd gvk("componentconfig", "v1alpha1", "KubeSchedulerConfiguration"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/extensions/v1beta1 // k8s.io/kubernetes/pkg/apis/extensions/v1beta1
gvr("extensions", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd gvk("extensions", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd
gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd gvk("extensions", "v1beta1", "ReplicationControllerDummy"), // not stored in etcd
gvr("extensions", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("extensions", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
// -- // --
// k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1 // k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1
gvr("imagepolicy.k8s.io", "v1alpha1", "imagereviews"), // not stored in etcd gvk("imagepolicy.k8s.io", "v1alpha1", "ImageReview"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/policy/v1beta1 // k8s.io/kubernetes/pkg/apis/policy/v1beta1
gvr("policy", "v1beta1", "evictions"), // not stored in etcd, deals with evicting kapiv1.Pod gvk("policy", "v1beta1", "Eviction"), // not stored in etcd, deals with evicting kapiv1.Pod
// -- // --
// k8s.io/kubernetes/pkg/apis/admission/v1beta1 // k8s.io/kubernetes/pkg/apis/admission/v1beta1
gvr("admission.k8s.io", "v1beta1", "admissionreviews"), // not stored in etcd, call out to webhooks. gvk("admission.k8s.io", "v1beta1", "AdmissionReview"), // not stored in etcd, call out to webhooks.
// -- // --
) )
@ -561,7 +560,7 @@ func TestEtcdStoragePath(t *testing.T) {
kindSeen := sets.NewString() kindSeen := sets.NewString()
pathSeen := map[string][]schema.GroupVersionResource{} pathSeen := map[string][]schema.GroupVersionResource{}
etcdSeen := map[schema.GroupVersionResource]empty{} etcdSeen := map[schema.GroupVersionResource]empty{}
ephemeralSeen := map[schema.GroupVersionResource]empty{} ephemeralSeen := map[schema.GroupVersionKind]empty{}
cohabitatingResources := map[string]map[schema.GroupVersionKind]empty{} cohabitatingResources := map[string]map[schema.GroupVersionKind]empty{}
for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() {
@ -577,6 +576,11 @@ func TestEtcdStoragePath(t *testing.T) {
kindSeen.Insert(kind) kindSeen.Insert(kind)
continue continue
} }
_, isEphemeral := ephemeralWhiteList[gvk]
if isEphemeral {
ephemeralSeen[gvk] = empty{}
continue
}
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil { if err != nil {
@ -588,25 +592,12 @@ func TestEtcdStoragePath(t *testing.T) {
etcdSeen[gvResource] = empty{} etcdSeen[gvResource] = empty{}
testData, hasTest := etcdStorageData[gvResource] testData, hasTest := etcdStorageData[gvResource]
_, isEphemeral := ephemeralWhiteList[gvResource]
if !hasTest && !isEphemeral { if !hasTest {
t.Errorf("no test data for %s from %s. Please add a test for your new type to etcdStorageData.", kind, pkgPath) t.Errorf("no test data for %s from %s. Please add a test for your new type to etcdStorageData.", kind, pkgPath)
continue continue
} }
if hasTest && isEphemeral {
t.Errorf("duplicate test data for %s from %s. Object has both test data and is ephemeral.", kind, pkgPath)
continue
}
if isEphemeral { // TODO it would be nice if we could remove this and infer if an object is not stored in etcd
// t.Logf("Skipping test for %s from %s", kind, pkgPath)
ephemeralSeen[gvResource] = empty{}
delete(etcdSeen, gvResource)
continue
}
if len(testData.expectedEtcdPath) == 0 { if len(testData.expectedEtcdPath) == 0 {
t.Errorf("empty test data for %s from %s", kind, pkgPath) t.Errorf("empty test data for %s from %s", kind, pkgPath)
continue continue
@ -811,10 +802,11 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV
t.Fatal(err) t.Fatal(err)
} }
mapper, err := util.NewFactory(clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{})).RESTMapper() discoveryClient := cacheddiscovery.NewMemCacheClient(kubeClient.Discovery())
if err != nil { restMapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient)
t.Fatal(err) restMapper.Reset()
} // allow conversion between typed and unstructured objects
mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient)
return client, kvClient, mapper return client, kvClient, mapper
} }
@ -891,17 +883,21 @@ func gvr(g, v, r string) schema.GroupVersionResource {
return schema.GroupVersionResource{Group: g, Version: v, Resource: r} return schema.GroupVersionResource{Group: g, Version: v, Resource: r}
} }
func gvk(g, v, k string) schema.GroupVersionKind {
return schema.GroupVersionKind{Group: g, Version: v, Kind: k}
}
func gvkP(g, v, k string) *schema.GroupVersionKind { func gvkP(g, v, k string) *schema.GroupVersionKind {
return &schema.GroupVersionKind{Group: g, Version: v, Kind: k} return &schema.GroupVersionKind{Group: g, Version: v, Kind: k}
} }
func createEphemeralWhiteList(gvrs ...schema.GroupVersionResource) map[schema.GroupVersionResource]empty { func createEphemeralWhiteList(gvks ...schema.GroupVersionKind) map[schema.GroupVersionKind]empty {
ephemeral := map[schema.GroupVersionResource]empty{} ephemeral := map[schema.GroupVersionKind]empty{}
for _, gvResource := range gvrs { for _, gvKind := range gvks {
if _, ok := ephemeral[gvResource]; ok { if _, ok := ephemeral[gvKind]; ok {
panic("invalid ephemeral whitelist contains duplicate keys") panic("invalid ephemeral whitelist contains duplicate keys")
} }
ephemeral[gvResource] = empty{} ephemeral[gvKind] = empty{}
} }
return ephemeral return ephemeral
} }