110
pkg/api/persistentvolume/util_test.go
Normal file
110
pkg/api/persistentvolume/util_test.go
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
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 persistentvolume
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDropDisabledFields(t *testing.T) {
|
||||||
|
secretRef := &api.SecretReference{
|
||||||
|
Name: "expansion-secret",
|
||||||
|
Namespace: "default",
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := map[string]struct {
|
||||||
|
oldSpec *api.PersistentVolumeSpec
|
||||||
|
newSpec *api.PersistentVolumeSpec
|
||||||
|
expectOldSpec *api.PersistentVolumeSpec
|
||||||
|
expectNewSpec *api.PersistentVolumeSpec
|
||||||
|
csiExpansionEnabled bool
|
||||||
|
}{
|
||||||
|
"disabled csi expansion clears secrets": {
|
||||||
|
csiExpansionEnabled: false,
|
||||||
|
newSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectNewSpec: specWithCSISecrets(nil),
|
||||||
|
oldSpec: nil,
|
||||||
|
expectOldSpec: nil,
|
||||||
|
},
|
||||||
|
"enabled csi expansion preserve secrets": {
|
||||||
|
csiExpansionEnabled: true,
|
||||||
|
newSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectNewSpec: specWithCSISecrets(secretRef),
|
||||||
|
oldSpec: nil,
|
||||||
|
expectOldSpec: nil,
|
||||||
|
},
|
||||||
|
"enabled csi expansion preserve secrets when both old and new have it": {
|
||||||
|
csiExpansionEnabled: true,
|
||||||
|
newSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectNewSpec: specWithCSISecrets(secretRef),
|
||||||
|
oldSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectOldSpec: specWithCSISecrets(secretRef),
|
||||||
|
},
|
||||||
|
"disabled csi expansion old pv had secrets": {
|
||||||
|
csiExpansionEnabled: false,
|
||||||
|
newSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectNewSpec: specWithCSISecrets(secretRef),
|
||||||
|
oldSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectOldSpec: specWithCSISecrets(secretRef),
|
||||||
|
},
|
||||||
|
"enabled csi expansion preserves secrets when old pv did not had secrets": {
|
||||||
|
csiExpansionEnabled: true,
|
||||||
|
newSpec: specWithCSISecrets(secretRef),
|
||||||
|
expectNewSpec: specWithCSISecrets(secretRef),
|
||||||
|
oldSpec: specWithCSISecrets(nil),
|
||||||
|
expectOldSpec: specWithCSISecrets(nil),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSINodeExpandSecret, tc.csiExpansionEnabled)()
|
||||||
|
|
||||||
|
DropDisabledFields(tc.newSpec, tc.oldSpec)
|
||||||
|
if !reflect.DeepEqual(tc.newSpec, tc.expectNewSpec) {
|
||||||
|
t.Error(cmp.Diff(tc.newSpec, tc.expectNewSpec))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tc.oldSpec, tc.expectOldSpec) {
|
||||||
|
t.Error(cmp.Diff(tc.oldSpec, tc.expectOldSpec))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func specWithCSISecrets(secret *api.SecretReference) *api.PersistentVolumeSpec {
|
||||||
|
pvSpec := &api.PersistentVolumeSpec{
|
||||||
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
|
CSI: &api.CSIPersistentVolumeSource{
|
||||||
|
Driver: "com.google.gcepd",
|
||||||
|
VolumeHandle: "foobar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if secret != nil {
|
||||||
|
pvSpec.CSI.NodeExpandSecretRef = secret
|
||||||
|
}
|
||||||
|
return pvSpec
|
||||||
|
}
|
@@ -149,6 +149,13 @@ func TestPVSecrets(t *testing.T) {
|
|||||||
ControllerExpandSecretRef: &corev1.SecretReference{
|
ControllerExpandSecretRef: &corev1.SecretReference{
|
||||||
Name: "Spec.PersistentVolumeSource.CSI.ControllerExpandSecretRef",
|
Name: "Spec.PersistentVolumeSource.CSI.ControllerExpandSecretRef",
|
||||||
Namespace: "csi"}}}}},
|
Namespace: "csi"}}}}},
|
||||||
|
{Spec: corev1.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||||
|
PersistentVolumeSource: corev1.PersistentVolumeSource{
|
||||||
|
CSI: &corev1.CSIPersistentVolumeSource{
|
||||||
|
NodeExpandSecretRef: &corev1.SecretReference{
|
||||||
|
Name: "Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef",
|
||||||
|
Namespace: "csi"}}}}},
|
||||||
}
|
}
|
||||||
extractedNames := sets.NewString()
|
extractedNames := sets.NewString()
|
||||||
extractedNamesWithNamespace := sets.NewString()
|
extractedNamesWithNamespace := sets.NewString()
|
||||||
@@ -181,6 +188,7 @@ func TestPVSecrets(t *testing.T) {
|
|||||||
"Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
"Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
||||||
"Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
"Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
||||||
"Spec.PersistentVolumeSource.CSI.ControllerExpandSecretRef",
|
"Spec.PersistentVolumeSource.CSI.ControllerExpandSecretRef",
|
||||||
|
"Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef",
|
||||||
)
|
)
|
||||||
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.PersistentVolume{}))
|
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.PersistentVolume{}))
|
||||||
secretPaths = secretPaths.Difference(excludedSecretPaths)
|
secretPaths = secretPaths.Difference(excludedSecretPaths)
|
||||||
@@ -229,6 +237,7 @@ func TestPVSecrets(t *testing.T) {
|
|||||||
"csi/Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
"csi/Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
|
||||||
"csi/Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
"csi/Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
|
||||||
"csi/Spec.PersistentVolumeSource.CSI.ControllerExpandSecretRef",
|
"csi/Spec.PersistentVolumeSource.CSI.ControllerExpandSecretRef",
|
||||||
|
"csi/Spec.PersistentVolumeSource.CSI.NodeExpandSecretRef",
|
||||||
)
|
)
|
||||||
if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 {
|
if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 {
|
||||||
t.Logf("Missing expected namespaced names:\n%s", strings.Join(missingNames.List(), "\n"))
|
t.Logf("Missing expected namespaced names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||||
|
@@ -2898,6 +2898,22 @@ func TestValidateCSIPersistentVolumeSource(t *testing.T) {
|
|||||||
errtype: field.ErrorTypeRequired,
|
errtype: field.ErrorTypeRequired,
|
||||||
errfield: "nodePublishSecretRef.namespace",
|
errfield: "nodePublishSecretRef.namespace",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "nodeExpandSecretRef: invalid name missing",
|
||||||
|
csi: &core.CSIPersistentVolumeSource{Driver: "com.google.gcepd", VolumeHandle: "foobar", NodeExpandSecretRef: &core.SecretReference{Namespace: "default"}},
|
||||||
|
errtype: field.ErrorTypeRequired,
|
||||||
|
errfield: "nodeExpandSecretRef.name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nodeExpandSecretRef: invalid namespace missing",
|
||||||
|
csi: &core.CSIPersistentVolumeSource{Driver: "com.google.gcepd", VolumeHandle: "foobar", NodeExpandSecretRef: &core.SecretReference{Name: "foobar"}},
|
||||||
|
errtype: field.ErrorTypeRequired,
|
||||||
|
errfield: "nodeExpandSecretRef.namespace",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid nodeExpandSecretRef",
|
||||||
|
csi: &core.CSIPersistentVolumeSource{Driver: "com.google.gcepd", VolumeHandle: "foobar", NodeExpandSecretRef: &core.SecretReference{Name: "foobar", Namespace: "default"}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
|
@@ -17,26 +17,34 @@ limitations under the License.
|
|||||||
package csi
|
package csi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
api "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNodeExpand(t *testing.T) {
|
func TestNodeExpand(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
nodeExpansion bool
|
nodeExpansion bool
|
||||||
nodeStageSet bool
|
nodeStageSet bool
|
||||||
success bool
|
success bool
|
||||||
fsVolume bool
|
fsVolume bool
|
||||||
grpcError error
|
grpcError error
|
||||||
hasVolumeInUseError bool
|
hasVolumeInUseError bool
|
||||||
deviceStagePath string
|
deviceStagePath string
|
||||||
|
enableCSINodeExpandSecret bool
|
||||||
|
secret *api.Secret
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "when node expansion is not set",
|
name: "when node expansion is not set",
|
||||||
@@ -87,13 +95,39 @@ func TestNodeExpand(t *testing.T) {
|
|||||||
grpcError: status.Error(codes.InvalidArgument, "invalid-argument"),
|
grpcError: status.Error(codes.InvalidArgument, "invalid-argument"),
|
||||||
hasVolumeInUseError: false,
|
hasVolumeInUseError: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "when nodeExpansion=on, nodeStage=on, volumePhase=staged",
|
||||||
|
nodeExpansion: true,
|
||||||
|
nodeStageSet: true,
|
||||||
|
success: true,
|
||||||
|
fsVolume: true,
|
||||||
|
deviceStagePath: "/foo/bar",
|
||||||
|
enableCSINodeExpandSecret: true,
|
||||||
|
secret: &api.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "expand-secret",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"apiUsername": []byte("csiusername"),
|
||||||
|
"apiPassword": []byte("csipassword"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSINodeExpandSecret, tc.enableCSINodeExpandSecret)()
|
||||||
plug, tmpDir := newTestPlugin(t, nil)
|
plug, tmpDir := newTestPlugin(t, nil)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
spec := volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 10, "expandable", "test-vol"), false)
|
spec := volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 10, "expandable", "test-vol"), false)
|
||||||
|
if tc.enableCSINodeExpandSecret {
|
||||||
|
spec.PersistentVolume.Spec.CSI.NodeExpandSecretRef = &api.SecretReference{
|
||||||
|
Name: tc.secret.Name,
|
||||||
|
Namespace: tc.secret.Namespace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newSize, _ := resource.ParseQuantity("20Gi")
|
newSize, _ := resource.ParseQuantity("20Gi")
|
||||||
|
|
||||||
@@ -110,6 +144,13 @@ func TestNodeExpand(t *testing.T) {
|
|||||||
fakeCSIClient, _ := csClient.(*fakeCsiDriverClient)
|
fakeCSIClient, _ := csClient.(*fakeCsiDriverClient)
|
||||||
fakeNodeClient := fakeCSIClient.nodeClient
|
fakeNodeClient := fakeCSIClient.nodeClient
|
||||||
|
|
||||||
|
if tc.enableCSINodeExpandSecret {
|
||||||
|
_, err := plug.host.GetKubeClient().CoreV1().Secrets(tc.secret.Namespace).Create(context.TODO(), tc.secret, metav1.CreateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if tc.grpcError != nil {
|
if tc.grpcError != nil {
|
||||||
fakeNodeClient.SetNextError(tc.grpcError)
|
fakeNodeClient.SetNextError(tc.grpcError)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user