diff --git a/README.md b/README.md index 85abbc4a..d046e433 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,25 @@ spec: storage: 10Gi storageClassName: linode-block-storage-retain-luks ``` +### Adding Tags to created volumes +This feature gives users the ability to add tags to volumes created by a specific storageClass, to allow for better tracking of volumes. +Tags are added as a comma seperated string value for a parameter `linodebs.csi.linode.com/volumeTags` + +#### Example StorageClass +``` +allowVolumeExpansion: true +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + annotations: + storageclass.kubernetes.io/is-default-class: "true" + name: linode-block-storage + namespace: kube-system +provisioner: linodebs.csi.linode.com +parameters: + linodebs.csi.linode.com/volumeTags: "test, foo, yolo" +``` + ## Disclaimers diff --git a/helm-chart/csi-driver/templates/linode-block-storage-retain.yaml b/helm-chart/csi-driver/templates/linode-block-storage-retain.yaml index 861f83bc..42afe816 100644 --- a/helm-chart/csi-driver/templates/linode-block-storage-retain.yaml +++ b/helm-chart/csi-driver/templates/linode-block-storage-retain.yaml @@ -7,6 +7,10 @@ metadata: annotations: storageclass.kubernetes.io/is-default-class: "true" {{- end }} +{{- if .Values.addTags }} +parameters: + linodebs.csi.linode.com/volumeTags: "{{ .Values.addTags }}" +{{- end}} allowVolumeExpansion: true provisioner: linodebs.csi.linode.com reclaimPolicy: Retain diff --git a/helm-chart/csi-driver/templates/linode-block-storage.yaml b/helm-chart/csi-driver/templates/linode-block-storage.yaml index cd26adfa..7acf6b4a 100644 --- a/helm-chart/csi-driver/templates/linode-block-storage.yaml +++ b/helm-chart/csi-driver/templates/linode-block-storage.yaml @@ -7,5 +7,9 @@ metadata: annotations: storageclass.kubernetes.io/is-default-class: "true" {{- end }} +{{- if .Values.addTags }} +parameters: + linodebs.csi.linode.com/volumeTags: "{{ .Values.addTags }}" +{{- end}} allowVolumeExpansion: true provisioner: linodebs.csi.linode.com diff --git a/helm-chart/csi-driver/values.yaml b/helm-chart/csi-driver/values.yaml index 7045d4a3..65ebe87f 100644 --- a/helm-chart/csi-driver/values.yaml +++ b/helm-chart/csi-driver/values.yaml @@ -18,6 +18,9 @@ namespace: kube-system # "linode-block-storage" or left as an empty string defaultStorageClass: linode-block-storage-retain +# set these value to a comma seperated string if you'd like to add tags to the created volumes +# addTags: + # Images - Default csiProvisioner: image: registry.k8s.io/sig-storage/csi-provisioner @@ -45,4 +48,4 @@ kubectl: csiNodeDriverRegistrar: image: registry.k8s.io/sig-storage/csi-node-driver-registrar - tag: v1.3.0 \ No newline at end of file + tag: v1.3.0 diff --git a/pkg/linode-bs/controllerserver.go b/pkg/linode-bs/controllerserver.go index a62be526..c0222240 100644 --- a/pkg/linode-bs/controllerserver.go +++ b/pkg/linode-bs/controllerserver.go @@ -102,6 +102,8 @@ func (linodeCS *LinodeControllerServer) CreateVolume(ctx context.Context, req *c volumeContext[LuksKeySizeAttribute] = req.Parameters[LuksKeySizeAttribute] } + tags := req.Parameters[VolumeTags] + if len(volumes) != 0 { if len(volumes) > 1 { return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("duplicate volume %q exists", volumeName)) @@ -131,7 +133,7 @@ func (linodeCS *LinodeControllerServer) CreateVolume(ctx context.Context, req *c vol, err = linodeCS.cloneLinodeVolume(ctx, volumeName, volumeSizeGB, sourceVolumeInfo.VolumeID) } else { // Create the volume from scratch - vol, err = linodeCS.createLinodeVolume(ctx, volumeName, volumeSizeGB) + vol, err = linodeCS.createLinodeVolume(ctx, volumeName, volumeSizeGB, tags) } // Error handling for the above function calls @@ -546,11 +548,13 @@ func (linodeCS *LinodeControllerServer) attemptGetContentSourceVolume( // createLinodeVolume creates a Linode volume and returns the result func (linodeCS *LinodeControllerServer) createLinodeVolume( - ctx context.Context, label string, sizeGB int) (*linodego.Volume, error) { + ctx context.Context, label string, sizeGB int, tags string) (*linodego.Volume, error) { + volumeReq := linodego.VolumeCreateOptions{ Region: linodeCS.MetadataService.GetZone(), Label: label, Size: sizeGB, + Tags: strings.Split(tags, ","), } glog.V(4).Infoln("creating volume", map[string]interface{}{"volume_req": volumeReq}) diff --git a/pkg/linode-bs/driver_test.go b/pkg/linode-bs/driver_test.go index 1766ddc7..7c14283d 100644 --- a/pkg/linode-bs/driver_test.go +++ b/pkg/linode-bs/driver_test.go @@ -245,6 +245,7 @@ func (f *fakeAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) { Size: v.Size, FilesystemPath: path, Status: linodego.VolumeActive, + Tags: v.Tags, Created: &now, Updated: &now, } diff --git a/pkg/linode-bs/luks.go b/pkg/linode-bs/luks.go index 31f72256..2f9e040d 100644 --- a/pkg/linode-bs/luks.go +++ b/pkg/linode-bs/luks.go @@ -65,6 +65,10 @@ const ( // LuksKeyAttribute is the key of the luks key used in the map of secrets passed from the CO LuksKeyAttribute = "luksKey" + // VolumeTags is a comma seperated string used to pass information to the linode APIs to tag the + // created volumes + VolumeTags = driverName + "/volumeTags" + VolumeLifecycleNodeStageVolume VolumeLifecycle = "NodeStageVolume" VolumeLifecycleNodePublishVolume VolumeLifecycle = "NodePublishVolume" VolumeLifecycleNodeUnstageVolume VolumeLifecycle = "NodeUnstageVolume" @@ -257,7 +261,7 @@ func luksClose(volume string) error { func luksOpen(volume string, keyFile string, ctx LuksContext) error { // check if the luks volume is already open if _, err := os.Stat("/dev/mapper/" + ctx.VolumeName); !os.IsNotExist(err) { - glog.V(4).Info("luks volume is already open %s", volume) + glog.V(4).Infof("luks volume is already open %s", volume) return nil } diff --git a/pkg/linode-bs/nodeserver.go b/pkg/linode-bs/nodeserver.go index 2a315bb0..46694f5b 100644 --- a/pkg/linode-bs/nodeserver.go +++ b/pkg/linode-bs/nodeserver.go @@ -203,7 +203,7 @@ func (ns *LinodeNodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.No return nil, status.Error(codes.Internal, fmt.Sprintf("Unmount failed: %v\nUnmounting arguments: %s\n", err, targetPath)) } - glog.V(4).Infof("NodeUnpublishVolume called with args: %v, targetPath ", req, targetPath) + glog.V(4).Infof("NodeUnpublishVolume called with args: %v, targetPath %s", req, targetPath) if err := closeMountSources(targetPath); err != nil { return nil, err @@ -370,7 +370,7 @@ func closeMountSources(path string) error { return status.Error(codes.Internal, fmt.Sprintf("closeMountSources failed determine if mount is a luks mapping %s: %v", path, err)) } if isLuksMapping { - glog.V(4).Infof("luksClose ", mappingName) + glog.V(4).Infof("luksClose %s", mappingName) if err := luksClose(mappingName); err != nil { return status.Error(codes.Internal, fmt.Sprintf("closeMountSources failed to close luks mount %s: %v", path, err)) }