Skip to content

Commit

Permalink
Add support for custom path patterns
Browse files Browse the repository at this point in the history
Add support for the `pathPattern` parameter, if set it is expanded as
a go template with the PV name and PVC metadata as input. This allow
configuring the provisioner to use predictable paths so volumes can be
prefilled externally or re-used.

Signed-off-by: Alban Bedel <[email protected]>
  • Loading branch information
AlbanBedel authored and derekbit committed May 26, 2024
1 parent 2d1a709 commit af85381
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,9 @@ A few things to note; the annotation for the `StorageClass` will apply to all vo

### Storage classes

If more than one `paths` are specified in the `nodePathMap` the path is chosen randomly. To make the provisioner choose a specific path, use a `storageClass` defined with a parameter called `nodePath`. Note that this path should be defined in the `nodePathMap`
If more than one `paths` are specified in the `nodePathMap` the path is chosen randomly. To make the provisioner choose a specific path, use a `storageClass` defined with a parameter called `nodePath`. Note that this path should be defined in the `nodePathMap`.

By default the volume subdirectory is named using the template `{{ .PVName }}_{{ .PVC.Namespace }}_{{ .PVC.Name }}` which make the directory specific to the PV instance. The template can be changed using the `pathPattern` parameter which is interpreted as a go template. The template has access to the PV name using the `PVName` variable and the PVC metadata object, including labels and annotations, with the `PVC` variable.
```
apiVersion: storage.k8s.io/v1
kind: StorageClass
Expand All @@ -285,11 +286,12 @@ metadata:
provisioner: rancher.io/local-path
parameters:
nodePath: /data/ssd
pathPattern: "{{ .PVC.Namespace }}/{{ .PVC.Name }}"
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
```
Here the provisioner will use the path `/data/ssd` when storage class `ssd-local-path` is used.
Here the provisioner will use the path `/data/ssd` with a subdirectory per namespace and PVC when storage class `ssd-local-path` is used.
## Uninstall
Expand Down
35 changes: 35 additions & 0 deletions provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strconv"
"strings"
"sync"
"text/template"
"time"

"github.com/Sirupsen/logrus"
Expand Down Expand Up @@ -291,6 +292,31 @@ func (p *LocalPathProvisioner) pickConfig(storageClassName string) (*StorageClas
return &cfg, nil
}

type pvMetadata struct {
PVName string
PVC metav1.ObjectMeta
}

func pathFromPattern(pattern string, opts pvController.ProvisionOptions) (string, error) {
metadata := pvMetadata{
PVName: opts.PVName,
PVC: opts.PVC.ObjectMeta,
}

tpl, err := template.New("pathPattern").Parse(pattern)
if err != nil {
return "", err
}

buf := new(bytes.Buffer)
err = tpl.Execute(buf, metadata)
if err != nil {
return "", err
}

return buf.String(), nil
}

func (p *LocalPathProvisioner) Provision(ctx context.Context, opts pvController.ProvisionOptions) (*v1.PersistentVolume, pvController.ProvisioningState, error) {
cfg, err := p.pickConfig(opts.StorageClass.Name)
if err != nil {
Expand Down Expand Up @@ -340,6 +366,15 @@ func (p *LocalPathProvisioner) provisionFor(opts pvController.ProvisionOptions,
name := opts.PVName
folderName := strings.Join([]string{name, opts.PVC.Namespace, opts.PVC.Name}, "_")

pathPattern, exists := opts.StorageClass.Parameters["pathPattern"]
if exists {
folderName, err = pathFromPattern(pathPattern, opts)
if err != nil {
err = errors.Wrapf(err, "failed to create path from pattern %v", pathPattern)
return nil, pvController.ProvisioningFinished, err
}
}

path := filepath.Join(basePath, folderName)
if nodeName == "" {
logrus.Infof("Creating volume %v at %v", name, path)
Expand Down

0 comments on commit af85381

Please sign in to comment.