mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Merge pull request #90350 from ZeroMagic/update_azurefile
Switch to use AzureFile management SDK
This commit is contained in:
commit
5a5ae8d6ff
@ -165,22 +165,25 @@ func (plugin *azureFilePlugin) ExpandVolumeDevice(
|
|||||||
return oldSize, fmt.Errorf("invalid PV spec")
|
return oldSize, fmt.Errorf("invalid PV spec")
|
||||||
}
|
}
|
||||||
shareName := spec.PersistentVolume.Spec.AzureFile.ShareName
|
shareName := spec.PersistentVolume.Spec.AzureFile.ShareName
|
||||||
azure, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
azure, resourceGroup, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oldSize, err
|
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)
|
secretName, secretNamespace, err := getSecretNameAndNamespace(spec, spec.PersistentVolume.Spec.ClaimRef.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oldSize, err
|
return oldSize, err
|
||||||
}
|
}
|
||||||
|
|
||||||
accountName, accountKey, err := (&azureSvc{}).GetAzureCredentials(plugin.host, secretNamespace, secretName)
|
accountName, _, err := (&azureSvc{}).GetAzureCredentials(plugin.host, secretNamespace, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oldSize, err
|
return oldSize, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := azure.ResizeFileShare(accountName, accountKey, shareName, int(volumehelpers.RoundUpToGiB(newSize))); err != nil {
|
if err := azure.ResizeFileShare(resourceGroup, accountName, shareName, int(volumehelpers.RoundUpToGiB(newSize))); err != nil {
|
||||||
return oldSize, err
|
return oldSize, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,8 +36,12 @@ import (
|
|||||||
utilstrings "k8s.io/utils/strings"
|
utilstrings "k8s.io/utils/strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ volume.DeletableVolumePlugin = &azureFilePlugin{}
|
var (
|
||||||
var _ volume.ProvisionableVolumePlugin = &azureFilePlugin{}
|
_ volume.DeletableVolumePlugin = &azureFilePlugin{}
|
||||||
|
_ volume.ProvisionableVolumePlugin = &azureFilePlugin{}
|
||||||
|
|
||||||
|
resourceGroupAnnotation = "kubernetes.io/azure-file-resource-group"
|
||||||
|
)
|
||||||
|
|
||||||
// Abstract interface to file share operations.
|
// Abstract interface to file share operations.
|
||||||
// azure cloud provider should implement it
|
// azure cloud provider should implement it
|
||||||
@ -45,28 +49,31 @@ type azureCloudProvider interface {
|
|||||||
// create a file share
|
// create a file share
|
||||||
CreateFileShare(shareName, accountName, accountType, accountKind, resourceGroup, location string, requestGiB int) (string, string, error)
|
CreateFileShare(shareName, accountName, accountType, accountKind, resourceGroup, location string, requestGiB int) (string, string, error)
|
||||||
// delete a file share
|
// delete a file share
|
||||||
DeleteFileShare(accountName, accountKey, shareName string) error
|
DeleteFileShare(resourceGroup, accountName, shareName string) error
|
||||||
// resize a file share
|
// resize a file share
|
||||||
ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error
|
ResizeFileShare(resourceGroup, accountName, name string, sizeGiB int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type azureFileDeleter struct {
|
type azureFileDeleter struct {
|
||||||
*azureFile
|
*azureFile
|
||||||
accountName, accountKey, shareName string
|
resourceGroup, accountName, shareName string
|
||||||
azureProvider azureCloudProvider
|
azureProvider azureCloudProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *azureFilePlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) {
|
func (plugin *azureFilePlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) {
|
||||||
azure, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
azure, resourceGroup, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(4).Infof("failed to get azure provider")
|
klog.V(4).Infof("failed to get azure provider")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if spec.PersistentVolume != nil && spec.PersistentVolume.ObjectMeta.Annotations[resourceGroupAnnotation] != "" {
|
||||||
|
resourceGroup = spec.PersistentVolume.ObjectMeta.Annotations[resourceGroupAnnotation]
|
||||||
|
}
|
||||||
|
|
||||||
return plugin.newDeleterInternal(spec, &azureSvc{}, azure)
|
return plugin.newDeleterInternal(spec, &azureSvc{}, azure, resourceGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *azureFilePlugin) newDeleterInternal(spec *volume.Spec, util azureUtil, azure azureCloudProvider) (volume.Deleter, error) {
|
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 {
|
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AzureFile == nil {
|
||||||
return nil, fmt.Errorf("invalid PV spec")
|
return nil, fmt.Errorf("invalid PV spec")
|
||||||
}
|
}
|
||||||
@ -76,24 +83,25 @@ func (plugin *azureFilePlugin) newDeleterInternal(spec *volume.Spec, util azureU
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
shareName := spec.PersistentVolume.Spec.AzureFile.ShareName
|
shareName := spec.PersistentVolume.Spec.AzureFile.ShareName
|
||||||
if accountName, accountKey, err := util.GetAzureCredentials(plugin.host, secretNamespace, secretName); err != nil {
|
if accountName, _, err := util.GetAzureCredentials(plugin.host, secretNamespace, secretName); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return &azureFileDeleter{
|
return &azureFileDeleter{
|
||||||
azureFile: &azureFile{
|
azureFile: &azureFile{
|
||||||
volName: spec.Name(),
|
volName: spec.Name(),
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
},
|
},
|
||||||
|
resourceGroup: resourceGroup,
|
||||||
shareName: shareName,
|
shareName: shareName,
|
||||||
accountName: accountName,
|
accountName: accountName,
|
||||||
accountKey: accountKey,
|
|
||||||
azureProvider: azure,
|
azureProvider: azure,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *azureFilePlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
|
func (plugin *azureFilePlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
|
||||||
azure, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
azure, resourceGroup, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(4).Infof("failed to get azure provider")
|
klog.V(4).Infof("failed to get azure provider")
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -101,6 +109,9 @@ func (plugin *azureFilePlugin) NewProvisioner(options volume.VolumeOptions) (vol
|
|||||||
if len(options.PVC.Spec.AccessModes) == 0 {
|
if len(options.PVC.Spec.AccessModes) == 0 {
|
||||||
options.PVC.Spec.AccessModes = plugin.GetAccessModes()
|
options.PVC.Spec.AccessModes = plugin.GetAccessModes()
|
||||||
}
|
}
|
||||||
|
if resourceGroup != "" {
|
||||||
|
options.PVC.ObjectMeta.Annotations[resourceGroupAnnotation] = resourceGroup
|
||||||
|
}
|
||||||
return plugin.newProvisionerInternal(options, azure)
|
return plugin.newProvisionerInternal(options, azure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +135,7 @@ func (f *azureFileDeleter) GetPath() string {
|
|||||||
|
|
||||||
func (f *azureFileDeleter) Delete() error {
|
func (f *azureFileDeleter) Delete() error {
|
||||||
klog.V(4).Infof("deleting volume %s", f.shareName)
|
klog.V(4).Infof("deleting volume %s", f.shareName)
|
||||||
return f.azureProvider.DeleteFileShare(f.accountName, f.accountKey, f.shareName)
|
return f.azureProvider.DeleteFileShare(f.resourceGroup, f.accountName, f.shareName)
|
||||||
}
|
}
|
||||||
|
|
||||||
type azureFileProvisioner struct {
|
type azureFileProvisioner struct {
|
||||||
@ -180,6 +191,10 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
shareName = strings.Replace(name, "--", "-", -1)
|
shareName = strings.Replace(name, "--", "-", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resourceGroup == "" {
|
||||||
|
resourceGroup = a.options.PVC.ObjectMeta.Annotations[resourceGroupAnnotation]
|
||||||
|
}
|
||||||
|
|
||||||
// when use azure file premium, account kind should be specified as FileStorage
|
// when use azure file premium, account kind should be specified as FileStorage
|
||||||
accountKind := string(storage.StorageV2)
|
accountKind := string(storage.StorageV2)
|
||||||
if strings.HasPrefix(strings.ToLower(sku), "premium") {
|
if strings.HasPrefix(strings.ToLower(sku), "premium") {
|
||||||
@ -202,6 +217,7 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
Labels: map[string]string{},
|
Labels: map[string]string{},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
util.VolumeDynamicallyCreatedByKey: "azure-file-dynamic-provisioner",
|
util.VolumeDynamicallyCreatedByKey: "azure-file-dynamic-provisioner",
|
||||||
|
resourceGroupAnnotation: resourceGroup,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
@ -224,11 +240,11 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return cloud provider
|
// Return cloud provider
|
||||||
func getAzureCloudProvider(cloudProvider cloudprovider.Interface) (azureCloudProvider, error) {
|
func getAzureCloudProvider(cloudProvider cloudprovider.Interface) (azureCloudProvider, string, error) {
|
||||||
azureCloudProvider, ok := cloudProvider.(*azure.Cloud)
|
azureCloudProvider, ok := cloudProvider.(*azure.Cloud)
|
||||||
if !ok || azureCloudProvider == nil {
|
if !ok || azureCloudProvider == nil {
|
||||||
return nil, fmt.Errorf("Failed to get Azure Cloud Provider. GetCloudProvider returned %v instead", cloudProvider)
|
return nil, "", fmt.Errorf("Failed to get Azure Cloud Provider. GetCloudProvider returned %v instead", cloudProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
return azureCloudProvider, nil
|
return azureCloudProvider, azureCloudProvider.ResourceGroup, nil
|
||||||
}
|
}
|
||||||
|
@ -549,6 +549,8 @@ func (az *Cloud) configAzureClients(
|
|||||||
loadBalancerClientConfig := azClientConfig.WithRateLimiter(az.Config.LoadBalancerRateLimit)
|
loadBalancerClientConfig := azClientConfig.WithRateLimiter(az.Config.LoadBalancerRateLimit)
|
||||||
securityGroupClientConfig := azClientConfig.WithRateLimiter(az.Config.SecurityGroupRateLimit)
|
securityGroupClientConfig := azClientConfig.WithRateLimiter(az.Config.SecurityGroupRateLimit)
|
||||||
publicIPClientConfig := azClientConfig.WithRateLimiter(az.Config.PublicIPAddressRateLimit)
|
publicIPClientConfig := azClientConfig.WithRateLimiter(az.Config.PublicIPAddressRateLimit)
|
||||||
|
// TODO(ZeroMagic): add azurefileRateLimit
|
||||||
|
fileClientConfig := azClientConfig.WithRateLimiter(nil)
|
||||||
|
|
||||||
// If uses network resources in different AAD Tenant, update Authorizer for VM/VMSS client config
|
// If uses network resources in different AAD Tenant, update Authorizer for VM/VMSS client config
|
||||||
if multiTenantServicePrincipalToken != nil {
|
if multiTenantServicePrincipalToken != nil {
|
||||||
@ -591,8 +593,7 @@ func (az *Cloud) configAzureClients(
|
|||||||
az.LoadBalancerClient = loadbalancerclient.New(loadBalancerClientConfig)
|
az.LoadBalancerClient = loadbalancerclient.New(loadBalancerClientConfig)
|
||||||
az.SecurityGroupsClient = securitygroupclient.New(securityGroupClientConfig)
|
az.SecurityGroupsClient = securitygroupclient.New(securityGroupClientConfig)
|
||||||
az.PublicIPAddressesClient = publicipclient.New(publicIPClientConfig)
|
az.PublicIPAddressesClient = publicipclient.New(publicIPClientConfig)
|
||||||
// fileClient is not based on armclient, but it's still backoff retried.
|
az.FileClient = fileclient.New(fileClientConfig)
|
||||||
az.FileClient = fileclient.NewAzureFileClient(&az.Environment, azClientConfig.Backoff)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (az *Cloud) getAzureClientConfig(servicePrincipalToken *adal.ServicePrincipalToken) *azclients.ClientConfig {
|
func (az *Cloud) getAzureClientConfig(servicePrincipalToken *adal.ServicePrincipalToken) *azclients.ClientConfig {
|
||||||
|
@ -19,14 +19,14 @@ limitations under the License.
|
|||||||
package azure
|
package azure
|
||||||
|
|
||||||
// create file share
|
// create file share
|
||||||
func (az *Cloud) createFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (az *Cloud) createFileShare(resourceGroupName, accountName, name string, sizeGiB int) error {
|
||||||
return az.FileClient.CreateFileShare(accountName, accountKey, name, sizeGiB)
|
return az.FileClient.CreateFileShare(resourceGroupName, accountName, name, sizeGiB)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (az *Cloud) deleteFileShare(accountName, accountKey, name string) error {
|
func (az *Cloud) deleteFileShare(resourceGroupName, accountName, name string) error {
|
||||||
return az.FileClient.DeleteFileShare(accountName, accountKey, name)
|
return az.FileClient.DeleteFileShare(resourceGroupName, accountName, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (az *Cloud) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (az *Cloud) resizeFileShare(resourceGroupName, accountName, name string, sizeGiB int) error {
|
||||||
return az.FileClient.ResizeFileShare(accountName, accountKey, name, sizeGiB)
|
return az.FileClient.ResizeFileShare(resourceGroupName, accountName, name, sizeGiB)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func (az *Cloud) CreateFileShare(shareName, accountName, accountType, accountKin
|
|||||||
return "", "", fmt.Errorf("could not get storage key for storage account %s: %v", accountName, err)
|
return "", "", fmt.Errorf("could not get storage key for storage account %s: %v", accountName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := az.createFileShare(account, key, shareName, requestGiB); err != nil {
|
if err := az.createFileShare(resourceGroup, account, shareName, requestGiB); err != nil {
|
||||||
return "", "", fmt.Errorf("failed to create share %s in account %s: %v", shareName, account, err)
|
return "", "", fmt.Errorf("failed to create share %s in account %s: %v", shareName, account, err)
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("created share %s in account %s", shareName, account)
|
klog.V(4).Infof("created share %s in account %s", shareName, account)
|
||||||
@ -54,8 +54,8 @@ func (az *Cloud) CreateFileShare(shareName, accountName, accountType, accountKin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFileShare deletes a file share using storage account name and key
|
// DeleteFileShare deletes a file share using storage account name and key
|
||||||
func (az *Cloud) DeleteFileShare(accountName, accountKey, shareName string) error {
|
func (az *Cloud) DeleteFileShare(resourceGroup, accountName, shareName string) error {
|
||||||
if err := az.deleteFileShare(accountName, accountKey, shareName); err != nil {
|
if err := az.deleteFileShare(resourceGroup, accountName, shareName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("share %s deleted", shareName)
|
klog.V(4).Infof("share %s deleted", shareName)
|
||||||
@ -63,6 +63,6 @@ func (az *Cloud) DeleteFileShare(accountName, accountKey, shareName string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ResizeFileShare resizes a file share
|
// ResizeFileShare resizes a file share
|
||||||
func (az *Cloud) ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (az *Cloud) ResizeFileShare(resourceGroup, accountName, name string, sizeGiB int) error {
|
||||||
return az.resizeFileShare(accountName, accountKey, name, sizeGiB)
|
return az.resizeFileShare(resourceGroup, accountName, name, sizeGiB)
|
||||||
}
|
}
|
||||||
|
@ -145,3 +145,87 @@ func TestCreateFileShare(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteFileShare(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
cloud := &Cloud{}
|
||||||
|
mockFileClient := mockfileclient.NewMockInterface(ctrl)
|
||||||
|
mockFileClient.EXPECT().DeleteFileShare(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||||
|
cloud.FileClient = mockFileClient
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
rg string
|
||||||
|
acct string
|
||||||
|
name string
|
||||||
|
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
rg: "rg",
|
||||||
|
acct: "bar",
|
||||||
|
name: "foo",
|
||||||
|
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
mockStorageAccountsClient := mockstorageaccountclient.NewMockInterface(ctrl)
|
||||||
|
cloud.StorageAccountClient = mockStorageAccountsClient
|
||||||
|
|
||||||
|
err := cloud.DeleteFileShare(test.rg, test.acct, test.name)
|
||||||
|
if test.expectErr && err == nil {
|
||||||
|
t.Errorf("unexpected non-error")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !test.expectErr && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResizeFileShare(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
cloud := &Cloud{}
|
||||||
|
mockFileClient := mockfileclient.NewMockInterface(ctrl)
|
||||||
|
mockFileClient.EXPECT().ResizeFileShare(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||||
|
cloud.FileClient = mockFileClient
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
rg string
|
||||||
|
acct string
|
||||||
|
name string
|
||||||
|
gb int
|
||||||
|
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
rg: "rg",
|
||||||
|
acct: "bar",
|
||||||
|
name: "foo",
|
||||||
|
gb: 10,
|
||||||
|
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
mockStorageAccountsClient := mockstorageaccountclient.NewMockInterface(ctrl)
|
||||||
|
cloud.StorageAccountClient = mockStorageAccountsClient
|
||||||
|
|
||||||
|
err := cloud.ResizeFileShare(test.rg, test.acct, test.name, test.gb)
|
||||||
|
if test.expectErr && err == nil {
|
||||||
|
t.Errorf("unexpected non-error")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !test.expectErr && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,9 +11,8 @@ go_library(
|
|||||||
importpath = "k8s.io/legacy-cloud-providers/azure/clients/fileclient",
|
importpath = "k8s.io/legacy-cloud-providers/azure/clients/fileclient",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/legacy-cloud-providers/azure/retry:go_default_library",
|
"//staging/src/k8s.io/legacy-cloud-providers/azure/clients:go_default_library",
|
||||||
"//vendor/github.com/Azure/azure-sdk-for-go/storage:go_default_library",
|
"//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage:go_default_library",
|
||||||
"//vendor/github.com/Azure/go-autorest/autorest/azure:go_default_library",
|
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -19,106 +19,73 @@ limitations under the License.
|
|||||||
package fileclient
|
package fileclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
azs "github.com/Azure/azure-sdk-for-go/storage"
|
"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage"
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/legacy-cloud-providers/azure/retry"
|
azclients "k8s.io/legacy-cloud-providers/azure/clients"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Client implements the azure file client interface
|
||||||
useHTTPS = true
|
type Client struct {
|
||||||
)
|
fileSharesClient storage.FileSharesClient
|
||||||
|
|
||||||
var (
|
|
||||||
// refer https://github.com/Azure/azure-sdk-for-go/blob/master/storage/client.go#L88.
|
|
||||||
defaultValidStatusCodes = []int{
|
|
||||||
http.StatusRequestTimeout, // 408
|
|
||||||
http.StatusInternalServerError, // 500
|
|
||||||
http.StatusBadGateway, // 502
|
|
||||||
http.StatusServiceUnavailable, // 503
|
|
||||||
http.StatusGatewayTimeout, // 504
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// AzureFileClient implements the azure file client interface
|
|
||||||
type AzureFileClient struct {
|
|
||||||
env *azure.Environment
|
|
||||||
backoff *retry.Backoff
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAzureFileClient creates a azure file client
|
// New creates a azure file client
|
||||||
func NewAzureFileClient(env *azure.Environment, backoff *retry.Backoff) *AzureFileClient {
|
func New(config *azclients.ClientConfig) *Client {
|
||||||
return &AzureFileClient{
|
client := storage.NewFileSharesClientWithBaseURI(config.ResourceManagerEndpoint, config.SubscriptionID)
|
||||||
env: env,
|
client.Authorizer = config.Authorizer
|
||||||
backoff: backoff,
|
|
||||||
|
return &Client{
|
||||||
|
fileSharesClient: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileShare creates a file share
|
// CreateFileShare creates a file share
|
||||||
func (f *AzureFileClient) CreateFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (c *Client) CreateFileShare(resourceGroupName, accountName, name string, sizeGiB int) error {
|
||||||
fileClient, err := f.getFileSvcClient(accountName, accountKey)
|
quota := int32(sizeGiB)
|
||||||
if err != nil {
|
fileShare := storage.FileShare{
|
||||||
return err
|
Name: &name,
|
||||||
|
FileShareProperties: &storage.FileShareProperties{
|
||||||
|
ShareQuota: "a,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
share := fileClient.GetShareReference(name)
|
_, err := c.fileSharesClient.Create(context.Background(), resourceGroupName, accountName, name, fileShare)
|
||||||
share.Properties.Quota = sizeGiB
|
|
||||||
newlyCreated, err := share.CreateIfNotExists(nil)
|
return err
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create file share, err: %v", err)
|
|
||||||
}
|
|
||||||
if !newlyCreated {
|
|
||||||
klog.V(2).Infof("file share(%s) under account(%s) already exists", name, accountName)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFileShare deletes a file share
|
// DeleteFileShare deletes a file share
|
||||||
func (f *AzureFileClient) DeleteFileShare(accountName, accountKey, name string) error {
|
func (c *Client) DeleteFileShare(resourceGroupName, accountName, name string) error {
|
||||||
fileClient, err := f.getFileSvcClient(accountName, accountKey)
|
_, err := c.fileSharesClient.Delete(context.Background(), resourceGroupName, accountName, name)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
return fileClient.GetShareReference(name).Delete(nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResizeFileShare resizes a file share
|
// ResizeFileShare resizes a file share
|
||||||
func (f *AzureFileClient) ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (c *Client) ResizeFileShare(resourceGroupName, accountName, name string, sizeGiB int) error {
|
||||||
fileClient, err := f.getFileSvcClient(accountName, accountKey)
|
quota := int32(sizeGiB)
|
||||||
|
|
||||||
|
share, err := c.fileSharesClient.Get(context.Background(), resourceGroupName, accountName, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("failed to get file share(%s), : %v", name, err)
|
||||||
}
|
}
|
||||||
share := fileClient.GetShareReference(name)
|
if *share.FileShareProperties.ShareQuota >= quota {
|
||||||
if share.Properties.Quota >= sizeGiB {
|
|
||||||
klog.Warningf("file share size(%dGi) is already greater or equal than requested size(%dGi), accountName: %s, shareName: %s",
|
klog.Warningf("file share size(%dGi) is already greater or equal than requested size(%dGi), accountName: %s, shareName: %s",
|
||||||
share.Properties.Quota, sizeGiB, accountName, name)
|
share.FileShareProperties.ShareQuota, sizeGiB, accountName, name)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
share.Properties.Quota = sizeGiB
|
|
||||||
if err = share.SetProperties(nil); err != nil {
|
share.FileShareProperties.ShareQuota = "a
|
||||||
return fmt.Errorf("failed to set quota on file share %s, err: %v", name, err)
|
_, err = c.fileSharesClient.Update(context.Background(), resourceGroupName, accountName, name, share)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update quota on file share(%s), err: %v", name, err)
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("resize file share completed, accountName: %s, shareName: %s, sizeGiB: %d", accountName, name, sizeGiB)
|
|
||||||
|
klog.V(4).Infof("resize file share completed, resourceGroupName(%s), accountName: %s, shareName: %s, sizeGiB: %d", resourceGroupName, accountName, name, sizeGiB)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *AzureFileClient) getFileSvcClient(accountName, accountKey string) (*azs.FileServiceClient, error) {
|
|
||||||
fileClient, err := azs.NewClient(accountName, accountKey, f.env.StorageEndpointSuffix, azs.DefaultAPIVersion, useHTTPS)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error creating azure client: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.backoff != nil {
|
|
||||||
fileClient.Sender = &azs.DefaultSender{
|
|
||||||
RetryAttempts: f.backoff.Steps,
|
|
||||||
ValidStatusCodes: defaultValidStatusCodes,
|
|
||||||
RetryDuration: f.backoff.Duration,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fc := fileClient.GetFileService()
|
|
||||||
return &fc, nil
|
|
||||||
}
|
|
||||||
|
@ -21,7 +21,7 @@ package fileclient
|
|||||||
// Interface is the client interface for creating file shares, interface for test injection.
|
// Interface is the client interface for creating file shares, interface for test injection.
|
||||||
// mockgen -source=$GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/interface.go -package=mockfileclient Interface > $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/interface.go
|
// mockgen -source=$GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/interface.go -package=mockfileclient Interface > $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/interface.go
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
CreateFileShare(accountName, accountKey, name string, sizeGiB int) error
|
CreateFileShare(resourceGroupName, accountName, name string, sizeGiB int) error
|
||||||
DeleteFileShare(accountName, accountKey, name string) error
|
DeleteFileShare(resourceGroupName, accountName, name string) error
|
||||||
ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error
|
ResizeFileShare(resourceGroupName, accountName, name string, sizeGiB int) error
|
||||||
}
|
}
|
||||||
|
@ -48,43 +48,43 @@ func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileShare mocks base method
|
// CreateFileShare mocks base method
|
||||||
func (m *MockInterface) CreateFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (m *MockInterface) CreateFileShare(resourceGroupName, accountName, name string, sizeGiB int) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CreateFileShare", accountName, accountKey, name, sizeGiB)
|
ret := m.ctrl.Call(m, "CreateFileShare", resourceGroupName, accountName, name, sizeGiB)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileShare indicates an expected call of CreateFileShare
|
// CreateFileShare indicates an expected call of CreateFileShare
|
||||||
func (mr *MockInterfaceMockRecorder) CreateFileShare(accountName, accountKey, name, sizeGiB interface{}) *gomock.Call {
|
func (mr *MockInterfaceMockRecorder) CreateFileShare(resourceGroupName, accountName, name, sizeGiB interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFileShare", reflect.TypeOf((*MockInterface)(nil).CreateFileShare), accountName, accountKey, name, sizeGiB)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFileShare", reflect.TypeOf((*MockInterface)(nil).CreateFileShare), resourceGroupName, accountName, name, sizeGiB)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFileShare mocks base method
|
// DeleteFileShare mocks base method
|
||||||
func (m *MockInterface) DeleteFileShare(accountName, accountKey, name string) error {
|
func (m *MockInterface) DeleteFileShare(resourceGroupName, accountName, name string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "DeleteFileShare", accountName, accountKey, name)
|
ret := m.ctrl.Call(m, "DeleteFileShare", resourceGroupName, accountName, name)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFileShare indicates an expected call of DeleteFileShare
|
// DeleteFileShare indicates an expected call of DeleteFileShare
|
||||||
func (mr *MockInterfaceMockRecorder) DeleteFileShare(accountName, accountKey, name interface{}) *gomock.Call {
|
func (mr *MockInterfaceMockRecorder) DeleteFileShare(resourceGroupName, accountName, name interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFileShare", reflect.TypeOf((*MockInterface)(nil).DeleteFileShare), accountName, accountKey, name)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFileShare", reflect.TypeOf((*MockInterface)(nil).DeleteFileShare), resourceGroupName, accountName, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResizeFileShare mocks base method
|
// ResizeFileShare mocks base method
|
||||||
func (m *MockInterface) ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
func (m *MockInterface) ResizeFileShare(resourceGroupName, accountName, name string, sizeGiB int) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ResizeFileShare", accountName, accountKey, name, sizeGiB)
|
ret := m.ctrl.Call(m, "ResizeFileShare", resourceGroupName, accountName, name, sizeGiB)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResizeFileShare indicates an expected call of ResizeFileShare
|
// ResizeFileShare indicates an expected call of ResizeFileShare
|
||||||
func (mr *MockInterfaceMockRecorder) ResizeFileShare(accountName, accountKey, name, sizeGiB interface{}) *gomock.Call {
|
func (mr *MockInterfaceMockRecorder) ResizeFileShare(resourceGroupName, accountName, name, sizeGiB interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeFileShare", reflect.TypeOf((*MockInterface)(nil).ResizeFileShare), accountName, accountKey, name, sizeGiB)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeFileShare", reflect.TypeOf((*MockInterface)(nil).ResizeFileShare), resourceGroupName, accountName, name, sizeGiB)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user