From 55e1646fa42d4b2d02e9375d4ff72e29cf20b09f Mon Sep 17 00:00:00 2001 From: carlory Date: Thu, 4 Jan 2024 14:41:33 +0800 Subject: [PATCH] removed the deprecated azureFile in-tree storage plugin --- .../app/plugins_providers.go | 22 +- cmd/kubelet/app/plugins_providers.go | 2 - pkg/features/kube_features.go | 10 - pkg/volume/azure_file/OWNERS | 18 - pkg/volume/azure_file/azure_file.go | 414 ---------------- pkg/volume/azure_file/azure_file_test.go | 454 ------------------ pkg/volume/azure_file/azure_provision.go | 284 ----------- pkg/volume/azure_file/azure_util.go | 162 ------- pkg/volume/azure_file/doc.go | 19 - pkg/volume/csi/csi_plugin.go | 2 +- pkg/volume/csimigration/plugin_manager.go | 2 +- 11 files changed, 3 insertions(+), 1386 deletions(-) delete mode 100644 pkg/volume/azure_file/OWNERS delete mode 100644 pkg/volume/azure_file/azure_file.go delete mode 100644 pkg/volume/azure_file/azure_file_test.go delete mode 100644 pkg/volume/azure_file/azure_provision.go delete mode 100644 pkg/volume/azure_file/azure_util.go delete mode 100644 pkg/volume/azure_file/doc.go diff --git a/cmd/kube-controller-manager/app/plugins_providers.go b/cmd/kube-controller-manager/app/plugins_providers.go index 999b42b623d..8f95263ef81 100644 --- a/cmd/kube-controller-manager/app/plugins_providers.go +++ b/cmd/kube-controller-manager/app/plugins_providers.go @@ -25,7 +25,6 @@ import ( "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/azure_file" "k8s.io/kubernetes/pkg/volume/csimigration" "k8s.io/kubernetes/pkg/volume/portworx" "k8s.io/kubernetes/pkg/volume/rbd" @@ -77,24 +76,5 @@ func appendExpandableLegacyProviderVolumes(logger klog.Logger, allPlugins []volu } func appendLegacyProviderVolumes(logger klog.Logger, allPlugins []volume.VolumePlugin, featureGate featuregate.FeatureGate) ([]volume.VolumePlugin, error) { - var err error - // First append attachable volumes - allPlugins, err = appendAttachableLegacyProviderVolumes(logger, allPlugins, featureGate) - if err != nil { - return allPlugins, err - } - - // Then append non-attachable volumes - pluginName := plugins.AzureFileInTreePluginName - pluginInfo := pluginInfo{ - pluginMigrationFeature: features.CSIMigrationAzureFile, - pluginUnregisterFeature: features.InTreePluginAzureFileUnregister, - pluginProbeFunction: azure_file.ProbeVolumePlugins, - } - allPlugins, err = appendPluginBasedOnFeatureFlags(logger, allPlugins, pluginName, featureGate, pluginInfo) - if err != nil { - return allPlugins, err - } - - return allPlugins, nil + return appendAttachableLegacyProviderVolumes(logger, allPlugins, featureGate) } diff --git a/cmd/kubelet/app/plugins_providers.go b/cmd/kubelet/app/plugins_providers.go index 98a0631496d..a025f36cc59 100644 --- a/cmd/kubelet/app/plugins_providers.go +++ b/cmd/kubelet/app/plugins_providers.go @@ -29,7 +29,6 @@ import ( "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/azure_file" "k8s.io/kubernetes/pkg/volume/csimigration" "k8s.io/kubernetes/pkg/volume/portworx" "k8s.io/kubernetes/pkg/volume/rbd" @@ -64,7 +63,6 @@ type pluginInfo struct { func appendLegacyProviderVolumes(allPlugins []volume.VolumePlugin, featureGate featuregate.FeatureGate) ([]volume.VolumePlugin, error) { pluginMigrationStatus := make(map[string]pluginInfo) - pluginMigrationStatus[plugins.AzureFileInTreePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationAzureFile, pluginUnregisterFeature: features.InTreePluginAzureFileUnregister, pluginProbeFunction: azure_file.ProbeVolumePlugins} pluginMigrationStatus[plugins.PortworxVolumePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationPortworx, pluginUnregisterFeature: features.InTreePluginPortworxUnregister, pluginProbeFunction: portworx.ProbeVolumePlugins} pluginMigrationStatus[plugins.RBDVolumePluginName] = pluginInfo{pluginMigrationFeature: features.CSIMigrationRBD, pluginUnregisterFeature: features.InTreePluginRBDUnregister, pluginProbeFunction: rbd.ProbeVolumePlugins} var err error diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 25b51836b24..c12ced3cc4c 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -129,14 +129,6 @@ const ( // Allow the usage of options to fine-tune the cpumanager policies. CPUManagerPolicyOptions featuregate.Feature = "CPUManagerPolicyOptions" - // owner: @andyzhangx - // alpha: v1.15 - // beta: v1.21 - // GA: v1.26 - // - // Enables the Azure File in-tree driver to Azure File Driver migration feature. - CSIMigrationAzureFile featuregate.Feature = "CSIMigrationAzureFile" - // owner: @mfordjody // alpha: v1.26 // @@ -961,8 +953,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS CPUManagerPolicyOptions: {Default: true, PreRelease: featuregate.Beta}, - CSIMigrationAzureFile: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.28 - CSIMigrationPortworx: {Default: false, PreRelease: featuregate.Beta}, // Off by default (requires Portworx CSI driver) CSIMigrationRBD: {Default: false, PreRelease: featuregate.Deprecated}, // deprecated in 1.28, remove in 1.31 diff --git a/pkg/volume/azure_file/OWNERS b/pkg/volume/azure_file/OWNERS deleted file mode 100644 index 71675e1ce81..00000000000 --- a/pkg/volume/azure_file/OWNERS +++ /dev/null @@ -1,18 +0,0 @@ -# See the OWNERS docs at https://go.k8s.io/owners - -approvers: - - andyzhangx - - feiskyer - - khenidak -reviewers: - - andyzhangx - - feiskyer - - jsafrane - - jingxu97 - - khenidak - - msau42 - - saad-ali -emeritus_approvers: - - karataliu - - rootfs - - brendandburns diff --git a/pkg/volume/azure_file/azure_file.go b/pkg/volume/azure_file/azure_file.go deleted file mode 100644 index 8c00c41b579..00000000000 --- a/pkg/volume/azure_file/azure_file.go +++ /dev/null @@ -1,414 +0,0 @@ -//go:build !providerless -// +build !providerless - -/* -Copyright 2016 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 azure_file - -import ( - "fmt" - "io/ioutil" - "os" - "runtime" - "time" - - "k8s.io/klog/v2" - "k8s.io/mount-utils" - utilstrings "k8s.io/utils/strings" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" - cloudprovider "k8s.io/cloud-provider" - volumehelpers "k8s.io/cloud-provider/volume/helpers" - "k8s.io/kubernetes/pkg/volume" - volutil "k8s.io/kubernetes/pkg/volume/util" - "k8s.io/legacy-cloud-providers/azure" -) - -// ProbeVolumePlugins is the primary endpoint for volume plugins -func ProbeVolumePlugins() []volume.VolumePlugin { - return []volume.VolumePlugin{&azureFilePlugin{nil}} -} - -type azureFilePlugin struct { - host volume.VolumeHost -} - -var _ volume.VolumePlugin = &azureFilePlugin{} -var _ volume.PersistentVolumePlugin = &azureFilePlugin{} -var _ volume.ExpandableVolumePlugin = &azureFilePlugin{} - -const ( - azureFilePluginName = "kubernetes.io/azure-file" - minimumPremiumShareSize = 100 // GB -) - -func getPath(uid types.UID, volName string, host volume.VolumeHost) string { - return host.GetPodVolumeDir(uid, utilstrings.EscapeQualifiedName(azureFilePluginName), volName) -} - -func (plugin *azureFilePlugin) Init(host volume.VolumeHost) error { - plugin.host = host - return nil -} - -func (plugin *azureFilePlugin) GetPluginName() string { - return azureFilePluginName -} - -func (plugin *azureFilePlugin) GetVolumeName(spec *volume.Spec) (string, error) { - share, _, err := getVolumeSource(spec) - if err != nil { - return "", err - } - - return share, nil -} - -func (plugin *azureFilePlugin) CanSupport(spec *volume.Spec) bool { - //TODO: check if mount.cifs is there - return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AzureFile != nil) || - (spec.Volume != nil && spec.Volume.AzureFile != nil) -} - -func (plugin *azureFilePlugin) RequiresRemount(spec *volume.Spec) bool { - return false -} - -func (plugin *azureFilePlugin) SupportsMountOption() bool { - return true -} - -func (plugin *azureFilePlugin) SupportsBulkVolumeVerification() bool { - return false -} - -func (plugin *azureFilePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) { - return false, nil -} - -func (plugin *azureFilePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { - return []v1.PersistentVolumeAccessMode{ - v1.ReadWriteOnce, - v1.ReadOnlyMany, - v1.ReadWriteMany, - } -} - -func (plugin *azureFilePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { - return plugin.newMounterInternal(spec, pod, &azureSvc{}, plugin.host.GetMounter(plugin.GetPluginName())) -} - -func (plugin *azureFilePlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, util azureUtil, mounter mount.Interface) (volume.Mounter, error) { - share, readOnly, err := getVolumeSource(spec) - if err != nil { - return nil, err - } - secretName, secretNamespace, err := getSecretNameAndNamespace(spec, pod.Namespace) - if err != nil { - // Log-and-continue instead of returning an error for now - // due to unspecified backwards compatibility concerns (a subject to revise) - klog.Errorf("get secret name and namespace from pod(%s) return with error: %v", pod.Name, err) - } - return &azureFileMounter{ - azureFile: &azureFile{ - volName: spec.Name(), - mounter: mounter, - pod: pod, - plugin: plugin, - MetricsProvider: volume.NewMetricsStatFS(getPath(pod.UID, spec.Name(), plugin.host)), - }, - util: util, - secretNamespace: secretNamespace, - secretName: secretName, - shareName: share, - readOnly: readOnly, - mountOptions: volutil.MountOptionFromSpec(spec), - }, nil -} - -func (plugin *azureFilePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) { - return plugin.newUnmounterInternal(volName, podUID, plugin.host.GetMounter(plugin.GetPluginName())) -} - -func (plugin *azureFilePlugin) newUnmounterInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Unmounter, error) { - return &azureFileUnmounter{&azureFile{ - volName: volName, - mounter: mounter, - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: podUID}}, - plugin: plugin, - MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, plugin.host)), - }}, nil -} - -func (plugin *azureFilePlugin) RequiresFSResize() bool { - return false -} - -func (plugin *azureFilePlugin) ExpandVolumeDevice( - spec *volume.Spec, - newSize resource.Quantity, - oldSize resource.Quantity) (resource.Quantity, error) { - - if spec.PersistentVolume == nil || spec.PersistentVolume.Spec.AzureFile == nil { - return oldSize, fmt.Errorf("invalid PV spec") - } - shareName := spec.PersistentVolume.Spec.AzureFile.ShareName - azure, resourceGroup, err := getAzureCloudProvider(plugin.host.GetCloudProvider()) - if err != nil { - return oldSize, err - } - if spec.PersistentVolume.ObjectMeta.Annotations[resourceGroupAnnotation] != "" { - resourceGroup = spec.PersistentVolume.ObjectMeta.Annotations[resourceGroupAnnotation] - } - - secretName, secretNamespace, err := getSecretNameAndNamespace(spec, spec.PersistentVolume.Spec.ClaimRef.Namespace) - if err != nil { - return oldSize, err - } - - accountName, _, err := (&azureSvc{}).GetAzureCredentials(plugin.host, secretNamespace, secretName) - if err != nil { - return oldSize, err - } - - requestGiB, err := volumehelpers.RoundUpToGiBInt(newSize) - - if err != nil { - return oldSize, err - } - - if err := azure.ResizeFileShare(resourceGroup, accountName, shareName, requestGiB); err != nil { - return oldSize, err - } - - return newSize, nil -} - -func (plugin *azureFilePlugin) ConstructVolumeSpec(volName, mountPath string) (volume.ReconstructedVolume, error) { - azureVolume := &v1.Volume{ - Name: volName, - VolumeSource: v1.VolumeSource{ - AzureFile: &v1.AzureFileVolumeSource{ - SecretName: volName, - ShareName: volName, - }, - }, - } - return volume.ReconstructedVolume{ - Spec: volume.NewSpecFromVolume(azureVolume), - }, nil -} - -// azureFile volumes represent mount of an AzureFile share. -type azureFile struct { - volName string - podUID types.UID - pod *v1.Pod - mounter mount.Interface - plugin *azureFilePlugin - volume.MetricsProvider -} - -func (azureFileVolume *azureFile) GetPath() string { - return getPath(azureFileVolume.pod.UID, azureFileVolume.volName, azureFileVolume.plugin.host) -} - -type azureFileMounter struct { - *azureFile - util azureUtil - secretName string - secretNamespace string - shareName string - readOnly bool - mountOptions []string -} - -var _ volume.Mounter = &azureFileMounter{} - -func (b *azureFileMounter) GetAttributes() volume.Attributes { - return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: !b.readOnly, - SELinuxRelabel: false, - } -} - -// SetUp attaches the disk and bind mounts to the volume path. -func (b *azureFileMounter) SetUp(mounterArgs volume.MounterArgs) error { - return b.SetUpAt(b.GetPath(), mounterArgs) -} - -func (b *azureFileMounter) SetUpAt(dir string, mounterArgs volume.MounterArgs) error { - notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) - klog.V(4).Infof("AzureFile mount set up: %s %v %v", dir, !notMnt, err) - if err != nil && !os.IsNotExist(err) { - return err - } - if !notMnt { - // testing original mount point, make sure the mount link is valid - if _, err := ioutil.ReadDir(dir); err == nil { - klog.V(4).Infof("azureFile - already mounted to target %s", dir) - return nil - } - // mount link is invalid, now unmount and remount later - klog.Warningf("azureFile - ReadDir %s failed with %v, unmount this directory", dir, err) - if err := b.mounter.Unmount(dir); err != nil { - klog.Errorf("azureFile - Unmount directory %s failed with %v", dir, err) - return err - } - } - - var accountKey, accountName string - if accountName, accountKey, err = b.util.GetAzureCredentials(b.plugin.host, b.secretNamespace, b.secretName); err != nil { - return err - } - - var mountOptions []string - var sensitiveMountOptions []string - source := "" - osSeparator := string(os.PathSeparator) - source = fmt.Sprintf("%s%s%s.file.%s%s%s", osSeparator, osSeparator, accountName, getStorageEndpointSuffix(b.plugin.host.GetCloudProvider()), osSeparator, b.shareName) - - if runtime.GOOS == "windows" { - mountOptions = []string{fmt.Sprintf("AZURE\\%s", accountName)} - sensitiveMountOptions = []string{accountKey} - } else { - if err := os.MkdirAll(dir, 0700); err != nil { - return err - } - // parameters suggested by https://azure.microsoft.com/en-us/documentation/articles/storage-how-to-use-files-linux/ - options := []string{} - sensitiveMountOptions = []string{fmt.Sprintf("username=%s,password=%s", accountName, accountKey)} - if b.readOnly { - options = append(options, "ro") - } - mountOptions = volutil.JoinMountOptions(b.mountOptions, options) - mountOptions = appendDefaultMountOptions(mountOptions, mounterArgs.FsGroup) - } - - mountComplete := false - err = wait.PollImmediate(1*time.Second, 2*time.Minute, func() (bool, error) { - err := b.mounter.MountSensitiveWithoutSystemd(source, dir, "cifs", mountOptions, sensitiveMountOptions) - mountComplete = true - return true, err - }) - if !mountComplete { - return fmt.Errorf("volume(%s) mount on %s timeout(10m)", source, dir) - } - if err != nil { - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) - if mntErr != nil { - klog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) - return err - } - if !notMnt { - if mntErr = b.mounter.Unmount(dir); mntErr != nil { - klog.Errorf("Failed to unmount: %v", mntErr) - return err - } - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) - if mntErr != nil { - klog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) - return err - } - if !notMnt { - // This is very odd, we don't expect it. We'll try again next sync loop. - klog.Errorf("%s is still mounted, despite call to unmount(). Will try again next sync loop.", dir) - return err - } - } - os.Remove(dir) - return err - } - return nil -} - -var _ volume.Unmounter = &azureFileUnmounter{} - -type azureFileUnmounter struct { - *azureFile -} - -func (c *azureFileUnmounter) TearDown() error { - return c.TearDownAt(c.GetPath()) -} - -func (c *azureFileUnmounter) TearDownAt(dir string) error { - return mount.CleanupMountPoint(dir, c.mounter, false) -} - -func getVolumeSource(spec *volume.Spec) (string, bool, error) { - if spec.Volume != nil && spec.Volume.AzureFile != nil { - share := spec.Volume.AzureFile.ShareName - readOnly := spec.Volume.AzureFile.ReadOnly - return share, readOnly, nil - } else if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.AzureFile != nil { - share := spec.PersistentVolume.Spec.AzureFile.ShareName - readOnly := spec.ReadOnly - return share, readOnly, nil - } - return "", false, fmt.Errorf("Spec does not reference an AzureFile volume type") -} - -func getSecretNameAndNamespace(spec *volume.Spec, defaultNamespace string) (string, string, error) { - secretName := "" - secretNamespace := "" - if spec.Volume != nil && spec.Volume.AzureFile != nil { - secretName = spec.Volume.AzureFile.SecretName - secretNamespace = defaultNamespace - - } else if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.AzureFile != nil { - secretNamespace = defaultNamespace - if spec.PersistentVolume.Spec.AzureFile.SecretNamespace != nil { - secretNamespace = *spec.PersistentVolume.Spec.AzureFile.SecretNamespace - } - secretName = spec.PersistentVolume.Spec.AzureFile.SecretName - } else { - return "", "", fmt.Errorf("Spec does not reference an AzureFile volume type") - } - - if len(secretNamespace) == 0 { - return "", "", fmt.Errorf("invalid Azure volume: nil namespace") - } - return secretName, secretNamespace, nil - -} - -func getAzureCloud(cloudProvider cloudprovider.Interface) (*azure.Cloud, error) { - azure, ok := cloudProvider.(*azure.Cloud) - if !ok || azure == nil { - return nil, fmt.Errorf("failed to get Azure Cloud Provider. GetCloudProvider returned %v instead", cloudProvider) - } - - return azure, nil -} - -func getStorageEndpointSuffix(cloudprovider cloudprovider.Interface) string { - const publicCloudStorageEndpointSuffix = "core.windows.net" - azure, err := getAzureCloud(cloudprovider) - if err != nil { - klog.Warningf("No Azure cloud provider found. Using the Azure public cloud endpoint: %s", publicCloudStorageEndpointSuffix) - return publicCloudStorageEndpointSuffix - } - return azure.Environment.StorageEndpointSuffix -} diff --git a/pkg/volume/azure_file/azure_file_test.go b/pkg/volume/azure_file/azure_file_test.go deleted file mode 100644 index 59096837206..00000000000 --- a/pkg/volume/azure_file/azure_file_test.go +++ /dev/null @@ -1,454 +0,0 @@ -//go:build !providerless -// +build !providerless - -/* -Copyright 2016 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 azure_file - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "reflect" - goruntime "runtime" - "strings" - "testing" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes/fake" - fakecloud "k8s.io/cloud-provider/fake" - "k8s.io/mount-utils" - "k8s.io/utils/pointer" - - "k8s.io/kubernetes/pkg/volume" - volumetest "k8s.io/kubernetes/pkg/volume/testing" - "k8s.io/legacy-cloud-providers/azure" -) - -func TestCanSupport(t *testing.T) { - tmpDir, err := ioutil.TempDir(os.TempDir(), "azureFileTest") - if err != nil { - t.Fatalf("can't make a temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)) - - plug, err := plugMgr.FindPluginByName("kubernetes.io/azure-file") - if err != nil { - t.Fatal("Can't find the plugin by name") - } - if plug.GetPluginName() != "kubernetes.io/azure-file" { - t.Errorf("Wrong name: %s", plug.GetPluginName()) - } - if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{AzureFile: &v1.AzureFileVolumeSource{}}}}) { - t.Errorf("Expected true") - } - if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{AzureFile: &v1.AzureFilePersistentVolumeSource{}}}}}) { - t.Errorf("Expected true") - } -} - -func TestGetAccessModes(t *testing.T) { - tmpDir, err := ioutil.TempDir(os.TempDir(), "azureFileTest") - if err != nil { - t.Fatalf("can't make a temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)) - - plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/azure-file") - if err != nil { - t.Errorf("Can't find the plugin by name") - } - if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteMany) { - t.Errorf("Expected three AccessModeTypes: %s, %s, and %s", v1.ReadWriteOnce, v1.ReadOnlyMany, v1.ReadWriteMany) - } -} - -func getAzureTestCloud(t *testing.T) *azure.Cloud { - config := `{ - "aadClientId": "--aad-client-id--", - "aadClientSecret": "--aad-client-secret--" - }` - configReader := strings.NewReader(config) - azureCloud, err := azure.NewCloudWithoutFeatureGates(configReader) - if err != nil { - t.Error(err) - } - return azureCloud -} - -func getTestTempDir(t *testing.T) string { - tmpDir, err := ioutil.TempDir(os.TempDir(), "azurefileTest") - if err != nil { - t.Fatalf("can't make a temp dir: %v", err) - } - return tmpDir -} - -func TestPluginAzureCloudProvider(t *testing.T) { - tmpDir := getTestTempDir(t) - defer os.RemoveAll(tmpDir) - testPlugin(t, tmpDir, volumetest.NewFakeVolumeHostWithCloudProvider(t, tmpDir, nil, nil, getAzureTestCloud(t))) -} - -func TestPluginWithoutCloudProvider(t *testing.T) { - tmpDir := getTestTempDir(t) - defer os.RemoveAll(tmpDir) - testPlugin(t, tmpDir, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)) -} - -func TestPluginWithOtherCloudProvider(t *testing.T) { - tmpDir := getTestTempDir(t) - defer os.RemoveAll(tmpDir) - cloud := &fakecloud.Cloud{} - testPlugin(t, tmpDir, volumetest.NewFakeVolumeHostWithCloudProvider(t, tmpDir, nil, nil, cloud)) -} - -func testPlugin(t *testing.T, tmpDir string, volumeHost volume.VolumeHost) { - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumeHost) - - plug, err := plugMgr.FindPluginByName("kubernetes.io/azure-file") - if err != nil { - t.Errorf("Can't find the plugin by name") - } - spec := &v1.Volume{ - Name: "vol1", - VolumeSource: v1.VolumeSource{ - AzureFile: &v1.AzureFileVolumeSource{ - SecretName: "secret", - ShareName: "share", - }, - }, - } - fake := mount.NewFakeMounter(nil) - pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} - mounter, err := plug.(*azureFilePlugin).newMounterInternal(volume.NewSpecFromVolume(spec), pod, &fakeAzureSvc{}, fake) - if err != nil { - t.Errorf("Failed to make a new Mounter: %v", err) - } - if mounter == nil { - t.Errorf("Got a nil Mounter") - } - volPath := filepath.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~azure-file/vol1") - path := mounter.GetPath() - if path != volPath { - t.Errorf("Got unexpected path: %s", path) - } - - if err := mounter.SetUp(volume.MounterArgs{}); err != nil { - t.Errorf("Expected success, got: %v", err) - } - // On Windows, Mount will create the parent of dir and mklink (create a symbolic link) at the volume path later, - // so mounter.SetUp will not create the directory. Otherwise mklink will error: "Cannot create a file when that file already exists". - if goruntime.GOOS != "windows" { - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - t.Errorf("SetUp() failed, volume path not created: %s", path) - } else { - t.Errorf("SetUp() failed: %v", err) - } - } - } - - unmounter, err := plug.(*azureFilePlugin).newUnmounterInternal("vol1", types.UID("poduid"), mount.NewFakeMounter(nil)) - if err != nil { - t.Errorf("Failed to make a new Unmounter: %v", err) - } - if unmounter == nil { - t.Errorf("Got a nil Unmounter") - } - - if err := unmounter.TearDown(); err != nil { - t.Errorf("Expected success, got: %v", err) - } - if _, err := os.Stat(path); err == nil { - t.Errorf("TearDown() failed, volume path still exists: %s", path) - } else if !os.IsNotExist(err) { - t.Errorf("TearDown() failed: %v", err) - } -} - -func TestPersistentClaimReadOnlyFlag(t *testing.T) { - pv := &v1.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pvA", - }, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - AzureFile: &v1.AzureFilePersistentVolumeSource{}, - }, - ClaimRef: &v1.ObjectReference{ - Name: "claimA", - }, - }, - } - - claim := &v1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "claimA", - Namespace: "nsA", - }, - Spec: v1.PersistentVolumeClaimSpec{ - VolumeName: "pvA", - }, - Status: v1.PersistentVolumeClaimStatus{ - Phase: v1.ClaimBound, - }, - } - - client := fake.NewSimpleClientset(pv, claim) - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, filepath.Join(os.TempDir(), "fake"), client, nil)) - plug, _ := plugMgr.FindPluginByName(azureFilePluginName) - - // readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes - spec := volume.NewSpecFromPersistentVolume(pv, true) - pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} - mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{}) - if mounter == nil { - t.Fatalf("Got a nil Mounter") - } - - if !mounter.GetAttributes().ReadOnly { - t.Errorf("Expected true for mounter.IsReadOnly") - } -} - -type fakeAzureSvc struct{} - -func (s *fakeAzureSvc) GetAzureCredentials(host volume.VolumeHost, nameSpace, secretName string) (string, string, error) { - return "name", "key", nil -} -func (s *fakeAzureSvc) SetAzureCredentials(host volume.VolumeHost, nameSpace, accountName, accountKey string) (string, error) { - return "secret", nil -} - -func TestMounterAndUnmounterTypeAssert(t *testing.T) { - tmpDir, err := ioutil.TempDir(os.TempDir(), "azurefileTest") - if err != nil { - t.Fatalf("can't make a temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)) - - plug, err := plugMgr.FindPluginByName("kubernetes.io/azure-file") - if err != nil { - t.Errorf("Can't find the plugin by name") - } - spec := &v1.Volume{ - Name: "vol1", - VolumeSource: v1.VolumeSource{ - AzureFile: &v1.AzureFileVolumeSource{ - SecretName: "secret", - ShareName: "share", - }, - }, - } - fake := mount.NewFakeMounter(nil) - pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} - mounter, err := plug.(*azureFilePlugin).newMounterInternal(volume.NewSpecFromVolume(spec), pod, &fakeAzureSvc{}, fake) - if err != nil { - t.Errorf("MounterInternal() failed: %v", err) - } - if _, ok := mounter.(volume.Unmounter); ok { - t.Errorf("Volume Mounter can be type-assert to Unmounter") - } - - unmounter, err := plug.(*azureFilePlugin).newUnmounterInternal("vol1", types.UID("poduid"), mount.NewFakeMounter(nil)) - if err != nil { - t.Errorf("MounterInternal() failed: %v", err) - } - if _, ok := unmounter.(volume.Mounter); ok { - t.Errorf("Volume Unmounter can be type-assert to Mounter") - } -} - -type testcase struct { - name string - defaultNs string - spec *volume.Spec - // Expected return of the test - expectedName string - expectedNs string - expectedError error -} - -func TestGetSecretNameAndNamespaceForPV(t *testing.T) { - secretNs := "ns" - tests := []testcase{ - { - name: "persistent volume source", - defaultNs: "default", - spec: &volume.Spec{ - PersistentVolume: &v1.PersistentVolume{ - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - AzureFile: &v1.AzureFilePersistentVolumeSource{ - ShareName: "share", - SecretName: "name", - SecretNamespace: &secretNs, - }, - }, - }, - }, - }, - expectedName: "name", - expectedNs: "ns", - expectedError: nil, - }, - { - name: "persistent volume source without namespace", - defaultNs: "default", - spec: &volume.Spec{ - PersistentVolume: &v1.PersistentVolume{ - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - AzureFile: &v1.AzureFilePersistentVolumeSource{ - ShareName: "share", - SecretName: "name", - }, - }, - }, - }, - }, - expectedName: "name", - expectedNs: "default", - expectedError: nil, - }, - { - name: "pod volume source", - defaultNs: "default", - spec: &volume.Spec{ - Volume: &v1.Volume{ - VolumeSource: v1.VolumeSource{ - AzureFile: &v1.AzureFileVolumeSource{ - ShareName: "share", - SecretName: "name", - }, - }, - }, - }, - expectedName: "name", - expectedNs: "default", - expectedError: nil, - }, - } - for _, testcase := range tests { - resultName, resultNs, err := getSecretNameAndNamespace(testcase.spec, testcase.defaultNs) - if err != testcase.expectedError || resultName != testcase.expectedName || resultNs != testcase.expectedNs { - t.Errorf("%s failed: expected err=%v ns=%q name=%q, got %v/%q/%q", testcase.name, testcase.expectedError, testcase.expectedNs, testcase.expectedName, - err, resultNs, resultName) - } - } - -} - -func TestAppendDefaultMountOptions(t *testing.T) { - tests := []struct { - options []string - fsGroup *int64 - expected []string - }{ - { - options: []string{"dir_mode=0777"}, - fsGroup: nil, - expected: []string{"dir_mode=0777", - fmt.Sprintf("%s=%s", fileMode, defaultFileMode), - fmt.Sprintf("%s=%s", vers, defaultVers), - fmt.Sprintf("%s=%s", actimeo, defaultActimeo), - mfsymlinks, - }, - }, - { - options: []string{"file_mode=0777"}, - fsGroup: pointer.Int64(0), - expected: []string{"file_mode=0777", - fmt.Sprintf("%s=%s", dirMode, defaultDirMode), - fmt.Sprintf("%s=%s", vers, defaultVers), - fmt.Sprintf("%s=0", gid), - fmt.Sprintf("%s=%s", actimeo, defaultActimeo), - mfsymlinks, - }, - }, - { - options: []string{"vers=2.1"}, - fsGroup: pointer.Int64(1000), - expected: []string{"vers=2.1", - fmt.Sprintf("%s=%s", fileMode, defaultFileMode), - fmt.Sprintf("%s=%s", dirMode, defaultDirMode), - fmt.Sprintf("%s=1000", gid), - fmt.Sprintf("%s=%s", actimeo, defaultActimeo), - mfsymlinks, - }, - }, - { - options: []string{""}, - expected: []string{"", fmt.Sprintf("%s=%s", - fileMode, defaultFileMode), - fmt.Sprintf("%s=%s", dirMode, defaultDirMode), - fmt.Sprintf("%s=%s", vers, defaultVers), - fmt.Sprintf("%s=%s", actimeo, defaultActimeo), - mfsymlinks, - }, - }, - { - options: []string{"file_mode=0777", "dir_mode=0777"}, - expected: []string{"file_mode=0777", "dir_mode=0777", - fmt.Sprintf("%s=%s", vers, defaultVers), - fmt.Sprintf("%s=%s", actimeo, defaultActimeo), - mfsymlinks, - }, - }, - { - options: []string{"gid=2000"}, - fsGroup: pointer.Int64(1000), - expected: []string{"gid=2000", - fmt.Sprintf("%s=%s", fileMode, defaultFileMode), - fmt.Sprintf("%s=%s", dirMode, defaultDirMode), - "vers=3.0", - fmt.Sprintf("%s=%s", actimeo, defaultActimeo), - mfsymlinks, - }, - }, - { - options: []string{"actimeo=3"}, - expected: []string{ - "actimeo=3", - fmt.Sprintf("%s=%s", fileMode, defaultFileMode), - fmt.Sprintf("%s=%s", dirMode, defaultDirMode), - fmt.Sprintf("%s=%s", vers, defaultVers), - mfsymlinks, - }, - }, - } - - for _, test := range tests { - result := appendDefaultMountOptions(test.options, test.fsGroup) - if !reflect.DeepEqual(result, test.expected) { - t.Errorf("input: %q, appendDefaultMountOptions result: %q, expected: %q", test.options, result, test.expected) - } - } -} diff --git a/pkg/volume/azure_file/azure_provision.go b/pkg/volume/azure_file/azure_provision.go deleted file mode 100644 index 9635348b3da..00000000000 --- a/pkg/volume/azure_file/azure_provision.go +++ /dev/null @@ -1,284 +0,0 @@ -//go:build !providerless -// +build !providerless - -/* -Copyright 2017 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 azure_file - -import ( - "fmt" - "strings" - - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - cloudprovider "k8s.io/cloud-provider" - volumehelpers "k8s.io/cloud-provider/volume/helpers" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/util" - "k8s.io/legacy-cloud-providers/azure" - "k8s.io/legacy-cloud-providers/azure/clients/fileclient" - utilstrings "k8s.io/utils/strings" -) - -var ( - _ volume.DeletableVolumePlugin = &azureFilePlugin{} - _ volume.ProvisionableVolumePlugin = &azureFilePlugin{} - - resourceGroupAnnotation = "kubernetes.io/azure-file-resource-group" -) - -// Abstract interface to file share operations. -// azure cloud provider should implement it -type azureCloudProvider interface { - // create a file share - CreateFileShare(account *azure.AccountOptions, fileShare *fileclient.ShareOptions) (string, string, error) - // delete a file share - DeleteFileShare(resourceGroup, accountName, shareName string) error - // resize a file share - ResizeFileShare(resourceGroup, accountName, name string, sizeGiB int) error -} - -type azureFileDeleter struct { - *azureFile - resourceGroup, accountName, shareName string - azureProvider azureCloudProvider -} - -func (plugin *azureFilePlugin) NewDeleter(logger klog.Logger, spec *volume.Spec) (volume.Deleter, error) { - azure, resourceGroup, err := getAzureCloudProvider(plugin.host.GetCloudProvider()) - if err != nil { - klog.V(4).Infof("failed to get azure provider") - return nil, err - } - if spec.PersistentVolume != nil && spec.PersistentVolume.ObjectMeta.Annotations[resourceGroupAnnotation] != "" { - resourceGroup = spec.PersistentVolume.ObjectMeta.Annotations[resourceGroupAnnotation] - } - - return plugin.newDeleterInternal(spec, &azureSvc{}, azure, resourceGroup) -} - -func (plugin *azureFilePlugin) newDeleterInternal(spec *volume.Spec, util azureUtil, azure azureCloudProvider, resourceGroup string) (volume.Deleter, error) { - if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AzureFile == nil { - return nil, fmt.Errorf("invalid PV spec") - } - - secretName, secretNamespace, err := getSecretNameAndNamespace(spec, spec.PersistentVolume.Spec.ClaimRef.Namespace) - if err != nil { - return nil, err - } - shareName := spec.PersistentVolume.Spec.AzureFile.ShareName - if accountName, _, err := util.GetAzureCredentials(plugin.host, secretNamespace, secretName); err != nil { - return nil, err - } else { - - return &azureFileDeleter{ - azureFile: &azureFile{ - volName: spec.Name(), - plugin: plugin, - }, - resourceGroup: resourceGroup, - shareName: shareName, - accountName: accountName, - azureProvider: azure, - }, nil - } -} - -func (plugin *azureFilePlugin) NewProvisioner(logger klog.Logger, options volume.VolumeOptions) (volume.Provisioner, error) { - azure, resourceGroup, err := getAzureCloudProvider(plugin.host.GetCloudProvider()) - if err != nil { - klog.V(4).Infof("failed to get azure provider") - return nil, err - } - if len(options.PVC.Spec.AccessModes) == 0 { - options.PVC.Spec.AccessModes = plugin.GetAccessModes() - } - if resourceGroup != "" { - options.PVC.ObjectMeta.Annotations[resourceGroupAnnotation] = resourceGroup - } - return plugin.newProvisionerInternal(options, azure) -} - -func (plugin *azureFilePlugin) newProvisionerInternal(options volume.VolumeOptions, azure azureCloudProvider) (volume.Provisioner, error) { - return &azureFileProvisioner{ - azureFile: &azureFile{ - plugin: plugin, - }, - azureProvider: azure, - util: &azureSvc{}, - options: options, - }, nil -} - -var _ volume.Deleter = &azureFileDeleter{} - -func (f *azureFileDeleter) GetPath() string { - name := azureFilePluginName - return f.plugin.host.GetPodVolumeDir(f.podUID, utilstrings.EscapeQualifiedName(name), f.volName) -} - -func (f *azureFileDeleter) Delete() error { - klog.V(4).Infof("deleting volume %s", f.shareName) - return f.azureProvider.DeleteFileShare(f.resourceGroup, f.accountName, f.shareName) -} - -type azureFileProvisioner struct { - *azureFile - azureProvider azureCloudProvider - util azureUtil - options volume.VolumeOptions -} - -var _ volume.Provisioner = &azureFileProvisioner{} - -func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { - if !util.ContainsAllAccessModes(a.plugin.GetAccessModes(), a.options.PVC.Spec.AccessModes) { - return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", a.options.PVC.Spec.AccessModes, a.plugin.GetAccessModes()) - } - if util.CheckPersistentVolumeClaimModeBlock(a.options.PVC) { - return nil, fmt.Errorf("%s does not support block volume provisioning", a.plugin.GetPluginName()) - } - - var sku, resourceGroup, location, account, shareName, customTags string - - capacity := a.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] - requestGiB, err := volumehelpers.RoundUpToGiBInt(capacity) - if err != nil { - return nil, err - } - - secretNamespace := a.options.PVC.Namespace - // Apply ProvisionerParameters (case-insensitive). We leave validation of - // the values to the cloud provider. - for k, v := range a.options.Parameters { - switch strings.ToLower(k) { - case "skuname": - sku = v - case "location": - location = v - case "storageaccount": - account = v - case "secretnamespace": - secretNamespace = v - case "resourcegroup": - resourceGroup = v - case "sharename": - shareName = v - case "tags": - customTags = v - default: - return nil, fmt.Errorf("invalid option %q for volume plugin %s", k, a.plugin.GetPluginName()) - } - } - // TODO: implement c.options.ProvisionerSelector parsing - if a.options.PVC.Spec.Selector != nil { - return nil, fmt.Errorf("claim.Spec.Selector is not supported for dynamic provisioning on Azure file") - } - - tags, err := azure.ConvertTagsToMap(customTags) - if err != nil { - return nil, err - } - - if shareName == "" { - // File share name has a length limit of 63, it cannot contain two consecutive '-'s, and all letters must be lower case. - name := util.GenerateVolumeName(a.options.ClusterName, a.options.PVName, 63) - shareName = strings.Replace(name, "--", "-", -1) - shareName = strings.ToLower(shareName) - } - - if resourceGroup == "" { - resourceGroup = a.options.PVC.ObjectMeta.Annotations[resourceGroupAnnotation] - } - - fileShareSize := int(requestGiB) - // when use azure file premium, account kind should be specified as FileStorage - accountKind := string(storage.StorageV2) - if strings.HasPrefix(strings.ToLower(sku), "premium") { - accountKind = string(storage.FileStorage) - // when using azure file premium, the shares have a minimum size - if fileShareSize < minimumPremiumShareSize { - fileShareSize = minimumPremiumShareSize - } - } - - accountOptions := &azure.AccountOptions{ - Name: account, - Type: sku, - Kind: accountKind, - ResourceGroup: resourceGroup, - Location: location, - Tags: tags, - } - - shareOptions := &fileclient.ShareOptions{ - Name: shareName, - Protocol: storage.SMB, - RequestGiB: fileShareSize, - } - - account, key, err := a.azureProvider.CreateFileShare(accountOptions, shareOptions) - if err != nil { - return nil, err - } - - // create a secret for storage account and key - secretName, err := a.util.SetAzureCredentials(a.plugin.host, secretNamespace, account, key) - if err != nil { - return nil, err - } - // create PV - pv := &v1.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: a.options.PVName, - Labels: map[string]string{}, - Annotations: map[string]string{ - util.VolumeDynamicallyCreatedByKey: "azure-file-dynamic-provisioner", - resourceGroupAnnotation: resourceGroup, - }, - }, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeReclaimPolicy: a.options.PersistentVolumeReclaimPolicy, - AccessModes: a.options.PVC.Spec.AccessModes, - Capacity: v1.ResourceList{ - v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", fileShareSize)), - }, - PersistentVolumeSource: v1.PersistentVolumeSource{ - AzureFile: &v1.AzureFilePersistentVolumeSource{ - SecretName: secretName, - ShareName: shareName, - SecretNamespace: &secretNamespace, - }, - }, - MountOptions: a.options.MountOptions, - }, - } - return pv, nil -} - -// Return cloud provider -func getAzureCloudProvider(cloudProvider cloudprovider.Interface) (azureCloudProvider, string, error) { - azureCloudProvider, ok := cloudProvider.(*azure.Cloud) - if !ok || azureCloudProvider == nil { - return nil, "", fmt.Errorf("failed to get Azure Cloud Provider. GetCloudProvider returned %v instead", cloudProvider) - } - - return azureCloudProvider, azureCloudProvider.ResourceGroup, nil -} diff --git a/pkg/volume/azure_file/azure_util.go b/pkg/volume/azure_file/azure_util.go deleted file mode 100644 index f44757aaef5..00000000000 --- a/pkg/volume/azure_file/azure_util.go +++ /dev/null @@ -1,162 +0,0 @@ -//go:build !providerless -// +build !providerless - -/* -Copyright 2016 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 azure_file - -import ( - "context" - "fmt" - "strings" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/volume" -) - -const ( - fileMode = "file_mode" - dirMode = "dir_mode" - gid = "gid" - vers = "vers" - actimeo = "actimeo" - mfsymlinks = "mfsymlinks" - defaultFileMode = "0777" - defaultDirMode = "0777" - defaultVers = "3.0" - defaultActimeo = "30" -) - -// Abstract interface to azure file operations. -type azureUtil interface { - GetAzureCredentials(host volume.VolumeHost, nameSpace, secretName string) (string, string, error) - SetAzureCredentials(host volume.VolumeHost, nameSpace, accountName, accountKey string) (string, error) -} - -type azureSvc struct{} - -func (s *azureSvc) GetAzureCredentials(host volume.VolumeHost, nameSpace, secretName string) (string, string, error) { - var accountKey, accountName string - kubeClient := host.GetKubeClient() - if kubeClient == nil { - return "", "", fmt.Errorf("cannot get kube client") - } - - keys, err := kubeClient.CoreV1().Secrets(nameSpace).Get(context.TODO(), secretName, metav1.GetOptions{}) - if err != nil { - return "", "", fmt.Errorf("couldn't get secret %v/%v", nameSpace, secretName) - } - for name, data := range keys.Data { - if name == "azurestorageaccountname" { - accountName = string(data) - } - if name == "azurestorageaccountkey" { - accountKey = string(data) - } - } - if accountName == "" || accountKey == "" { - return "", "", fmt.Errorf("invalid %v/%v, couldn't extract azurestorageaccountname or azurestorageaccountkey", nameSpace, secretName) - } - accountName = strings.TrimSpace(accountName) - return accountName, accountKey, nil -} - -func (s *azureSvc) SetAzureCredentials(host volume.VolumeHost, nameSpace, accountName, accountKey string) (string, error) { - kubeClient := host.GetKubeClient() - if kubeClient == nil { - return "", fmt.Errorf("cannot get kube client") - } - secretName := "azure-storage-account-" + accountName + "-secret" - secret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: nameSpace, - Name: secretName, - }, - Data: map[string][]byte{ - "azurestorageaccountname": []byte(accountName), - "azurestorageaccountkey": []byte(accountKey), - }, - Type: "Opaque", - } - _, err := kubeClient.CoreV1().Secrets(nameSpace).Create(context.TODO(), secret, metav1.CreateOptions{}) - if errors.IsAlreadyExists(err) { - err = nil - } - if err != nil { - return "", fmt.Errorf("couldn't create secret %v", err) - } - return secretName, err -} - -// check whether mountOptions contain file_mode, dir_mode, vers, gid, if not, append default mode -func appendDefaultMountOptions(mountOptions []string, fsGroup *int64) []string { - fileModeFlag := false - dirModeFlag := false - versFlag := false - gidFlag := false - actimeoFlag := false - mfsymlinksFlag := false - - for _, mountOption := range mountOptions { - if strings.HasPrefix(mountOption, fileMode) { - fileModeFlag = true - } - if strings.HasPrefix(mountOption, dirMode) { - dirModeFlag = true - } - if strings.HasPrefix(mountOption, vers) { - versFlag = true - } - if strings.HasPrefix(mountOption, gid) { - gidFlag = true - } - if strings.HasPrefix(mountOption, actimeo) { - actimeoFlag = true - } - if strings.HasPrefix(mountOption, mfsymlinks) { - mfsymlinksFlag = true - } - } - - allMountOptions := mountOptions - if !fileModeFlag { - allMountOptions = append(allMountOptions, fmt.Sprintf("%s=%s", fileMode, defaultFileMode)) - } - - if !dirModeFlag { - allMountOptions = append(allMountOptions, fmt.Sprintf("%s=%s", dirMode, defaultDirMode)) - } - - if !versFlag { - allMountOptions = append(allMountOptions, fmt.Sprintf("%s=%s", vers, defaultVers)) - } - - if !gidFlag && fsGroup != nil { - allMountOptions = append(allMountOptions, fmt.Sprintf("%s=%d", gid, *fsGroup)) - } - - if !actimeoFlag { - allMountOptions = append(allMountOptions, fmt.Sprintf("%s=%s", actimeo, defaultActimeo)) - } - - if !mfsymlinksFlag { - allMountOptions = append(allMountOptions, mfsymlinks) - } - return allMountOptions -} diff --git a/pkg/volume/azure_file/doc.go b/pkg/volume/azure_file/doc.go deleted file mode 100644 index 262683625a5..00000000000 --- a/pkg/volume/azure_file/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2016 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 azure_file contains the internal representation of -// Azure File Service Volume -package azure_file // import "k8s.io/kubernetes/pkg/volume/azure_file" diff --git a/pkg/volume/csi/csi_plugin.go b/pkg/volume/csi/csi_plugin.go index 8cfa3186d53..6f3678f8dc7 100644 --- a/pkg/volume/csi/csi_plugin.go +++ b/pkg/volume/csi/csi_plugin.go @@ -234,7 +234,7 @@ func (p *csiPlugin) Init(host volume.VolumeHost) error { return true }, csitranslationplugins.AzureFileInTreePluginName: func() bool { - return utilfeature.DefaultFeatureGate.Enabled(features.CSIMigrationAzureFile) + return true }, csitranslationplugins.VSphereInTreePluginName: func() bool { return true diff --git a/pkg/volume/csimigration/plugin_manager.go b/pkg/volume/csimigration/plugin_manager.go index c38e8c5073b..029523caea6 100644 --- a/pkg/volume/csimigration/plugin_manager.go +++ b/pkg/volume/csimigration/plugin_manager.go @@ -93,7 +93,7 @@ func (pm PluginManager) IsMigrationEnabledForPlugin(pluginName string) bool { case csilibplugins.GCEPDInTreePluginName: return true case csilibplugins.AzureFileInTreePluginName: - return pm.featureGate.Enabled(features.CSIMigrationAzureFile) + return true case csilibplugins.AzureDiskInTreePluginName: return true case csilibplugins.CinderInTreePluginName: