Skip to content

Commit

Permalink
Merge pull request #7 from ccremer/zfs
Browse files Browse the repository at this point in the history
[kubernetes-zfs-provisioner] Add StorageClass templates
  • Loading branch information
ccremer authored Apr 13, 2020
2 parents 04eff41 + 3d854ba commit 222762b
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 8 deletions.
2 changes: 1 addition & 1 deletion kubernetes-zfs-provisioner/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description: Dynamic ZFS persistent volume provisioner for Kubernetes

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 0.1.0
version: 0.2.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
Expand Down
13 changes: 10 additions & 3 deletions kubernetes-zfs-provisioner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ kubernetes-zfs-provisioner
==========================
Dynamic ZFS persistent volume provisioner for Kubernetes

Current chart version is `0.1.0`
Current chart version is `0.2.0`



Expand All @@ -22,7 +22,6 @@ Current chart version is `0.1.0`
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | Reminder: This has no effect on any PVs, but maybe you want the provisioner pod running on certain nodes. |
| podSecurityContext | object | `{}` | |
| provisioner.externalSecretName | string | `""` | If SSH secrets are managed externally, specify the name |
| provisioner.instance | string | `"pv.kubernetes.io/zfs"` | Provisoner instance name if multiple are running (multiple instances are not required for managing multiple ZFS hosts) |
| rbac.create | bool | `false` | **Required for first time deployments** Grant the service account the necessary permissions, |
| replicaCount | int | `1` | Usually `1` is fine |
Expand All @@ -36,6 +35,14 @@ Current chart version is `0.1.0`
| ssh.config | string | `""` | **Required.** ssh_config(5)-compatible file content to configure SSH options when connecting |
| ssh.externalSecretName | string | `""` | If SSH secrets are managed externally, specify the name |
| ssh.identities | object | `{}` | **Required.** Provide a private key for each SSH identity, see values.yaml for an example |
| ssh.knownHosts | string | `nil` | **Required.** List of {host, pubKey} dicts where the public key of each host is configured |
| ssh.knownHosts | list | `[]` | **Required.** List of {host, pubKey} dicts where the public key of each host is configured |
| ssh.mountPath | string | `"/home/zfs/.ssh"` | The path where the SSH config and identities are mounted |
| storageClass.classes[0].hostName | string | `"storage-1.domain.tld"` | The provisioners connects through SSH to this ZFS host |
| storageClass.classes[0].name | string | `"zfs"` | |
| storageClass.classes[0].node | string | `""` | Override `kubernetes.io/hostname` from `hostName` parameter for `HostPath` node affinity |
| storageClass.classes[0].parentDataset | string | `"tank/kubernetes"` | Existing dataset on the target ZFS host |
| storageClass.classes[0].policy | string | `"Delete"` | The reclaim policy supported by the provisioner |
| storageClass.classes[0].shareProperties | string | `""` | NFS export properties (see `exports(5)`) |
| storageClass.classes[0].type | string | `"nfs"` | Provision type, one of [`nfs`, `hostpath`] |
| storageClass.create | bool | `false` | Whether to create storage classes for this provisioner. One example is given in the `classes` array |
| tolerations | list | `[]` | |
19 changes: 19 additions & 0 deletions kubernetes-zfs-provisioner/templates/storageclass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{- if .Values.storageClass.create -}}
{{- range .Values.storageClass.classes }}
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: {{ .name }}
labels:
{{- include "kubernetes-zfs-provisioner.labels" $ | nindent 4 }}
provisioner: {{ $.Values.provisioner.instance }}
reclaimPolicy: {{ .policy | default "Delete" }}
parameters:
parentDataset: {{ .parentDataset }}
hostname: {{ .hostName }}
type: {{ .type | default "nfs" }}
node: {{ .nodeName | default "" }}
shareProperties: {{ .shareProperties | default "" }}
{{- end }}
{{- end }}
1 change: 0 additions & 1 deletion kubernetes-zfs-provisioner/test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.14

