Skip to content

Commit fce8cb0

Browse files
authored
Merge pull request #648 from andyzhangx/containerNamePrefix
feat: add containerNamePrefix in storage class
2 parents cc21fb1 + c69edcd commit fce8cb0

File tree

6 files changed

+135
-9
lines changed

6 files changed

+135
-9
lines changed

docs/driver-parameters.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ location | Azure location | `eastus`, `westus`, etc. | No | if empty, driver wil
1313
resourceGroup | Azure resource group name | existing resource group name | No | if empty, driver will use the same resource group name as current k8s cluster
1414
storageAccount | specify Azure storage account name| STORAGE_ACCOUNT_NAME | - No for blobfuse mount </br> - Yes for NFSv3 mount | - For blobfuse mount: if empty, driver will find a suitable storage account that matches `skuName` in the same resource group; if a storage account name is provided, storage account must exist. </br> - For NFSv3 mount, storage account name must be provided
1515
protocol | specify blobfuse mount or NFSv3 mount | `fuse`, `nfs` | No | `fuse`
16-
containerName | specify the existing container name | existing container name | No | if empty, driver will create a new container name, starting with `pvc-fuse` for blobfuse or `pvc-nfs` for NFSv3
16+
containerName | specify the existing container(directory) name | existing container name | No | if empty, driver will create a new container name, starting with `pvc-fuse` for blobfuse or `pvc-nfs` for NFSv3
17+
containerNamePrefix | specify Azure storage directory prefix created by driver | can only contain lowercase letters, numbers, hyphens, and length should be less than 21 | No |
1718
server | specify Azure storage account server address | existing server address, e.g. `accountname.privatelink.blob.core.windows.net` | No | if empty, driver will use default `accountname.blob.core.windows.net` or other sovereign cloud account address
1819
allowBlobPublicAccess | Allow or disallow public access to all blobs or containers for storage account created by driver | `true`,`false` | No | `false`
1920
storageEndpointSuffix | specify Azure storage endpoint suffix | `core.windows.net` | No | if empty, driver will use default storage endpoint suffix according to cloud environment, e.g. `core.windows.net`

pkg/blob/blob.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ const (
6464
secretNameField = "secretname"
6565
secretNamespaceField = "secretnamespace"
6666
containerNameField = "containername"
67+
containerNamePrefixField = "containernameprefix"
6768
storeAccountKeyField = "storeaccountkey"
6869
isHnsEnabledField = "ishnsenabled"
6970
getAccountKeyFromSecretField = "getaccountkeyfromsecret"
@@ -278,11 +279,9 @@ func getValidContainerName(volumeName, protocol string) string {
278279
// now we set as 63 for maximum container name length
279280
// todo: get cluster name
280281
containerName = k8sutil.GenerateVolumeName(fmt.Sprintf("pvc-%s", protocol), uuid.NewUUID().String(), 63)
281-
klog.Warningf("the requested volume name (%q) is invalid, so it is regenerated as (%q)", volumeName, containerName)
282+
klog.Warningf("requested volume name (%s) is invalid, regenerated as (%q)", volumeName, containerName)
282283
}
283-
containerName = strings.Replace(containerName, "--", "-", -1)
284-
285-
return containerName
284+
return strings.Replace(containerName, "--", "-", -1)
286285
}
287286

288287
func checkContainerNameBeginAndEnd(containerName string) bool {
@@ -563,6 +562,26 @@ func isSupportedProtocol(protocol string) bool {
563562
return false
564563
}
565564

565+
// container names can contain only lowercase letters, numbers, and hyphens,
566+
// and must begin and end with a letter or a number
567+
func isSupportedContainerNamePrefix(prefix string) bool {
568+
if prefix == "" {
569+
return true
570+
}
571+
if len(prefix) > 20 {
572+
return false
573+
}
574+
if prefix[0] == '-' {
575+
return false
576+
}
577+
for _, v := range prefix {
578+
if v != '-' && (v < '0' || v > '9') && (v < 'a' || v > 'z') {
579+
return false
580+
}
581+
}
582+
return true
583+
}
584+
566585
// get storage account from secrets map
567586
func getStorageAccount(secrets map[string]string) (string, string, error) {
568587
if secrets == nil {

pkg/blob/blob_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,3 +816,50 @@ func TestAppendDefaultMountOptions(t *testing.T) {
816816
}
817817
}
818818
}
819+
820+
func TestIsSupportedContainerNamePrefix(t *testing.T) {
821+
tests := []struct {
822+
prefix string
823+
expectedResult bool
824+
}{
825+
{
826+
prefix: "",
827+
expectedResult: true,
828+
},
829+
{
830+
prefix: "ext3",
831+
expectedResult: true,
832+
},
833+
{
834+
prefix: "ext-2",
835+
expectedResult: true,
836+
},
837+
{
838+
prefix: "-xfs",
839+
expectedResult: false,
840+
},
841+
{
842+
prefix: "Absdf",
843+
expectedResult: false,
844+
},
845+
{
846+
prefix: "tooooooooooooooooooooooooolong",
847+
expectedResult: false,
848+
},
849+
{
850+
prefix: "+invalid",
851+
expectedResult: false,
852+
},
853+
{
854+
prefix: " invalidspace",
855+
expectedResult: false,
856+
},
857+
}
858+
859+
for _, test := range tests {
860+
result := isSupportedContainerNamePrefix(test.prefix)
861+
if result != test.expectedResult {
862+
t.Errorf("isSupportedContainerNamePrefix(%s) returned with %v, not equal to %v", test.prefix, result, test.expectedResult)
863+
}
864+
}
865+
}

pkg/blob/controllerserver.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (d *Driver) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest)
6767
if parameters == nil {
6868
parameters = make(map[string]string)
6969
}
70-
var storageAccountType, subsID, resourceGroup, location, account, containerName, protocol, customTags, secretName, secretNamespace, pvcNamespace string
70+
var storageAccountType, subsID, resourceGroup, location, account, containerName, containerNamePrefix, protocol, customTags, secretName, secretNamespace, pvcNamespace string
7171
var isHnsEnabled *bool
7272
var vnetResourceGroup, vnetName, subnetName string
7373
// set allowBlobPublicAccess as false by default
@@ -94,6 +94,8 @@ func (d *Driver) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest)
9494
resourceGroup = v
9595
case containerNameField:
9696
containerName = v
97+
case containerNamePrefixField:
98+
containerNamePrefix = v
9799
case protocolField:
98100
protocol = v
99101
case tagsField:
@@ -170,6 +172,13 @@ func (d *Driver) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest)
170172
return nil, status.Errorf(codes.InvalidArgument, "protocol(%s) is not supported, supported protocol list: %v", protocol, supportedProtocolList)
171173
}
172174

