From b48ecac166be2b5202f8acb53a6a2ecd7487a138 Mon Sep 17 00:00:00 2001 From: Rob Kooper Date: Sat, 19 Nov 2022 09:02:55 -0600 Subject: [PATCH 1/5] Add missing pvname This adds the ability to use the pvname as part of the pathpattern. The defaultpath is now a string that is parsed the same way as the user specified pathpattern. --- README.md | 10 +++--- .../provisioner.go | 34 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 68a9835b..56571ebb 100644 --- a/README.md +++ b/README.md @@ -234,11 +234,11 @@ To disable leader election, define an env variable named ENABLE_LEADER_ELECTION **_Parameters:_** -| Name | Description | Default | -| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------: | -| onDelete | If it exists and has a delete value, delete the directory, if it exists and has a retain value, save the directory. | will be archived with name on the share: `archived-` | -| archiveOnDelete | If it exists and has a false value, delete the directory. if `onDelete` exists, `archiveOnDelete` will be ignored. | will be archived with name on the share: `archived-` | -| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. | n/a | +| Name | Description | Default | +| --------------- | ------------------------------------------------------------ | :----------------------------------------------------------: | +| onDelete | If it exists and has a delete value, delete the directory, if it exists and has a retain value, save the directory. | will be archived with name on the share: `archived-` | +| archiveOnDelete | If it exists and has a false value, delete the directory. if `onDelete` exists, `archiveOnDelete` will be ignored. | will be archived with name on the share: `archived-` | +| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combing namespace, name and an unique id. | will create a folder witht the pattern: `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | This is `deploy/class.yaml` which defines the NFS subdir external provisioner's Kubernetes Storage Class: diff --git a/cmd/nfs-subdir-external-provisioner/provisioner.go b/cmd/nfs-subdir-external-provisioner/provisioner.go index e124757d..0829ed6c 100644 --- a/cmd/nfs-subdir-external-provisioner/provisioner.go +++ b/cmd/nfs-subdir-external-provisioner/provisioner.go @@ -41,6 +41,8 @@ import ( const ( provisionerNameKey = "PROVISIONER_NAME" + defaultPathPattern = "${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}" + mountPath = "/persistentvolumes" ) type nfsProvisioner struct { @@ -73,10 +75,6 @@ func (meta *pvcMetadata) stringParser(str string) string { return str } -const ( - mountPath = "/persistentvolumes" -) - var _ controller.Provisioner = &nfsProvisioner{} func (p *nfsProvisioner) Provision(ctx context.Context, options controller.ProvisionOptions) (*v1.PersistentVolume, controller.ProvisioningState, error) { @@ -85,31 +83,27 @@ func (p *nfsProvisioner) Provision(ctx context.Context, options controller.Provi } glog.V(4).Infof("nfs provisioner: VolumeOptions %v", options) - pvcNamespace := options.PVC.Namespace - pvcName := options.PVC.Name - - pvName := strings.Join([]string{pvcNamespace, pvcName, options.PVName}, "-") - metadata := &pvcMetadata{ data: map[string]string{ - "name": pvcName, - "namespace": pvcNamespace, + "name": options.PVC.Name, + "namespace": options.PVC.Namespace, + "pvname": options.PVName, }, labels: options.PVC.Labels, annotations: options.PVC.Annotations, } - fullPath := filepath.Join(mountPath, pvName) - path := filepath.Join(p.path, pvName) - pathPattern, exists := options.StorageClass.Parameters["pathPattern"] - if exists { - customPath := metadata.stringParser(pathPattern) - if customPath != "" { - path = filepath.Join(p.path, customPath) - fullPath = filepath.Join(mountPath, customPath) - } + if !exists { + pathPattern = defaultPathPattern + } + + parsedPath := metadata.stringParser(pathPattern) + if parsedPath == "" { + return nil, controller.ProvisioningFinished, errors.New("unable to parse pathPattern: " + pathPattern) } + path := filepath.Join(p.path, parsedPath) + fullPath := filepath.Join(mountPath, parsedPath) glog.V(4).Infof("creating path %s", fullPath) if err := os.MkdirAll(fullPath, 0o777); err != nil { From 7a1baca618f9ae84dac469f9e0fb3bd1614262a6 Mon Sep 17 00:00:00 2001 From: Rob Kooper Date: Thu, 24 Nov 2022 11:59:12 -0600 Subject: [PATCH 2/5] fix typo and space --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56571ebb..62c4e2a2 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ To disable leader election, define an env variable named ENABLE_LEADER_ELECTION | --------------- | ------------------------------------------------------------ | :----------------------------------------------------------: | | onDelete | If it exists and has a delete value, delete the directory, if it exists and has a retain value, save the directory. | will be archived with name on the share: `archived-` | | archiveOnDelete | If it exists and has a false value, delete the directory. if `onDelete` exists, `archiveOnDelete` will be ignored. | will be archived with name on the share: `archived-` | -| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combing namespace, name and an unique id. | will create a folder witht the pattern: `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | +| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combing namespace, name and an unique id. | will create a folder with the pattern: `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | This is `deploy/class.yaml` which defines the NFS subdir external provisioner's Kubernetes Storage Class: From b47ac8ea653077d31ba1e433a4dc03fb435e47a9 Mon Sep 17 00:00:00 2001 From: Rob Kooper Date: Fri, 25 Nov 2022 15:13:36 -0600 Subject: [PATCH 3/5] fix tyopos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 62c4e2a2..a46b9bd1 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ $ oc adm policy add-scc-to-user hostmount-anyuid system:serviceaccount:$NAMESPAC If you would like to use a custom built nfs-subdir-external-provisioner image, you must edit the provisioner's deployment file to specify the correct location of your `nfs-client-provisioner` container image. -Next you must edit the provisioner's deployment file to add connection information for your NFS server. Edit `deploy/deployment.yaml` and replace the two occurences of with your server's hostname. +Next you must edit the provisioner's deployment file to add connection information for your NFS server. Edit `deploy/deployment.yaml` and replace the two occurrences of with your server's hostname. ```yaml kind: Deployment @@ -238,7 +238,7 @@ To disable leader election, define an env variable named ENABLE_LEADER_ELECTION | --------------- | ------------------------------------------------------------ | :----------------------------------------------------------: | | onDelete | If it exists and has a delete value, delete the directory, if it exists and has a retain value, save the directory. | will be archived with name on the share: `archived-` | | archiveOnDelete | If it exists and has a false value, delete the directory. if `onDelete` exists, `archiveOnDelete` will be ignored. | will be archived with name on the share: `archived-` | -| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combing namespace, name and an unique id. | will create a folder with the pattern: `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | +| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combining namespace, name and an unique id. | will create a folder with the pattern: `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | This is `deploy/class.yaml` which defines the NFS subdir external provisioner's Kubernetes Storage Class: From faed42f738b7c4facb56d65382ea516116c1e057 Mon Sep 17 00:00:00 2001 From: Rob Kooper Date: Fri, 17 Mar 2023 15:41:04 -0500 Subject: [PATCH 4/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a46b9bd1..be226fdd 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ To disable leader election, define an env variable named ENABLE_LEADER_ELECTION | --------------- | ------------------------------------------------------------ | :----------------------------------------------------------: | | onDelete | If it exists and has a delete value, delete the directory, if it exists and has a retain value, save the directory. | will be archived with name on the share: `archived-` | | archiveOnDelete | If it exists and has a false value, delete the directory. if `onDelete` exists, `archiveOnDelete` will be ignored. | will be archived with name on the share: `archived-` | -| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combining namespace, name and an unique id. | will create a folder with the pattern: `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | +| pathPattern | Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace. To specify metadata use `${.PVC.}`. Example: If folder should be named like `-`, use `${.PVC.namespace}-${.PVC.name}` as pathPattern. The default pattern will add the pvname to folder, which will result in a unique folder name, combining namespace, name and an unique id. | `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | This is `deploy/class.yaml` which defines the NFS subdir external provisioner's Kubernetes Storage Class: From a398074e32ee4bcd3cfe53b12facad60b1528df9 Mon Sep 17 00:00:00 2001 From: Rob Kooper Date: Fri, 11 Aug 2023 13:45:51 -0500 Subject: [PATCH 5/5] updates - add text to chart/readme - empty pathPattern is same as default --- .../nfs-subdir-external-provisioner/README.md | 78 +++++++++---------- .../provisioner.go | 2 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/charts/nfs-subdir-external-provisioner/README.md b/charts/nfs-subdir-external-provisioner/README.md index eb4e41e5..373f8698 100644 --- a/charts/nfs-subdir-external-provisioner/README.md +++ b/charts/nfs-subdir-external-provisioner/README.md @@ -48,45 +48,45 @@ The command removes all the Kubernetes components associated with the chart and The following tables lists the configurable parameters of this chart and their default values. -| Parameter | Description | Default | -| ------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| `replicaCount` | Number of provisioner instances to deployed | `1` | -| `strategyType` | Specifies the strategy used to replace old Pods by new ones | `Recreate` | -| `image.repository` | Provisioner image | `registry.k8s.io/sig-storage/nfs-subdir-external-provisioner` | -| `image.tag` | Version of provisioner image | `v4.0.2` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `imagePullSecrets` | Image pull secrets | `[]` | -| `storageClass.name` | Name of the storageClass | `nfs-client` | -| `storageClass.defaultClass` | Set as the default StorageClass | `false` | -| `storageClass.allowVolumeExpansion` | Allow expanding the volume | `true` | -| `storageClass.reclaimPolicy` | Method used to reclaim an obsoleted volume | `Delete` | -| `storageClass.provisionerName` | Name of the provisionerName | null | -| `storageClass.archiveOnDelete` | Archive PVC when deleting | `true` | -| `storageClass.onDelete` | Strategy on PVC deletion. Overrides archiveOnDelete when set to lowercase values 'delete' or 'retain' | null | -| `storageClass.pathPattern` | Specifies a template for the directory name | null | -| `storageClass.accessModes` | Set access mode for PV | `ReadWriteOnce` | -| `storageClass.volumeBindingMode` | Set volume binding mode for Storage Class | `Immediate` | -| `storageClass.annotations` | Set additional annotations for the StorageClass | `{}` | -| `leaderElection.enabled` | Enables or disables leader election | `true` | -| `nfs.server` | Hostname of the NFS server (required) | null (ip or hostname) | -| `nfs.path` | Basepath of the mount point to be used | `/nfs-storage` | -| `nfs.mountOptions` | Mount options (e.g. 'nfsvers=3') | null | -| `nfs.volumeName` | Volume name used inside the pods | `nfs-subdir-external-provisioner-root` | -| `nfs.reclaimPolicy` | Reclaim policy for the main nfs volume used for subdir provisioning | `Retain` | -| `resources` | Resources required (e.g. CPU, memory) | `{}` | -| `rbac.create` | Use Role-based Access Control | `true` | -| `podSecurityPolicy.enabled` | Create & use Pod Security Policy resources | `false` | -| `podAnnotations` | Additional annotations for the Pods | `{}` | -| `priorityClassName` | Set pod priorityClassName | null | -| `serviceAccount.create` | Should we create a ServiceAccount | `true` | -| `serviceAccount.name` | Name of the ServiceAccount to use | null | -| `serviceAccount.annotations` | Additional annotations for the ServiceAccount | `{}` | -| `nodeSelector` | Node labels for pod assignment | `{}` | -| `affinity` | Affinity settings | `{}` | -| `tolerations` | List of node taints to tolerate | `[]` | -| `labels` | Additional labels for any resource created | `{}` | -| `podDisruptionBudget.enabled` | Create and use Pod Disruption Budget | `false` | -| `podDisruptionBudget.maxUnavailable` | Set maximum unavailable pods in the Pod Disruption Budget | `1` | +| Parameter | Description | Default | +| ------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| `replicaCount` | Number of provisioner instances to deployed | `1` | +| `strategyType` | Specifies the strategy used to replace old Pods by new ones | `Recreate` | +| `image.repository` | Provisioner image | `registry.k8s.io/sig-storage/nfs-subdir-external-provisioner` | +| `image.tag` | Version of provisioner image | `v4.0.2` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `imagePullSecrets` | Image pull secrets | `[]` | +| `storageClass.name` | Name of the storageClass | `nfs-client` | +| `storageClass.defaultClass` | Set as the default StorageClass | `false` | +| `storageClass.allowVolumeExpansion` | Allow expanding the volume | `true` | +| `storageClass.reclaimPolicy` | Method used to reclaim an obsoleted volume | `Delete` | +| `storageClass.provisionerName` | Name of the provisionerName | null | +| `storageClass.archiveOnDelete` | Archive PVC when deleting | `true` | +| `storageClass.onDelete` | Strategy on PVC deletion. Overrides archiveOnDelete when set to lowercase values 'delete' or 'retain' | null | +| `storageClass.pathPattern` | Specifies a template for the directory name. The default will combine PVC namespce, PVC name and PV name which will result in a unique folder name. | `${.PVC.namespace}-${.PVC.name}-${.PVC.pvname}` | +| `storageClass.accessModes` | Set access mode for PV | `ReadWriteOnce` | +| `storageClass.volumeBindingMode` | Set volume binding mode for Storage Class | `Immediate` | +| `storageClass.annotations` | Set additional annotations for the StorageClass | `{}` | +| `leaderElection.enabled` | Enables or disables leader election | `true` | +| `nfs.server` | Hostname of the NFS server (required) | null (ip or hostname) | +| `nfs.path` | Basepath of the mount point to be used | `/nfs-storage` | +| `nfs.mountOptions` | Mount options (e.g. 'nfsvers=3') | null | +| `nfs.volumeName` | Volume name used inside the pods | `nfs-subdir-external-provisioner-root` | +| `nfs.reclaimPolicy` | Reclaim policy for the main nfs volume used for subdir provisioning | `Retain` | +| `resources` | Resources required (e.g. CPU, memory) | `{}` | +| `rbac.create` | Use Role-based Access Control | `true` | +| `podSecurityPolicy.enabled` | Create & use Pod Security Policy resources | `false` | +| `podAnnotations` | Additional annotations for the Pods | `{}` | +| `priorityClassName` | Set pod priorityClassName | null | +| `serviceAccount.create` | Should we create a ServiceAccount | `true` | +| `serviceAccount.name` | Name of the ServiceAccount to use | null | +| `serviceAccount.annotations` | Additional annotations for the ServiceAccount | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `affinity` | Affinity settings | `{}` | +| `tolerations` | List of node taints to tolerate | `[]` | +| `labels` | Additional labels for any resource created | `{}` | +| `podDisruptionBudget.enabled` | Create and use Pod Disruption Budget | `false` | +| `podDisruptionBudget.maxUnavailable` | Set maximum unavailable pods in the Pod Disruption Budget | `1` | ## Install Multiple Provisioners diff --git a/cmd/nfs-subdir-external-provisioner/provisioner.go b/cmd/nfs-subdir-external-provisioner/provisioner.go index 0829ed6c..8ced5ec0 100644 --- a/cmd/nfs-subdir-external-provisioner/provisioner.go +++ b/cmd/nfs-subdir-external-provisioner/provisioner.go @@ -94,7 +94,7 @@ func (p *nfsProvisioner) Provision(ctx context.Context, options controller.Provi } pathPattern, exists := options.StorageClass.Parameters["pathPattern"] - if !exists { + if !exists || pathPattern == "" { pathPattern = defaultPathPattern }