require (
github.com/gruntwork-io/terratest v0.25.0
github.com/magiconair/properties v1.8.1
github.com/stretchr/testify v1.5.1
k8s.io/api v0.17.0
)
8 changes: 8 additions & 0 deletions kubernetes-zfs-provisioner/test/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik=
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
Expand Down Expand Up @@ -155,6 +157,7 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
Expand Down Expand Up @@ -215,9 +218,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
Expand Down Expand Up @@ -460,6 +465,7 @@ golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200113040837-eac381796e91/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
Expand All @@ -474,6 +480,7 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
Expand All @@ -494,6 +501,7 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
Expand Down
62 changes: 62 additions & 0 deletions kubernetes-zfs-provisioner/test/storageclass_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package test

import (
"github.com/gruntwork-io/terratest/modules/helm"
"github.com/stretchr/testify/assert"
core "k8s.io/api/core/v1"
v1 "k8s.io/api/storage/v1"
"testing"
)

var tplStorageclass = []string{"templates/storageclass.yaml"}

func Test_Storageclass_GivenClassesEnabled_WhenNoPolicyDefined_ThenRenderDefault(t *testing.T) {
options := &helm.Options{
SetValues: map[string]string{
"storageClass.create": "true",
"storageClass.classes[0].policy": "",
},
}

output := helm.RenderTemplate(t, options, helmChartPath, releaseName, tplStorageclass)

var class v1.StorageClass
helm.UnmarshalK8SYaml(t, output, &class)

expectedPolicy := core.PersistentVolumeReclaimDelete
assert.Equal(t, &expectedPolicy, class.ReclaimPolicy)
}

func Test_Secret_GivenClassesEnabled_WhenNoTypeDefined_ThenRenderDefault(t *testing.T) {
options := &helm.Options{
SetValues: map[string]string{
"storageClass.create": "true",
"storageClass.classes[0].type": "",
},
}

output := helm.RenderTemplate(t, options, helmChartPath, releaseName, tplStorageclass)

var class v1.StorageClass
helm.UnmarshalK8SYaml(t, output, &class)

assert.Equal(t, "nfs", class.Parameters["type"])
}

func Test_Secret_GivenClassesEnabled_WhenAdditionalParametersUndefined_ThenRenderEmptyValues(t *testing.T) {
options := &helm.Options{
SetValues: map[string]string{
"storageClass.create": "true",
"storageClass.classes[0].node": "",
"storageClass.classes[0].shareProperties": "",
},
}

output := helm.RenderTemplate(t, options, helmChartPath, releaseName, tplStorageclass)

var class v1.StorageClass
helm.UnmarshalK8SYaml(t, output, &class)

assert.Equal(t, "", class.Parameters["shareProperties"])
assert.Equal(t, "", class.Parameters["node"])
}
24 changes: 21 additions & 3 deletions kubernetes-zfs-provisioner/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,26 @@ provisioner:
# provisioner.instance -- Provisoner instance name if multiple are running (multiple
# instances are not required for managing multiple ZFS hosts)
instance: pv.kubernetes.io/zfs
# provisioner.externalSecretName -- If SSH secrets are managed externally, specify the name
externalSecretName: ""

storageClass:
# storageClass.create -- Whether to create storage classes for this provisioner. One example is given
# in the `classes` array
create: false
classes:
- name: zfs
# storageClass.classes[0].hostName -- The provisioners connects through SSH to this ZFS host
hostName: storage-1.domain.tld
# storageClass.classes[0].parentDataset -- Existing dataset on the target ZFS host
parentDataset: tank/kubernetes
# storageClass.classes[0].policy -- The reclaim policy supported by the provisioner
policy: "Delete"
# storageClass.classes[0].shareProperties -- NFS export properties (see `exports(5)`)
shareProperties: ""
# storageClass.classes[0].type -- Provision type, one of [`nfs`, `hostpath`]
type: "nfs"
# storageClass.classes[0].node -- Override `kubernetes.io/hostname` from `hostName` parameter for
# `HostPath` node affinity
node: ""

ssh:
# ssh.externalSecretName -- If SSH secrets are managed externally, specify the name
Expand All @@ -41,7 +59,7 @@ ssh:
# ...
# -----END OPENSSH PRIVATE KEY-----
# ssh.knownHosts -- **Required.** List of {host, pubKey} dicts where the public key of each host is configured
knownHosts:
knownHosts: []
# - host: my-host
# pubKey: ssh-ed25519 AAAAC3NzaC...

Expand Down

0 comments on commit 222762b

Please sign in to comment.