add tags support for azure file driver

Signed-off-by: ZeroMagic <jiliu8@microsoft.com>
This commit is contained in:
ZeroMagic
2020-07-06 06:57:53 +00:00
parent bc60bdaded
commit 7e7cf6a314
16 changed files with 243 additions and 140 deletions

View File

@@ -35,11 +35,6 @@ import (
"k8s.io/legacy-cloud-providers/azure"
)
const (
TagsDelimiter = ","
TagKeyValueDelimiter = "="
)
type azureDiskProvisioner struct {
plugin *azureDataDiskPlugin
options volume.VolumeOptions
@@ -269,7 +264,7 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
diskURI := ""
labels := map[string]string{}
if kind == v1.AzureManagedDisk {
tags, err := ConvertTagsToMap(customTags)
tags, err := azure.ConvertTagsToMap(customTags)
if err != nil {
return nil, err
}
@@ -399,28 +394,3 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
return pv, nil
}
// ConvertTagsToMap convert the tags from string to map
// the valid tags fomat is "key1=value1,key2=value2", which could be converted to
// {"key1": "value1", "key2": "value2"}
func ConvertTagsToMap(tags string) (map[string]string, error) {
m := make(map[string]string)
if tags == "" {
return m, nil
}
s := strings.Split(tags, TagsDelimiter)
for _, tag := range s {
kv := strings.Split(tag, TagKeyValueDelimiter)
if len(kv) != 2 {
return nil, fmt.Errorf("Tags '%s' are invalid, the format should like: 'key1=value1,key2=value2'", tags)
}
key := strings.TrimSpace(kv[0])
if key == "" {
return nil, fmt.Errorf("Tags '%s' are invalid, the format should like: 'key1=value1,key2=value2'", tags)
}
value := strings.TrimSpace(kv[1])
m[key] = value
}
return m, nil
}

View File

@@ -20,7 +20,6 @@ package azure_dd
import (
"fmt"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
@@ -97,69 +96,3 @@ func TestParseZoned(t *testing.T) {
}
}
}
func TestConvertTagsToMap(t *testing.T) {
testCases := []struct {
desc string
tags string
expectedOutput map[string]string
expectedError bool
}{
{
desc: "should return empty map when tag is empty",
tags: "",
expectedOutput: map[string]string{},
expectedError: false,
},
{
desc: "sing valid tag should be converted",
tags: "key=value",
expectedOutput: map[string]string{
"key": "value",
},
expectedError: false,
},
{
desc: "multiple valid tags should be converted",
tags: "key1=value1,key2=value2",
expectedOutput: map[string]string{
"key1": "value1",
"key2": "value2",
},
expectedError: false,
},
{
desc: "whitespaces should be trimmed",
tags: "key1=value1, key2=value2",
expectedOutput: map[string]string{
"key1": "value1",
"key2": "value2",
},
expectedError: false,
},
{
desc: "should return error for invalid format",
tags: "foo,bar",
expectedOutput: nil,
expectedError: true,
},
{
desc: "should return error for when key is missed",
tags: "key1=value1,=bar",
expectedOutput: nil,
expectedError: true,
},
}
for i, c := range testCases {
m, err := ConvertTagsToMap(c.tags)
if c.expectedError {
assert.NotNil(t, err, "TestCase[%d]: %s", i, c.desc)
} else {
assert.Nil(t, err, "TestCase[%d]: %s", i, c.desc)
if !reflect.DeepEqual(m, c.expectedOutput) {
t.Errorf("got: %v, expected: %v, desc: %v", m, c.expectedOutput, c.desc)
}
}
}
}

View File

@@ -22,6 +22,7 @@ go_library(
"//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//staging/src/k8s.io/legacy-cloud-providers/azure:go_default_library",
"//staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient:go_default_library",
"//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
"//vendor/k8s.io/utils/mount:go_default_library",

View File

@@ -33,6 +33,7 @@ import (
"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"
)
@@ -47,7 +48,7 @@ var (
// azure cloud provider should implement it
type azureCloudProvider interface {
// create a file share
CreateFileShare(shareName, accountName, accountType, accountKind, resourceGroup, location string, protocol storage.EnabledProtocols, requestGiB int) (string, string, error)
CreateFileShare(account *azure.AccountOptions, fileShare *fileclient.ShareOptions) (string, string, error)
// delete a file share
DeleteFileShare(resourceGroup, accountName, shareName string) error
// resize a file share
@@ -155,7 +156,7 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
return nil, fmt.Errorf("%s does not support block volume provisioning", a.plugin.GetPluginName())
}
var sku, resourceGroup, location, account, shareName string
var sku, resourceGroup, location, account, shareName, customTags string
capacity := a.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
requestGiB, err := volumehelpers.RoundUpToGiBInt(capacity)
@@ -180,6 +181,8 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
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())
}
@@ -189,6 +192,11 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
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, and it cannot contain two consecutive '-'s.
name := util.GenerateVolumeName(a.options.ClusterName, a.options.PVName, 63)
@@ -204,7 +212,23 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
if strings.HasPrefix(strings.ToLower(sku), "premium") {
accountKind = string(storage.FileStorage)
}
account, key, err := a.azureProvider.CreateFileShare(shareName, account, sku, accountKind, resourceGroup, location, storage.SMB, requestGiB)
accountOptions := &azure.AccountOptions{
Name: account,
Type: sku,
Kind: accountKind,
ResourceGroup: resourceGroup,
Location: location,
Tags: tags,
}
shareOptions := &fileclient.ShareOptions{
Name: shareName,
Protocol: storage.SMB,
RequestGiB: requestGiB,
}
account, key, err := a.azureProvider.CreateFileShare(accountOptions, shareOptions)
if err != nil {
return nil, err
}