mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
Fresh dep ensure
This commit is contained in:
14
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/BUILD
generated
vendored
14
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/BUILD
generated
vendored
@ -1,10 +1,6 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
@ -13,7 +9,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -37,8 +33,8 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
129
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go
generated
vendored
129
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go
generated
vendored
@ -22,123 +22,22 @@ import (
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func getClaimRefNamespace(pv *api.PersistentVolume) string {
|
||||
if pv.Spec.ClaimRef != nil {
|
||||
return pv.Spec.ClaimRef.Namespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Visitor is called with each object's namespace and name, and returns true if visiting should continue
|
||||
type Visitor func(namespace, name string, kubeletVisible bool) (shouldContinue bool)
|
||||
|
||||
// VisitPVSecretNames invokes the visitor function with the name of every secret
|
||||
// referenced by the PV spec. If visitor returns false, visiting is short-circuited.
|
||||
// Returns true if visiting completed, false if visiting was short-circuited.
|
||||
func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
|
||||
source := &pv.Spec.PersistentVolumeSource
|
||||
switch {
|
||||
case source.AzureFile != nil:
|
||||
if source.AzureFile.SecretNamespace != nil && len(*source.AzureFile.SecretNamespace) > 0 {
|
||||
if len(source.AzureFile.SecretName) > 0 && !visitor(*source.AzureFile.SecretNamespace, source.AzureFile.SecretName, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if len(source.AzureFile.SecretName) > 0 && !visitor(getClaimRefNamespace(pv), source.AzureFile.SecretName, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case source.CephFS != nil:
|
||||
if source.CephFS.SecretRef != nil {
|
||||
// previously persisted PV objects use claimRef namespace
|
||||
ns := getClaimRefNamespace(pv)
|
||||
if len(source.CephFS.SecretRef.Namespace) > 0 {
|
||||
// use the secret namespace if namespace is set
|
||||
ns = source.CephFS.SecretRef.Namespace
|
||||
}
|
||||
if !visitor(ns, source.CephFS.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case source.Cinder != nil:
|
||||
if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Namespace, source.Cinder.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
case source.FlexVolume != nil:
|
||||
if source.FlexVolume.SecretRef != nil {
|
||||
// previously persisted PV objects use claimRef namespace
|
||||
ns := getClaimRefNamespace(pv)
|
||||
if len(source.FlexVolume.SecretRef.Namespace) > 0 {
|
||||
// use the secret namespace if namespace is set
|
||||
ns = source.FlexVolume.SecretRef.Namespace
|
||||
}
|
||||
if !visitor(ns, source.FlexVolume.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case source.RBD != nil:
|
||||
if source.RBD.SecretRef != nil {
|
||||
// previously persisted PV objects use claimRef namespace
|
||||
ns := getClaimRefNamespace(pv)
|
||||
if len(source.RBD.SecretRef.Namespace) > 0 {
|
||||
// use the secret namespace if namespace is set
|
||||
ns = source.RBD.SecretRef.Namespace
|
||||
}
|
||||
if !visitor(ns, source.RBD.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case source.ScaleIO != nil:
|
||||
if source.ScaleIO.SecretRef != nil {
|
||||
ns := getClaimRefNamespace(pv)
|
||||
if source.ScaleIO.SecretRef != nil && len(source.ScaleIO.SecretRef.Namespace) > 0 {
|
||||
ns = source.ScaleIO.SecretRef.Namespace
|
||||
}
|
||||
if !visitor(ns, source.ScaleIO.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case source.ISCSI != nil:
|
||||
if source.ISCSI.SecretRef != nil {
|
||||
// previously persisted PV objects use claimRef namespace
|
||||
ns := getClaimRefNamespace(pv)
|
||||
if len(source.ISCSI.SecretRef.Namespace) > 0 {
|
||||
// use the secret namespace if namespace is set
|
||||
ns = source.ISCSI.SecretRef.Namespace
|
||||
}
|
||||
if !visitor(ns, source.ISCSI.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case source.StorageOS != nil:
|
||||
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Namespace, source.StorageOS.SecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
case source.CSI != nil:
|
||||
if source.CSI.ControllerPublishSecretRef != nil {
|
||||
if !visitor(source.CSI.ControllerPublishSecretRef.Namespace, source.CSI.ControllerPublishSecretRef.Name, false /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if source.CSI.NodePublishSecretRef != nil {
|
||||
if !visitor(source.CSI.NodePublishSecretRef.Namespace, source.CSI.NodePublishSecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if source.CSI.NodeStageSecretRef != nil {
|
||||
if !visitor(source.CSI.NodeStageSecretRef.Namespace, source.CSI.NodeStageSecretRef.Name, true /* kubeletVisible */) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// DropDisabledAlphaFields removes disabled fields from the pv spec.
|
||||
// DropDisabledFields removes disabled fields from the pv spec.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
|
||||
func DropDisabledAlphaFields(pvSpec *api.PersistentVolumeSpec) {
|
||||
func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.PersistentVolumeSpec) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
// TODO(liggitt): change this to only drop pvSpec.VolumeMode if (oldPVSpec == nil || oldPVSpec.VolumeMode == nil)
|
||||
// Requires more coordinated changes to validation
|
||||
pvSpec.VolumeMode = nil
|
||||
if oldPVSpec != nil {
|
||||
oldPVSpec.VolumeMode = nil
|
||||
}
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
||||
// if this is a new PV, or the old PV didn't already have the CSI field, clear it
|
||||
if oldPVSpec == nil || oldPVSpec.PersistentVolumeSource.CSI == nil {
|
||||
pvSpec.PersistentVolumeSource.CSI = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
403
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go
generated
vendored
403
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2018 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.
|
||||
@ -20,307 +20,136 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestPVSecrets(t *testing.T) {
|
||||
// Stub containing all possible secret references in a PV.
|
||||
// The names of the referenced secrets match struct paths detected by reflection.
|
||||
secretNamespace := "Spec.PersistentVolumeSource.AzureFile.SecretNamespace"
|
||||
pvs := []*api.PersistentVolume{
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
AzureFile: &api.AzureFilePersistentVolumeSource{
|
||||
SecretName: "Spec.PersistentVolumeSource.AzureFile.SecretName"}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
AzureFile: &api.AzureFilePersistentVolumeSource{
|
||||
SecretName: "Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
SecretNamespace: &secretNamespace}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
CephFS: &api.CephFSPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
Namespace: "cephfs"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
CephFS: &api.CephFSPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.CephFS.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Cinder: &api.CinderPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.Cinder.SecretRef",
|
||||
Namespace: "cinder"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
FlexVolume: &api.FlexPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||
Namespace: "flexns"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
FlexVolume: &api.FlexPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
RBD: &api.RBDPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.RBD.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
RBD: &api.RBDPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||
Namespace: "rbdns"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ScaleIO: &api.ScaleIOPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.ScaleIO.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ScaleIO: &api.ScaleIOPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||
Namespace: "scaleions"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ISCSI: &api.ISCSIPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||
Namespace: "iscsi"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ISCSI: &api.ISCSIPersistentVolumeSource{
|
||||
SecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.ISCSI.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
StorageOS: &api.StorageOSPersistentVolumeSource{
|
||||
SecretRef: &api.ObjectReference{
|
||||
Name: "Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||
Namespace: "storageosns"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
CSI: &api.CSIPersistentVolumeSource{
|
||||
ControllerPublishSecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef",
|
||||
Namespace: "csi"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
CSI: &api.CSIPersistentVolumeSource{
|
||||
NodePublishSecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
||||
Namespace: "csi"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
CSI: &api.CSIPersistentVolumeSource{
|
||||
NodeStageSecretRef: &api.SecretReference{
|
||||
Name: "Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
||||
Namespace: "csi"}}}}},
|
||||
func TestDropDisabledFields(t *testing.T) {
|
||||
specWithCSI := func() *api.PersistentVolumeSpec {
|
||||
return &api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{CSI: &api.CSIPersistentVolumeSource{}}}
|
||||
}
|
||||
extractedNames := sets.NewString()
|
||||
extractedNamesWithNamespace := sets.NewString()
|
||||
for _, pv := range pvs {
|
||||
VisitPVSecretNames(pv, func(namespace, name string, kubeletVisible bool) bool {
|
||||
extractedNames.Insert(name)
|
||||
extractedNamesWithNamespace.Insert(namespace + "/" + name)
|
||||
return true
|
||||
})
|
||||
specWithoutCSI := func() *api.PersistentVolumeSpec {
|
||||
return &api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{CSI: nil}}
|
||||
}
|
||||
specWithMode := func(mode *api.PersistentVolumeMode) *api.PersistentVolumeSpec {
|
||||
return &api.PersistentVolumeSpec{VolumeMode: mode}
|
||||
}
|
||||
|
||||
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
|
||||
excludedSecretPaths := sets.NewString(
|
||||
"Spec.PersistentVolumeSource.CephFS.SecretFile",
|
||||
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace",
|
||||
)
|
||||
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
|
||||
// every path here should be represented as an example in the PV stub above, with the secret name set to the path.
|
||||
expectedSecretPaths := sets.NewString(
|
||||
"Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
"Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
"Spec.PersistentVolumeSource.Cinder.SecretRef",
|
||||
"Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||
"Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||
"Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||
"Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||
"Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||
"Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef",
|
||||
"Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
||||
"Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
||||
)
|
||||
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.PersistentVolume{}))
|
||||
secretPaths = secretPaths.Difference(excludedSecretPaths)
|
||||
if missingPaths := expectedSecretPaths.Difference(secretPaths); len(missingPaths) > 0 {
|
||||
t.Logf("Missing expected secret paths:\n%s", strings.Join(missingPaths.List(), "\n"))
|
||||
t.Error("Missing expected secret paths. Verify VisitPVSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
|
||||
}
|
||||
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
|
||||
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n"))
|
||||
t.Error("Extra fields with 'secret' in the name found. Verify VisitPVSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
|
||||
}
|
||||
modeBlock := api.PersistentVolumeBlock
|
||||
|
||||
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
|
||||
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||
t.Error("Missing expected secret names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names")
|
||||
}
|
||||
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
|
||||
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n"))
|
||||
t.Error("Extra secret names extracted. Verify VisitPVSecretNames() is correctly extracting secret names")
|
||||
}
|
||||
tests := map[string]struct {
|
||||
oldSpec *api.PersistentVolumeSpec
|
||||
newSpec *api.PersistentVolumeSpec
|
||||
expectOldSpec *api.PersistentVolumeSpec
|
||||
expectNewSpec *api.PersistentVolumeSpec
|
||||
csiEnabled bool
|
||||
blockEnabled bool
|
||||
}{
|
||||
"disabled csi clears new": {
|
||||
csiEnabled: false,
|
||||
newSpec: specWithCSI(),
|
||||
expectNewSpec: specWithoutCSI(),
|
||||
oldSpec: nil,
|
||||
expectOldSpec: nil,
|
||||
},
|
||||
"disabled csi clears update when old pv did not use csi": {
|
||||
csiEnabled: false,
|
||||
newSpec: specWithCSI(),
|
||||
expectNewSpec: specWithoutCSI(),
|
||||
oldSpec: specWithoutCSI(),
|
||||
expectOldSpec: specWithoutCSI(),
|
||||
},
|
||||
"disabled csi preserves update when old pv did use csi": {
|
||||
csiEnabled: false,
|
||||
newSpec: specWithCSI(),
|
||||
expectNewSpec: specWithCSI(),
|
||||
oldSpec: specWithCSI(),
|
||||
expectOldSpec: specWithCSI(),
|
||||
},
|
||||
|
||||
expectedNamespacedNames := sets.NewString(
|
||||
"claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
"enabled csi preserves new": {
|
||||
csiEnabled: true,
|
||||
newSpec: specWithCSI(),
|
||||
expectNewSpec: specWithCSI(),
|
||||
oldSpec: nil,
|
||||
expectOldSpec: nil,
|
||||
},
|
||||
"enabled csi preserves update when old pv did not use csi": {
|
||||
csiEnabled: true,
|
||||
newSpec: specWithCSI(),
|
||||
expectNewSpec: specWithCSI(),
|
||||
oldSpec: specWithoutCSI(),
|
||||
expectOldSpec: specWithoutCSI(),
|
||||
},
|
||||
"enabled csi preserves update when old pv did use csi": {
|
||||
csiEnabled: true,
|
||||
newSpec: specWithCSI(),
|
||||
expectNewSpec: specWithCSI(),
|
||||
oldSpec: specWithCSI(),
|
||||
expectOldSpec: specWithCSI(),
|
||||
},
|
||||
|
||||
"claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
"disabled block clears new": {
|
||||
blockEnabled: false,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(nil),
|
||||
oldSpec: nil,
|
||||
expectOldSpec: nil,
|
||||
},
|
||||
"disabled block clears update when old pv did not use block": {
|
||||
blockEnabled: false,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(nil),
|
||||
oldSpec: specWithMode(nil),
|
||||
expectOldSpec: specWithMode(nil),
|
||||
},
|
||||
// TODO: consider changing this case to preserve
|
||||
"disabled block clears old and new on update when old pv did use block": {
|
||||
blockEnabled: false,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(nil),
|
||||
oldSpec: specWithMode(&modeBlock),
|
||||
expectOldSpec: specWithMode(nil),
|
||||
},
|
||||
|
||||
"cinder/Spec.PersistentVolumeSource.Cinder.SecretRef",
|
||||
|
||||
"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||
"flexns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||
|
||||
"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||
"rbdns/Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||
|
||||
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||
"scaleions/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||
|
||||
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||
"iscsi/Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||
|
||||
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||
|
||||
"csi/Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef",
|
||||
"csi/Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
||||
"csi/Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
||||
)
|
||||
if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 {
|
||||
t.Logf("Missing expected namespaced names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||
t.Error("Missing expected namespaced names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names")
|
||||
}
|
||||
if extraNames := extractedNamesWithNamespace.Difference(expectedNamespacedNames); len(extraNames) > 0 {
|
||||
t.Logf("Extra namespaced names:\n%s", strings.Join(extraNames.List(), "\n"))
|
||||
t.Error("Extra namespaced names extracted. Verify VisitPVSecretNames() is correctly extracting secret names")
|
||||
}
|
||||
}
|
||||
|
||||
// collectSecretPaths traverses the object, computing all the struct paths that lead to fields with "secret" in the name.
|
||||
func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.Type) sets.String {
|
||||
secretPaths := sets.NewString()
|
||||
|
||||
if tp.Kind() == reflect.Ptr {
|
||||
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
|
||||
return secretPaths
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(name), "secret") {
|
||||
secretPaths.Insert(path.String())
|
||||
}
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Ptr:
|
||||
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
|
||||
case reflect.Struct:
|
||||
for i := 0; i < tp.NumField(); i++ {
|
||||
field := tp.Field(i)
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Child(field.Name), field.Name, field.Type).List()...)
|
||||
}
|
||||
case reflect.Interface:
|
||||
t.Errorf("cannot find secret fields in interface{} field %s", path.String())
|
||||
case reflect.Map:
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
|
||||
case reflect.Slice:
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
|
||||
default:
|
||||
// all primitive types
|
||||
}
|
||||
|
||||
return secretPaths
|
||||
}
|
||||
|
||||
func newHostPathType(pathType string) *api.HostPathType {
|
||||
hostPathType := new(api.HostPathType)
|
||||
*hostPathType = api.HostPathType(pathType)
|
||||
return hostPathType
|
||||
}
|
||||
|
||||
func TestDropAlphaPVVolumeMode(t *testing.T) {
|
||||
vmode := api.PersistentVolumeFilesystem
|
||||
|
||||
// PersistentVolume with VolumeMode set
|
||||
pv := api.PersistentVolume{
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: "/foo",
|
||||
Type: newHostPathType(string(api.HostPathDirectory)),
|
||||
},
|
||||
},
|
||||
StorageClassName: "test-storage-class",
|
||||
VolumeMode: &vmode,
|
||||
"enabled block preserves new": {
|
||||
blockEnabled: true,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: nil,
|
||||
expectOldSpec: nil,
|
||||
},
|
||||
"enabled block preserves update when old pv did not use block": {
|
||||
blockEnabled: true,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: specWithMode(nil),
|
||||
expectOldSpec: specWithMode(nil),
|
||||
},
|
||||
"enabled block preserves update when old pv did use block": {
|
||||
blockEnabled: true,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: specWithMode(&modeBlock),
|
||||
expectOldSpec: specWithMode(&modeBlock),
|
||||
},
|
||||
}
|
||||
|
||||
// Enable alpha feature BlockVolume
|
||||
err1 := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
||||
if err1 != nil {
|
||||
t.Fatalf("Failed to enable feature gate for BlockVolume: %v", err1)
|
||||
}
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIPersistentVolume, tc.csiEnabled)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, tc.blockEnabled)()
|
||||
|
||||
// now test dropping the fields - should not be dropped
|
||||
DropDisabledAlphaFields(&pv.Spec)
|
||||
|
||||
// check to make sure VolumeDevices is still present
|
||||
// if featureset is set to true
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
if pv.Spec.VolumeMode == nil {
|
||||
t.Error("VolumeMode in pv.Spec should not have been dropped based on feature-gate")
|
||||
}
|
||||
}
|
||||
|
||||
// Disable alpha feature BlockVolume
|
||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to disable feature gate for BlockVolume: %v", err)
|
||||
}
|
||||
|
||||
// now test dropping the fields
|
||||
DropDisabledAlphaFields(&pv.Spec)
|
||||
|
||||
// check to make sure VolumeDevices is nil
|
||||
// if featureset is set to false
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
if pv.Spec.VolumeMode != nil {
|
||||
t.Error("DropDisabledAlphaFields VolumeMode for pv.Spec failed")
|
||||
}
|
||||
DropDisabledFields(tc.newSpec, tc.oldSpec)
|
||||
if !reflect.DeepEqual(tc.newSpec, tc.expectNewSpec) {
|
||||
t.Error(diff.ObjectReflectDiff(tc.newSpec, tc.expectNewSpec))
|
||||
}
|
||||
if !reflect.DeepEqual(tc.oldSpec, tc.expectOldSpec) {
|
||||
t.Error(diff.ObjectReflectDiff(tc.oldSpec, tc.expectOldSpec))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user