diff --git a/examples/custom_path/deployment.yaml b/examples/custom_path/deployment.yaml new file mode 100644 index 000000000..b18fc4d86 --- /dev/null +++ b/examples/custom_path/deployment.yaml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: local-path-rwx-example + labels: + app: local-path-rwx-example +spec: + replicas: 2 + selector: + matchLabels: + app: local-path-rwx-example + template: + metadata: + labels: + app: local-path-rwx-example + spec: + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app: local-path-rwx-example + containers: + - name: pause + image: busybox + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - 'hostname >> /data/shared.txt; sleep 3; cat /data/shared.txt; sleep infinity' + volumeMounts: + - name: volv + mountPath: /data + ports: + - containerPort: 80 + volumes: + - name: volv + persistentVolumeClaim: + claimName: local-path-rwx-example diff --git a/examples/custom_path/pvc.yaml b/examples/custom_path/pvc.yaml new file mode 100644 index 000000000..f2d18df4d --- /dev/null +++ b/examples/custom_path/pvc.yaml @@ -0,0 +1,21 @@ +# Plesase note, configuration of the Local Path Provisioner should be set correspondingly +# for this to work: +# +# data: +# config.json: |- +# { +# "sharedFileSystemPath": "/shared/fs/mounted/on/the/same/path/on/all/nodes" +# } +# +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: local-path-rwx-example +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: local-path + volumeMode: Filesystem diff --git a/provisioner.go b/provisioner.go index 25f6aeca6..61a3a7e62 100644 --- a/provisioner.go +++ b/provisioner.go @@ -30,8 +30,8 @@ const ( ) const ( - KeyNode = "kubernetes.io/hostname" - customPathAnnotation = "rancher.io/customPath" + KeyNode = "kubernetes.io/hostname" + customFolderNameAnnotation = "rancher.io/customFolderName" NodeDefaultNonListedNodes = "DEFAULT_PATH_FOR_NON_LISTED_NODES" @@ -46,6 +46,7 @@ const ( const ( defaultCmdTimeoutSeconds = 120 + defaultFolderExpression = "{{.pv.name}}-{{.namespace}}-{{.pvc.name}}" ) var ( @@ -78,6 +79,7 @@ type ConfigData struct { NodePathMap []*NodePathMapData `json:"nodePathMap,omitempty"` CmdTimeoutSeconds int `json:"cmdTimeoutSeconds,omitempty"` SharedFileSystemPath string `json:"sharedFileSystemPath,omitempty"` + FolderExpression string `json:"folderExpression,omitempty"` } type NodePathMap struct { @@ -88,6 +90,7 @@ type Config struct { NodePathMap map[string]*NodePathMap CmdTimeoutSeconds int SharedFileSystemPath string + FolderExpression string } func NewProvisioner(ctx context.Context, kubeClient *clientset.Clientset, @@ -259,17 +262,20 @@ func (p *LocalPathProvisioner) Provision(ctx context.Context, opts pvController. } name := opts.PVName - folderName := strings.Join([]string{name, opts.PVC.Namespace, opts.PVC.Name}, "_") - + folderName := "" + if pvc.GetAnnotations()[customFolderNameAnnotation] != "" { + folderName = pvc.GetAnnotations()[customFolderNameAnnotation] + } else { + folderName := strings.Replace(p.config.FolderExpression, "{{.namespace}}", opts.PVC.Namespace, -1) + folderName = strings.Replace(folderName, "{{.pvName}}", name, -1) + folderName = strings.Replace(folderName, "{{.pvcName}}", opts.PVC.Name, -1) + } path := filepath.Join(basePath, folderName) if nodeName == "" { logrus.Infof("Creating volume %v at %v", name, path) } else { logrus.Infof("Creating volume %v at %v:%v", name, nodeName, path) } - if pvc.GetAnnotations()[customPathAnnotation] != "" { - path = pvc.GetAnnotations()[customPathAnnotation] - } storage := pvc.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] provisionCmd := []string{"/bin/sh", "/script/setup"} if err := p.createHelperPod(ActionTypeCreate, provisionCmd, volumeOptions{ @@ -656,5 +662,10 @@ func canonicalizeConfig(data *ConfigData) (cfg *Config, err error) { } else { cfg.CmdTimeoutSeconds = defaultCmdTimeoutSeconds } + if data.FolderExpression != "" { + cfg.FolderExpression = data.FolderExpression + } else { + cfg.FolderExpression = defaultFolderExpression + } return cfg, nil }