diff --git a/README.md b/README.md index acd6ecc..6efc03b 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,10 @@ stringData: endpoint: https://storage.yandexcloud.net # For AWS set it to AWS region #region: "" + # 'usePrefix' must be true in order to enable the prefix feature and to avoid the removal of the prefix or bucket + usePrefix: "true" + # 'prefix' can be empty (it will mount on the root of the bucket), an existing prefix or a new one. + prefix: custom-prefix ``` The region can be empty if you are using some other S3 compatible storage. diff --git a/deploy/helm/templates/secret.yaml b/deploy/helm/templates/secret.yaml index dd6a748..4b6b79f 100644 --- a/deploy/helm/templates/secret.yaml +++ b/deploy/helm/templates/secret.yaml @@ -9,3 +9,7 @@ stringData: secretAccessKey: {{ .Values.secret.secretKey }} endpoint: {{ .Values.secret.endpoint }} {{- end -}} +{{- if .Values.secret.usePrefix }} + usePrefix: "true" +{{- end }} + prefix: "{{ .Values.secret.prefix }}" diff --git a/deploy/helm/values.yaml b/deploy/helm/values.yaml index 6b01f1c..42506c5 100644 --- a/deploy/helm/values.yaml +++ b/deploy/helm/values.yaml @@ -37,3 +37,7 @@ secret: secretKey: "" # Endpoint endpoint: https://storage.yandexcloud.net + # 'usePrefix' must be true in order to enable the prefix feature and to avoid the removal of the prefix or bucket + usePrefix: + # 'prefix' can be empty (it will mount on the root of the bucket), an existing prefix or a new one. + prefix: diff --git a/pkg/driver/controllerserver.go b/pkg/driver/controllerserver.go index 4ce6d86..90b386f 100644 --- a/pkg/driver/controllerserver.go +++ b/pkg/driver/controllerserver.go @@ -22,6 +22,7 @@ import ( "fmt" "io" "path" + "strconv" "strings" "github.com/yandex-cloud/k8s-csi-s3/pkg/mounter" @@ -41,10 +42,12 @@ type controllerServer struct { func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) { params := req.GetParameters() + secrets := req.GetSecrets() capacityBytes := int64(req.GetCapacityRange().GetRequiredBytes()) volumeID := sanitizeVolumeID(req.GetName()) bucketName := volumeID prefix := "" + usePrefix, usePrefixError := strconv.ParseBool(secrets[mounter.UsePrefix]) // check if bucket name is overridden if params[mounter.BucketKey] != "" { @@ -53,6 +56,15 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol volumeID = path.Join(bucketName, prefix) } + // check if volume prefix is overridden + if usePrefixError == nil && usePrefix { + prefix = "" + if prefixOverride, ok := secrets[mounter.VolumePrefix]; ok && prefixOverride != "" { + prefix = prefixOverride + } + volumeID = path.Join(bucketName, prefix) + } + if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil { glog.V(3).Infof("invalid create volume req: %v", req) return nil, err @@ -85,7 +97,9 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol } if err = client.CreatePrefix(bucketName, prefix); err != nil { - return nil, fmt.Errorf("failed to create prefix %s: %v", prefix, err) + if usePrefixError != nil || !usePrefix { + return nil, fmt.Errorf("failed to create prefix %s: %v", prefix, err) + } } glog.V(4).Infof("create volume %s", volumeID) @@ -126,7 +140,12 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol } var deleteErr error - if prefix == "" { + usePrefix, usePrefixError := strconv.ParseBool(req.GetSecrets()[mounter.UsePrefix]) + if usePrefixError == nil && usePrefix { + // UsePrefix is true, we do not delete anything + glog.V(4).Infof("Nothing to remove for %s", bucketName) + return &csi.DeleteVolumeResponse{}, nil + } else if prefix == "" { // prefix is empty, we delete the whole bucket if err := client.RemoveBucket(bucketName); err != nil && err.Error() != "The specified bucket does not exist" { deleteErr = err diff --git a/pkg/mounter/mounter.go b/pkg/mounter/mounter.go index 1e79421..6626c29 100644 --- a/pkg/mounter/mounter.go +++ b/pkg/mounter/mounter.go @@ -32,6 +32,8 @@ const ( TypeKey = "mounter" BucketKey = "bucket" OptionsKey = "options" + VolumePrefix = "prefix" + UsePrefix = "usePrefix" ) // New returns a new mounter depending on the mounterType parameter