Skip to content

Commit 8e3b4f8

Browse files
committed
feat: support data plane api using Oauth on smb file share operations
1 parent e26f052 commit 8e3b4f8

File tree

10 files changed

+261
-132
lines changed

10 files changed

+261
-132
lines changed

pkg/azurefile/azure.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func getCloudProvider(ctx context.Context, kubeconfig, nodeID, secretName, secre
181181
klog.V(2).Infof("starting node server on node(%s)", nodeID)
182182
}
183183

184-
repo, err = storage.NewRepository(*config, env, az.ComputeClientFactory, az.NetworkClientFactory)
184+
repo, err = storage.NewRepository(*config, env, az.AuthProvider, az.ComputeClientFactory, az.NetworkClientFactory)
185185
if err != nil {
186186
return nil, nil, fmt.Errorf("failed to create storage repository: %v", err)
187187
}

pkg/azurefile/azure_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ var _ = ginkgo.Describe("AzureFile", func() {
318318
var err error
319319
d.cloud, err = storage.NewRepository(config, &azclient.Environment{
320320
StorageEndpointSuffix: "fake-endpoint",
321-
}, mockClientFactory, mockClientFactory)
321+
}, nil, mockClientFactory, mockClientFactory)
322322
gomega.Expect(err).NotTo(gomega.HaveOccurred(), "Unexpected error:", err)
323323
})
324324
ginkgo.AfterEach(func() {

pkg/azurefile/azurefile.go

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ const (
166166
accountLimitExceedManagementAPI = "TotalSharesProvisionedCapacityExceedsAccountLimit"
167167
accountLimitExceedDataPlaneAPI = "specified share does not exist"
168168

169-
fileShareNotFound = "ErrorCode=ShareNotFound"
169+
fileShareNotFound = "ShareNotFound"
170170
statusCodeNotFound = "StatusCode=404"
171171
httpCodeNotFound = "HTTPStatusCode: 404"
172172

@@ -196,6 +196,8 @@ const (
196196
FSGroupChangeNone = "None"
197197
// define tag value delimiter and default is comma
198198
tagValueDelimiterField = "tagvaluedelimiter"
199+
// for data plane API
200+
oauth = "oauth"
199201
)
200202

201203
var (
@@ -260,7 +262,7 @@ type Driver struct {
260262
accountCacheMap azcache.Resource
261263
// a map storing all secret names created by this driver <secretCacheKey, "">
262264
secretCacheMap azcache.Resource
263-
// a map storing all volumes using data plane API <volumeID, "">
265+
// a map storing all volumes using data plane API <volumeID, value>
264266
dataPlaneAPIVolMap sync.Map
265267
// a timed cache storing all storage accounts that are using data plane API temporarily
266268
dataPlaneAPIAccountCache azcache.Resource
@@ -473,25 +475,27 @@ func (d *Driver) Run(ctx context.Context) error {
473475
}
474476

475477
// getFileShareQuota return (-1, nil) means file share does not exist
476-
func (d *Driver) getFileShareQuota(ctx context.Context, accountOptions *storage.AccountOptions, fileShareName string, secrets map[string]string) (int, error) {
478+
func (d *Driver) getFileShareQuota(ctx context.Context, accountOptions *storage.AccountOptions, fileShareName string, secrets map[string]string, useDataPlaneAPI string) (int, error) {
477479
var fileClient azureFileClient
478480
var err error
479481
if len(secrets) > 0 {
480-
accountName, accountKey, err := getStorageAccount(secrets)
481-
if err != nil {
482-
return -1, err
482+
accountName, accountKey, rerr := getStorageAccount(secrets)
483+
if rerr != nil {
484+
return -1, rerr
483485
}
484486
storageEndPointSuffix := d.getStorageEndPointSuffix()
485487
if accountOptions != nil && accountOptions.StorageEndpointSuffix != "" {
486488
storageEndPointSuffix = accountOptions.StorageEndpointSuffix
487489
}
488-
if fileClient, err = newAzureFileClient(accountName, accountKey, storageEndPointSuffix); err != nil {
489-
return -1, err
490-
}
490+
fileClient, err = newAzureFileClient(accountName, accountKey, storageEndPointSuffix)
491+
} else if d.cloud != nil && d.cloud.AuthProvider != nil && strings.EqualFold(useDataPlaneAPI, oauth) {
492+
fileClient, err = newAzureFileClientWithOAuth(d.cloud.AuthProvider.GetAzIdentity(), accountOptions.Name, d.getStorageEndPointSuffix())
491493
} else {
492-
if fileClient, err = newAzureFileMgmtClient(d.cloud, accountOptions); err != nil {
493-
return -1, err
494-
}
494+
fileClient, err = newAzureFileMgmtClient(d.cloud, accountOptions)
495+
}
496+
497+
if err != nil {
498+
return -1, err
495499
}
496500
quota, err := fileClient.GetFileShareQuota(ctx, fileShareName)
497501
if err != nil {
@@ -709,7 +713,7 @@ func getDirectoryClient(accountName, accountKey, storageEndpointSuffix, fileShar
709713
if u == nil {
710714
return nil, fmt.Errorf("parse fileURLTemplate error: url is nil")
711715
}
712-
serviceURL := fmt.Sprintf("https://%s.file.%s/", accountName, storageEndpointSuffix)
716+
serviceURL := getFileServiceURL(accountName, storageEndpointSuffix)
713717

714718
serviceClient, err := service.NewClientWithSharedKeyCredential(serviceURL, credential, nil)
715719
if err != nil {
@@ -942,7 +946,7 @@ func isSupportedFSGroupChangePolicy(policy string) bool {
942946
}
943947

944948
// CreateFileShare creates a file share
945-
func (d *Driver) CreateFileShare(ctx context.Context, accountOptions *storage.AccountOptions, shareOptions *ShareOptions, secrets map[string]string) error {
949+
func (d *Driver) CreateFileShare(ctx context.Context, accountOptions *storage.AccountOptions, shareOptions *ShareOptions, secrets map[string]string, useDataPlaneAPI string) error {
946950
return wait.ExponentialBackoff(getBackOff(d.cloud.Config), func() (bool, error) {
947951
var err error
948952
var fileClient azureFileClient
@@ -959,12 +963,20 @@ func (d *Driver) CreateFileShare(ctx context.Context, accountOptions *storage.Ac
959963
if fileClient, err = newAzureFileClient(accountName, accountKey, storageEndPointSuffix); err != nil {
960964
return true, err
961965
}
966+
} else if d.cloud != nil && d.cloud.AuthProvider != nil && strings.EqualFold(useDataPlaneAPI, oauth) {
967+
fileClient, err = newAzureFileClientWithOAuth(d.cloud.AuthProvider.GetAzIdentity(), accountOptions.Name, d.getStorageEndPointSuffix())
962968
} else {
963-
if fileClient, err = newAzureFileMgmtClient(d.cloud, accountOptions); err != nil {
964-
return true, err
965-
}
969+
fileClient, err = newAzureFileMgmtClient(d.cloud, accountOptions)
966970
}
971+
if err != nil {
972+
return true, err
973+
}
974+
967975
if err = fileClient.CreateFileShare(ctx, shareOptions); err != nil {
976+
if strings.Contains(err.Error(), "ShareAlreadyExists") {
977+
klog.Warningf("CreateFileShare(%s) on account(%s) failed with error(%v), return as success", shareOptions.Name, accountOptions.Name, err)
978+
return true, nil
979+
}
968980
if isRetriableError(err) {
969981
klog.Warningf("CreateFileShare(%s) on account(%s) failed with error(%v), waiting for retrying", shareOptions.Name, accountOptions.Name, err)
970982
sleepIfThrottled(err, fileOpThrottlingSleepSec)
@@ -977,7 +989,7 @@ func (d *Driver) CreateFileShare(ctx context.Context, accountOptions *storage.Ac
977989
}
978990

979991
// DeleteFileShare deletes a file share using storage account name and key
980-
func (d *Driver) DeleteFileShare(ctx context.Context, subsID, resourceGroup, accountName, shareName string, secrets map[string]string) error {
992+
func (d *Driver) DeleteFileShare(ctx context.Context, subsID, resourceGroup, accountName, shareName string, secrets map[string]string, useDataPlaneAPI string) error {
981993
return wait.ExponentialBackoff(getBackOff(d.cloud.Config), func() (bool, error) {
982994
var err error
983995
if len(secrets) > 0 {
@@ -990,6 +1002,12 @@ func (d *Driver) DeleteFileShare(ctx context.Context, subsID, resourceGroup, acc
9901002
return true, rerr
9911003
}
9921004
err = fileClient.DeleteFileShare(ctx, shareName)
1005+
} else if d.cloud != nil && d.cloud.AuthProvider != nil && strings.EqualFold(useDataPlaneAPI, oauth) {
1006+
fileClient, rerr := newAzureFileClientWithOAuth(d.cloud.AuthProvider.GetAzIdentity(), accountName, d.getStorageEndPointSuffix())
1007+
if rerr != nil {
1008+
return true, rerr
1009+
}
1010+
err = fileClient.DeleteFileShare(ctx, shareName)
9931011
} else {
9941012
fileClient, errGetClient := d.getFileShareClientForSub(subsID)
9951013
if errGetClient != nil {
@@ -1022,7 +1040,7 @@ func (d *Driver) DeleteFileShare(ctx context.Context, subsID, resourceGroup, acc
10221040
}
10231041

10241042
// ResizeFileShare resizes a file share
1025-
func (d *Driver) ResizeFileShare(ctx context.Context, subsID, resourceGroup, accountName, shareName string, sizeGiB int, secrets map[string]string) error {
1043+
func (d *Driver) ResizeFileShare(ctx context.Context, subsID, resourceGroup, accountName, shareName string, sizeGiB int, secrets map[string]string, useDataPlaneAPI string) error {
10261044
return wait.ExponentialBackoff(getBackOff(d.cloud.Config), func() (bool, error) {
10271045
var err error
10281046
if len(secrets) > 0 {
@@ -1035,14 +1053,20 @@ func (d *Driver) ResizeFileShare(ctx context.Context, subsID, resourceGroup, acc
10351053
return true, rerr
10361054
}
10371055
err = fileClient.ResizeFileShare(ctx, shareName, sizeGiB)
1056+
} else if d.cloud != nil && d.cloud.AuthProvider != nil && strings.EqualFold(useDataPlaneAPI, oauth) {
1057+
fileClient, rerr := newAzureFileClientWithOAuth(d.cloud.AuthProvider.GetAzIdentity(), accountName, d.getStorageEndPointSuffix())
1058+
if rerr != nil {
1059+
return true, rerr
1060+
}
1061+
err = fileClient.ResizeFileShare(ctx, shareName, sizeGiB)
10381062
} else {
1039-
fileClient, err := d.getFileShareClientForSub(subsID)
1040-
if err != nil {
1041-
return true, err
1063+
fileClient, rerr := d.getFileShareClientForSub(subsID)
1064+
if rerr != nil {
1065+
return true, rerr
10421066
}
1043-
fileShare, err := fileClient.Get(ctx, resourceGroup, accountName, shareName, nil)
1044-
if err != nil {
1045-
return true, err
1067+
fileShare, rerr := fileClient.Get(ctx, resourceGroup, accountName, shareName, nil)
1068+
if rerr != nil {
1069+
return true, rerr
10461070
}
10471071
if ptr.Deref(fileShare.FileShareProperties.ShareQuota, 0) >= int32(sizeGiB) {
10481072
klog.Warningf("file share size(%dGi) is already greater or equal than requested size(%dGi), accountName: %s, shareName: %s",
@@ -1051,7 +1075,6 @@ func (d *Driver) ResizeFileShare(ctx context.Context, subsID, resourceGroup, acc
10511075
}
10521076
fileShare.FileShareProperties.ShareQuota = to.Ptr(int32(sizeGiB))
10531077
_, err = fileClient.Update(ctx, resourceGroup, accountName, shareName, *fileShare)
1054-
return true, err
10551078
}
10561079
if isRetriableError(err) {
10571080
klog.Warningf("ResizeFileShare(%s) on account(%s) with new size(%d) failed with error(%v), waiting for retrying", shareName, accountName, sizeGiB, err)
@@ -1232,20 +1255,21 @@ func (d *Driver) getSubnetResourceID(vnetResourceGroup, vnetName, subnetName str
12321255
return fmt.Sprintf(subnetTemplate, subsID, vnetResourceGroup, vnetName, subnetName)
12331256
}
12341257

1235-
func (d *Driver) useDataPlaneAPI(ctx context.Context, volumeID, accountName string) bool {
1236-
_, useDataPlaneAPI := d.dataPlaneAPIVolMap.Load(volumeID)
1258+
func (d *Driver) useDataPlaneAPI(ctx context.Context, volumeID, accountName string) string {
1259+
v, useDataPlaneAPI := d.dataPlaneAPIVolMap.Load(volumeID)
12371260
if useDataPlaneAPI {
1238-
return true
1261+
return v.(string)
12391262
}
12401263

12411264
cache, err := d.dataPlaneAPIAccountCache.Get(ctx, accountName, azcache.CacheReadTypeDefault)
12421265
if err != nil {
12431266
klog.Errorf("get(%s) from dataPlaneAPIAccountCache failed with error: %v", accountName, err)
1267+
return ""
12441268
}
12451269
if cache != nil {
1246-
return true
1270+
return cache.(string)
12471271
}
1248-
return false
1272+
return ""
12491273
}
12501274

12511275
func (d *Driver) SetAzureCredentials(ctx context.Context, accountName, accountKey, secretName, secretNamespace string) (string, error) {

pkg/azurefile/azurefile_dataplane_client.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"net/http"
2323

24+
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
2425
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
2526
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service"
2627
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share"
@@ -47,18 +48,15 @@ type azureFileDataplaneClient struct {
4748
}
4849

4950
func newAzureFileClient(accountName, accountKey, storageEndpointSuffix string) (azureFileClient, error) {
50-
if storageEndpointSuffix == "" {
51-
storageEndpointSuffix = defaultStorageEndPointSuffix
52-
}
5351
keyCred, err := service.NewSharedKeyCredential(accountName, accountKey)
5452
if err != nil {
5553
return nil, fmt.Errorf("error creating azure client: %v", err)
5654
}
57-
storageEndpoint := fmt.Sprintf("https://%s.file."+storageEndpointSuffix, accountName)
55+
serviceURL := getFileServiceURL(accountName, storageEndpointSuffix)
5856
clientOps := utils.GetDefaultAzCoreClientOption()
5957
clientOps.Retry.StatusCodes = defaultValidStatusCodes
6058

61-
fileClient, err := service.NewClientWithSharedKeyCredential(storageEndpoint, keyCred, &service.ClientOptions{
59+
fileClient, err := service.NewClientWithSharedKeyCredential(serviceURL, keyCred, &service.ClientOptions{
6260
ClientOptions: clientOps,
6361
})
6462
if err != nil {
@@ -71,6 +69,21 @@ func newAzureFileClient(accountName, accountKey, storageEndpointSuffix string) (
7169
}, nil
7270
}
7371

72+
func newAzureFileClientWithOAuth(cred azcore.TokenCredential, accountName, storageEndpointSuffix string) (azureFileClient, error) {
73+
serviceURL := getFileServiceURL(accountName, storageEndpointSuffix)
74+
fileClient, err := service.NewClient(serviceURL, cred, &service.ClientOptions{
75+
ClientOptions: utils.GetDefaultAzCoreClientOption(),
76+
})
77+
if err != nil {
78+
return nil, fmt.Errorf("error creating azure client with oauth: %v", err)
79+
}
80+
klog.V(2).Infof("created azure file client with oauth, accountName: %s", accountName)
81+
return &azureFileDataplaneClient{
82+
accountName: accountName,
83+
Client: fileClient,
84+
}, nil
85+
}
86+
7487
func (f *azureFileDataplaneClient) CreateFileShare(ctx context.Context, shareOptions *ShareOptions) error {
7588
if shareOptions == nil {
7689
return fmt.Errorf("shareOptions of account(%s) is nil", f.accountName)

pkg/azurefile/azurefile_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ func TestGetFileShareQuota(t *testing.T) {
10151015
ResourceGroup: resourceGroupName,
10161016
Name: accountName,
10171017
SubscriptionID: "subsID",
1018-
}, fileShareName, test.secrets)
1018+
}, fileShareName, test.secrets, "")
10191019
if !reflect.DeepEqual(err, test.expectedError) {
10201020
t.Errorf("test name: %s, Unexpected error: %v, expected error: %v", test.desc, err, test.expectedError)
10211021
}

0 commit comments

Comments
 (0)