Skip to content

Commit 2768716

Browse files
authored
Merge pull request kubernetes#92356 from andyzhangx/azuredisk-tags
add tags support for azure disk driver
2 parents 0c57162 + 9973b1c commit 2768716

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

pkg/volume/azure_dd/azure_provision.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ import (
3535
"k8s.io/legacy-cloud-providers/azure"
3636
)
3737

38+
const (
39+
TagsDelimiter = ","
40+
TagKeyValueDelimiter = "="
41+
)
42+
3843
type azureDiskProvisioner struct {
3944
plugin *azureDataDiskPlugin
4045
options volume.VolumeOptions
@@ -118,6 +123,7 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
118123
diskIopsReadWrite string
119124
diskMbpsReadWrite string
120125
diskEncryptionSetID string
126+
customTags string
121127

122128
maxShares int
123129
)
@@ -164,6 +170,8 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
164170
diskMbpsReadWrite = v
165171
case "diskencryptionsetid":
166172
diskEncryptionSetID = v
173+
case "tags":
174+
customTags = v
167175
case azure.WriteAcceleratorEnabled:
168176
writeAcceleratorEnabled = v
169177
case "maxshares":
@@ -261,9 +269,14 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
261269
diskURI := ""
262270
labels := map[string]string{}
263271
if kind == v1.AzureManagedDisk {
264-
tags := make(map[string]string)
272+
tags, err := ConvertTagsToMap(customTags)
273+
if err != nil {
274+
return nil, err
275+
}
265276
if p.options.CloudTags != nil {
266-
tags = *(p.options.CloudTags)
277+
for k, v := range *(p.options.CloudTags) {
278+
tags[k] = v
279+
}
267280
}
268281
if strings.EqualFold(writeAcceleratorEnabled, "true") {
269282
tags[azure.WriteAcceleratorEnabled] = "true"
@@ -386,3 +399,28 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
386399

387400
return pv, nil
388401
}
402+
403+
// ConvertTagsToMap convert the tags from string to map
404+
// the valid tags fomat is "key1=value1,key2=value2", which could be converted to
405+
// {"key1": "value1", "key2": "value2"}
406+
func ConvertTagsToMap(tags string) (map[string]string, error) {
407+
m := make(map[string]string)
408+
if tags == "" {
409+
return m, nil
410+
}
411+
s := strings.Split(tags, TagsDelimiter)
412+
for _, tag := range s {
413+
kv := strings.Split(tag, TagKeyValueDelimiter)
414+
if len(kv) != 2 {
415+
return nil, fmt.Errorf("Tags '%s' are invalid, the format should like: 'key1=value1,key2=value2'", tags)
416+
}
417+
key := strings.TrimSpace(kv[0])
418+
if key == "" {
419+
return nil, fmt.Errorf("Tags '%s' are invalid, the format should like: 'key1=value1,key2=value2'", tags)
420+
}
421+
value := strings.TrimSpace(kv[1])
422+
m[key] = value
423+
}
424+
425+
return m, nil
426+
}

pkg/volume/azure_dd/azure_provision_test.go

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ package azure_dd
2020

2121
import (
2222
"fmt"
23+
"reflect"
2324
"testing"
2425

2526
"github.com/stretchr/testify/assert"
26-
"k8s.io/api/core/v1"
27+
v1 "k8s.io/api/core/v1"
2728
)
2829

2930
func TestParseZoned(t *testing.T) {
@@ -96,3 +97,69 @@ func TestParseZoned(t *testing.T) {
9697
}
9798
}
9899
}
100+
101+
func TestConvertTagsToMap(t *testing.T) {
102+
testCases := []struct {
103+
desc string
104+
tags string
105+
expectedOutput map[string]string
106+
expectedError bool
107+
}{
108+
{
109+
desc: "should return empty map when tag is empty",
110+
tags: "",
111+
expectedOutput: map[string]string{},
112+
expectedError: false,
113+
},
114+
{
115+
desc: "sing valid tag should be converted",
116+
tags: "key=value",
117+
expectedOutput: map[string]string{
118+
"key": "value",
119+
},
120+
expectedError: false,
121+
},
122+
{
123+
desc: "multiple valid tags should be converted",
124+
tags: "key1=value1,key2=value2",
125+
expectedOutput: map[string]string{
126+
"key1": "value1",
127+
"key2": "value2",
128+
},
129+
expectedError: false,
130+
},
131+
{
132+
desc: "whitespaces should be trimmed",
133+
tags: "key1=value1, key2=value2",
134+
expectedOutput: map[string]string{
135+
"key1": "value1",
136+
"key2": "value2",
137+
},
138+
expectedError: false,
139+
},
140+
{
141+
desc: "should return error for invalid format",
142+
tags: "foo,bar",
143+
expectedOutput: nil,
144+
expectedError: true,
145+
},
146+
{
147+
desc: "should return error for when key is missed",
148+
tags: "key1=value1,=bar",
149+
expectedOutput: nil,
150+
expectedError: true,
151+
},
152+
}
153+
154+
for i, c := range testCases {
155+
m, err := ConvertTagsToMap(c.tags)
156+
if c.expectedError {
157+
assert.NotNil(t, err, "TestCase[%d]: %s", i, c.desc)
158+
} else {
159+
assert.Nil(t, err, "TestCase[%d]: %s", i, c.desc)
160+
if !reflect.DeepEqual(m, c.expectedOutput) {
161+
t.Errorf("got: %v, expected: %v, desc: %v", m, c.expectedOutput, c.desc)
162+
}
163+
}
164+
}
165+
}

0 commit comments

Comments
 (0)