175+
if containerName != "" && containerNamePrefix != "" {
176+
return nil, status.Errorf(codes.InvalidArgument, "containerName(%s) and containerNamePrefix(%s) could not be specified together", containerName, containerNamePrefix)
177+
}
178+
if !isSupportedContainerNamePrefix(containerNamePrefix) {
179+
return nil, status.Errorf(codes.InvalidArgument, "containerNamePrefix(%s) can only contain lowercase letters, numbers, hyphens, and length should be less than 21", containerNamePrefix)
180+
}
181+
173182
enableHTTPSTrafficOnly := true
174183
accountKind := string(storage.KindStorageV2)
175184
var (
@@ -268,7 +277,11 @@ func (d *Driver) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest)
268277

269278
validContainerName := containerName
270279
if validContainerName == "" {
271-
validContainerName = getValidContainerName(volName, protocol)
280+
validContainerName = volName
281+
if containerNamePrefix != "" {
282+
validContainerName = containerNamePrefix + "-" + volName
283+
}
284+
validContainerName = getValidContainerName(validContainerName, protocol)
272285
parameters[containerNameField] = validContainerName
273286
}
274287

pkg/blob/controllerserver_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,51 @@ func TestCreateVolume(t *testing.T) {
171171
}
172172
},
173173
},
174+
{
175+
name: "containerName and containerNamePrefix could not be specified together",
176+
testFunc: func(t *testing.T) {
177+
d := NewFakeDriver()
178+
d.cloud = &azure.Cloud{}
179+
mp := make(map[string]string)
180+
mp[containerNameField] = "containerName"
181+
mp[containerNamePrefixField] = "containerNamePrefix"
182+
req := &csi.CreateVolumeRequest{
183+
Name: "unit-test",
184+
VolumeCapabilities: stdVolumeCapabilities,
185+
Parameters: mp,
186+
}
187+
d.Cap = []*csi.ControllerServiceCapability{
188+
controllerServiceCapability,
189+
}
190+
_, err := d.CreateVolume(context.Background(), req)
191+
expectedErr := status.Errorf(codes.InvalidArgument, "containerName(containerName) and containerNamePrefix(containerNamePrefix) could not be specified together")
192+
if !reflect.DeepEqual(err, expectedErr) {
193+
t.Errorf("actualErr: (%v), expectedErr: (%v)", err, expectedErr)
194+
}
195+
},
196+
},
197+
{
198+
name: "invalid containerNamePrefix",
199+
testFunc: func(t *testing.T) {
200+
d := NewFakeDriver()
201+
d.cloud = &azure.Cloud{}
202+
mp := make(map[string]string)
203+
mp[containerNamePrefixField] = "UpperCase"
204+
req := &csi.CreateVolumeRequest{
205+
Name: "unit-test",
206+
VolumeCapabilities: stdVolumeCapabilities,
207+
Parameters: mp,
208+
}
209+
d.Cap = []*csi.ControllerServiceCapability{
210+
controllerServiceCapability,
211+
}
212+
_, err := d.CreateVolume(context.Background(), req)
213+
expectedErr := status.Errorf(codes.InvalidArgument, "containerNamePrefix(UpperCase) can only contain lowercase letters, numbers, hyphens, and length should be less than 21")
214+
if !reflect.DeepEqual(err, expectedErr) {
215+
t.Errorf("actualErr: (%v), expectedErr: (%v)", err, expectedErr)
216+
}
217+
},
218+
},
174219
{
175220
name: "tags error",
176221
testFunc: func(t *testing.T) {

test/e2e/dynamic_provisioning_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@ var _ = ginkgo.Describe("[blob-csi-e2e] Dynamic Provisioning", func() {
115115
CSIDriver: testDriver,
116116
Pods: pods,
117117
StorageClassParameters: map[string]string{
118-
"skuName": "Standard_LRS",
119-
"secretNamespace": "default",
118+
"skuName": "Standard_LRS",
119+
"secretNamespace": "default",
120+
"containerNamePrefix": "nameprefix",
120121
},
121122
}
122123
test.Run(cs, ns)

0 commit comments

Comments
 (0)