@@ -38,8 +38,11 @@ import (
3838)
3939
4040const (
41- ociVolumeID = "ociVolumeID"
42- ociVolumeBackupID = "volume.beta.kubernetes.io/oci-volume-source"
41+ ociVolumeID = "ociVolumeID"
42+ ociVolumeBackupID = "volume.beta.kubernetes.io/oci-volume-source"
43+ ociTagAnnotation = "oraclecloud.com/additional-tags"
44+
45+ defaultTagsEnvVar = "OCI_DEFAULT_TAGS"
4346 volumePrefixEnvVarName = "OCI_VOLUME_NAME_PREFIX"
4447 fsType = "fsType"
4548)
@@ -113,6 +116,14 @@ func (block *blockProvisioner) Provision(options controller.VolumeOptions, ad *i
113116 SizeInMBs : common .Int (volSizeMB ),
114117 }
115118
119+ definedTags , freeformTags , err := getTags (options .PVC .Annotations )
120+ if err != nil {
121+ return nil , err
122+ }
123+
124+ volumeDetails .DefinedTags = definedTags
125+ volumeDetails .FreeformTags = freeformTags
126+
116127 if value , ok := options .PVC .Annotations [ociVolumeBackupID ]; ok {
117128 glog .Infof ("Creating volume from backup ID %s" , value )
118129 volumeDetails .SourceDetails = & core.VolumeSourceFromVolumeBackupDetails {Id : & value }
@@ -172,6 +183,72 @@ func (block *blockProvisioner) Provision(options controller.VolumeOptions, ad *i
172183 return pv , nil
173184}
174185
186+ func getTags (annotations map [string ]string ) (defined map [string ]map [string ]interface {}, freeform map [string ]string , err error ) {
187+ defaultDefinedTags , defaultFreeformTags , err := parseTags (os .Getenv (defaultTagsEnvVar ))
188+ if err != nil {
189+ return nil , nil , err
190+ }
191+
192+ definedTags , freeformTags , err := parseTags (annotations [ociTagAnnotation ])
193+ if err != nil {
194+ return nil , nil , err
195+ }
196+
197+ // merge annotation tags with default tags
198+ for namespace , tags := range definedTags {
199+ if _ , ok := defaultDefinedTags [namespace ]; ! ok {
200+ defaultDefinedTags [namespace ] = map [string ]interface {}{}
201+ }
202+
203+ for tag , value := range tags {
204+ defaultDefinedTags [namespace ][tag ] = value
205+ }
206+ }
207+
208+ for tag , value := range freeformTags {
209+ defaultFreeformTags [tag ] = value
210+ }
211+
212+ return defaultDefinedTags , defaultFreeformTags , nil
213+ }
214+
215+ func parseTags (tagStr string ) (defined map [string ]map [string ]interface {}, freeform map [string ]string , err error ) {
216+
217+ defined = map [string ]map [string ]interface {}{}
218+ freeform = map [string ]string {}
219+
220+ if tagStr == "" {
221+ return
222+ }
223+
224+ for _ , tag := range strings .Split (tagStr , "," ) {
225+ parts := strings .Split (tag , "=" )
226+ if len (parts ) != 2 {
227+ return nil , nil , fmt .Errorf ("tag format must follow (<namespace>.)<tagkey>=<value>: %q" , tag )
228+ }
229+
230+ key , value := parts [0 ], parts [1 ]
231+
232+ keyParts := strings .Split (key , "." )
233+ if len (keyParts ) == 1 {
234+ freeform [key ] = value
235+ } else if len (keyParts ) == 2 {
236+ namespace , key := keyParts [0 ], keyParts [1 ]
237+ namespaceTags , ok := defined [namespace ]
238+ if ! ok {
239+ namespaceTags = map [string ]interface {}{}
240+ defined [namespace ] = namespaceTags
241+ }
242+
243+ namespaceTags [key ] = value
244+ } else {
245+ return nil , nil , fmt .Errorf ("tag format must follow (<namespace>.)<tagkey>=<value>: %q" , tag )
246+ }
247+ }
248+
249+ return
250+ }
251+
175252// Delete destroys a OCI volume created by Provision
176253func (block * blockProvisioner ) Delete (volume * v1.PersistentVolume ) error {
177254 volID , ok := volume .Annotations [ociVolumeID ]
0 commit comments