Merge pull request #77605 from pohly/multivolume-storage-class-fix

Multivolume storage class fix
This commit is contained in:
Kubernetes Prow Robot 2019-05-09 15:48:22 -07:00 committed by GitHub
commit 69b52633cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 32 deletions

View File

@ -90,7 +90,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/discovery:go_default_library", "//staging/src/k8s.io/client-go/discovery:go_default_library",
"//staging/src/k8s.io/client-go/discovery/cached/memory:go_default_library", "//staging/src/k8s.io/client-go/discovery/cached/memory:go_default_library",

View File

@ -31,7 +31,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
"k8s.io/kubernetes/test/e2e/framework/testfiles" "k8s.io/kubernetes/test/e2e/framework/testfiles"
@ -101,9 +100,9 @@ func visitManifests(cb func([]byte) error, files ...string) error {
return nil return nil
} }
// PatchItems modifies the given items in place such that each // PatchItems modifies the given items in place such that each test
// test gets its own instances, to avoid conflicts between different tests and // gets its own instances, to avoid conflicts between different tests
// between tests and normal deployments. // and between tests and normal deployments.
// //
// This is done by: // This is done by:
// - creating namespaced items inside the test's namespace // - creating namespaced items inside the test's namespace
@ -288,27 +287,18 @@ var factories = map[What]ItemFactory{
{"StorageClass"}: &storageClassFactory{}, {"StorageClass"}: &storageClassFactory{},
} }
// uniquifyName makes the name of some item unique per namespace by appending the // PatchName makes the name of some item unique by appending the
// generated unique name of the test namespace. // generated unique name.
func (f *Framework) uniquifyName(item *string) { func (f *Framework) PatchName(item *string) {
if *item != "" { if *item != "" {
*item = *item + "-" + f.UniqueName *item = *item + "-" + f.UniqueName
} }
} }
// randomizeStorageClassName makes the name of the storage class unique per call // PatchNamespace moves the item into the test's namespace. Not
// by appending the generated unique name of the test namespace and a random 5
// character string
func (f *Framework) randomizeStorageClassName(item *string) {
if *item != "" {
*item = names.SimpleNameGenerator.GenerateName(*item + "-" + f.UniqueName + "-")
}
}
// patchNamespace moves the item into the test's namespace. Not
// all items can be namespaced. For those, the name also needs to be // all items can be namespaced. For those, the name also needs to be
// patched. // patched.
func (f *Framework) patchNamespace(item *string) { func (f *Framework) PatchNamespace(item *string) {
if f.Namespace != nil { if f.Namespace != nil {
*item = f.Namespace.GetName() *item = f.Namespace.GetName()
} }
@ -317,31 +307,31 @@ func (f *Framework) patchNamespace(item *string) {
func (f *Framework) patchItemRecursively(item interface{}) error { func (f *Framework) patchItemRecursively(item interface{}) error {
switch item := item.(type) { switch item := item.(type) {
case *rbac.Subject: case *rbac.Subject:
f.patchNamespace(&item.Namespace) f.PatchNamespace(&item.Namespace)
case *rbac.RoleRef: case *rbac.RoleRef:
// TODO: avoid hard-coding this special name. Perhaps add a Framework.PredefinedRoles // TODO: avoid hard-coding this special name. Perhaps add a Framework.PredefinedRoles
// which contains all role names that are defined cluster-wide before the test starts? // which contains all role names that are defined cluster-wide before the test starts?
// All those names are excempt from renaming. That list could be populated by querying // All those names are excempt from renaming. That list could be populated by querying
// and get extended by tests. // and get extended by tests.
if item.Name != "e2e-test-privileged-psp" { if item.Name != "e2e-test-privileged-psp" {
f.uniquifyName(&item.Name) f.PatchName(&item.Name)
} }
case *rbac.ClusterRole: case *rbac.ClusterRole:
f.uniquifyName(&item.Name) f.PatchName(&item.Name)
case *rbac.Role: case *rbac.Role:
f.patchNamespace(&item.Namespace) f.PatchNamespace(&item.Namespace)
// Roles are namespaced, but because for RoleRef above we don't // Roles are namespaced, but because for RoleRef above we don't
// know whether the referenced role is a ClusterRole or Role // know whether the referenced role is a ClusterRole or Role
// and therefore always renames, we have to do the same here. // and therefore always renames, we have to do the same here.
f.uniquifyName(&item.Name) f.PatchName(&item.Name)
case *storage.StorageClass: case *storage.StorageClass:
f.randomizeStorageClassName(&item.Name) f.PatchName(&item.Name)
case *v1.ServiceAccount: case *v1.ServiceAccount:
f.patchNamespace(&item.ObjectMeta.Namespace) f.PatchNamespace(&item.ObjectMeta.Namespace)
case *v1.Secret: case *v1.Secret:
f.patchNamespace(&item.ObjectMeta.Namespace) f.PatchNamespace(&item.ObjectMeta.Namespace)
case *rbac.ClusterRoleBinding: case *rbac.ClusterRoleBinding:
f.uniquifyName(&item.Name) f.PatchName(&item.Name)
for i := range item.Subjects { for i := range item.Subjects {
if err := f.patchItemRecursively(&item.Subjects[i]); err != nil { if err := f.patchItemRecursively(&item.Subjects[i]); err != nil {
return errors.Wrapf(err, "%T", f) return errors.Wrapf(err, "%T", f)
@ -351,7 +341,7 @@ func (f *Framework) patchItemRecursively(item interface{}) error {
return errors.Wrapf(err, "%T", f) return errors.Wrapf(err, "%T", f)
} }
case *rbac.RoleBinding: case *rbac.RoleBinding:
f.patchNamespace(&item.Namespace) f.PatchNamespace(&item.Namespace)
for i := range item.Subjects { for i := range item.Subjects {
if err := f.patchItemRecursively(&item.Subjects[i]); err != nil { if err := f.patchItemRecursively(&item.Subjects[i]); err != nil {
return errors.Wrapf(err, "%T", f) return errors.Wrapf(err, "%T", f)
@ -361,11 +351,11 @@ func (f *Framework) patchItemRecursively(item interface{}) error {
return errors.Wrapf(err, "%T", f) return errors.Wrapf(err, "%T", f)
} }
case *v1.Service: case *v1.Service:
f.patchNamespace(&item.ObjectMeta.Namespace) f.PatchNamespace(&item.ObjectMeta.Namespace)
case *apps.StatefulSet: case *apps.StatefulSet:
f.patchNamespace(&item.ObjectMeta.Namespace) f.PatchNamespace(&item.ObjectMeta.Namespace)
case *apps.DaemonSet: case *apps.DaemonSet:
f.patchNamespace(&item.ObjectMeta.Namespace) f.PatchNamespace(&item.ObjectMeta.Namespace)
default: default:
return errors.Errorf("missing support for patching item of type %T", item) return errors.Errorf("missing support for patching item of type %T", item)
} }

View File

@ -11,6 +11,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//test/e2e/framework:go_default_library", "//test/e2e/framework:go_default_library",
"//test/e2e/storage/testpatterns:go_default_library", "//test/e2e/storage/testpatterns:go_default_library",

View File

@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/testpatterns"
@ -242,6 +243,9 @@ func (d *driverDefinition) GetDynamicProvisionStorageClass(config *testsuites.Pe
sc, ok := items[0].(*storagev1.StorageClass) sc, ok := items[0].(*storagev1.StorageClass)
gomega.Expect(ok).To(gomega.BeTrue(), "storage class from %s", d.StorageClass.FromFile) gomega.Expect(ok).To(gomega.BeTrue(), "storage class from %s", d.StorageClass.FromFile)
// Ensure that we can load more than once as required for
// GetDynamicProvisionStorageClass by adding a random suffix.
sc.Name = names.SimpleNameGenerator.GenerateName(sc.Name + "-")
if fsType != "" { if fsType != "" {
if sc.Parameters == nil { if sc.Parameters == nil {
sc.Parameters = map[string]string{} sc.Parameters = map[string]string{}

View File

@ -88,6 +88,9 @@ type PreprovisionedPVTestDriver interface {
type DynamicPVTestDriver interface { type DynamicPVTestDriver interface {
TestDriver TestDriver
// GetDynamicProvisionStorageClass returns a StorageClass dynamic provision Persistent Volume. // GetDynamicProvisionStorageClass returns a StorageClass dynamic provision Persistent Volume.
// The StorageClass must be created in the current test's namespace and have
// a unique name inside that namespace because GetDynamicProvisionStorageClass might
// be called more than once per test.
// It will set fsType to the StorageClass, if TestDriver supports it. // It will set fsType to the StorageClass, if TestDriver supports it.
// It will return nil, if the TestDriver doesn't support it. // It will return nil, if the TestDriver doesn't support it.
GetDynamicProvisionStorageClass(config *PerTestConfig, fsType string) *storagev1.StorageClass GetDynamicProvisionStorageClass(config *PerTestConfig, fsType string) *storagev1.StorageClass