Skip to content

Commit

Permalink
[kubernetes-zfs-provisioner] Add first Chart
Browse files Browse the repository at this point in the history
  • Loading branch information
ccremer committed Apr 13, 2020
1 parent b83fc51 commit c97d9bb
Show file tree
Hide file tree
Showing 20 changed files with 1,101 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ ccremer's Helm charts repository

## List of Charts

* [kubernetes-zfs-provisioner](kubernetes-zfs-provisioner/README.md)
* [znapzend](znapzend/README.md)
23 changes: 23 additions & 0 deletions kubernetes-zfs-provisioner/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
23 changes: 23 additions & 0 deletions kubernetes-zfs-provisioner/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v2
name: kubernetes-zfs-provisioner
description: Dynamic ZFS persistent volume provisioner for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
#type: application

# 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

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 0.1.0
# Licensing of https://commons.wikimedia.org/wiki/File:Openzfs.svg applies
icon: https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Openzfs.svg/257px-Openzfs.svg.png
41 changes: 41 additions & 0 deletions kubernetes-zfs-provisioner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
kubernetes-zfs-provisioner
==========================
Dynamic ZFS persistent volume provisioner for Kubernetes

Current chart version is `0.1.0`





## Chart Values

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | |
| env | object | `{}` | A dict with KEY: VALUE pairs |
| fullnameOverride | string | `""` | |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.repository | string | `"docker.io/ccremer/zfs-provisioner"` | Location of the container image |
| image.tag | string | `"v0.1.0"` | Container image tag |
| imagePullSecrets | list | `[]` | |
| 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 |
| resources.limits.memory | string | `"100Mi"` | |
| resources.requests.cpu | string | `"10m"` | |
| resources.requests.memory | string | `"20Mi"` | |
| securityContext | object | `{}` | |
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template |
| 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.mountPath | string | `"/home/zfs/.ssh"` | The path where the SSH config and identities are mounted |
| tolerations | list | `[]` | |
70 changes: 70 additions & 0 deletions kubernetes-zfs-provisioner/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "kubernetes-zfs-provisioner.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "kubernetes-zfs-provisioner.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "kubernetes-zfs-provisioner.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Common labels
*/}}
{{- define "kubernetes-zfs-provisioner.labels" -}}
helm.sh/chart: {{ include "kubernetes-zfs-provisioner.chart" . }}
{{ include "kubernetes-zfs-provisioner.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}

{{/*
Selector labels
*/}}
{{- define "kubernetes-zfs-provisioner.selectorLabels" -}}
app.kubernetes.io/name: {{ include "kubernetes-zfs-provisioner.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}

{{/*
Create the name of the service account to use
*/}}
{{- define "kubernetes-zfs-provisioner.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "kubernetes-zfs-provisioner.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

{{/*
Create the name of the secret to use
*/}}
{{- define "kubernetes-zfs-provisioner.secretName" -}}
{{ default (include "kubernetes-zfs-provisioner.fullname" .) .Values.ssh.externalSecretName }}
{{- end -}}
65 changes: 65 additions & 0 deletions kubernetes-zfs-provisioner/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "kubernetes-zfs-provisioner.fullname" . }}
labels:
{{- include "kubernetes-zfs-provisioner.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "kubernetes-zfs-provisioner.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "kubernetes-zfs-provisioner.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "kubernetes-zfs-provisioner.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: provisioner
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: ZFS_PROVISIONER_INSTANCE
value: {{ .Values.provisioner.instance }}
{{- with .Values.env }}
{{- range $key, $value := . }}
- name: {{ $key }}
value: {{ $value }}
{{- end }}
{{- end }}
ports:
- name: http
containerPort: 8080
volumeMounts:
- name: ssh
mountPath: {{ .Values.ssh.mountPath }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
{{- with .Values.ssh }}
- name: ssh
secret:
secretName: {{ include "kubernetes-zfs-provisioner.secretName" $ }}
defaultMode: 0600
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
32 changes: 32 additions & 0 deletions kubernetes-zfs-provisioner/templates/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{- if .Values.rbac.create -}}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ include "kubernetes-zfs-provisioner.fullname" . }}-binding
labels:
{{- include "kubernetes-zfs-provisioner.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:persistent-volume-provisioner
subjects:
- kind: ServiceAccount
name: {{ include "kubernetes-zfs-provisioner.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ include "kubernetes-zfs-provisioner.fullname" . }}-leaderelection
labels:
{{- include "kubernetes-zfs-provisioner.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:controller:endpoint-controller
subjects:
- kind: ServiceAccount
name: {{ include "kubernetes-zfs-provisioner.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end -}}
22 changes: 22 additions & 0 deletions kubernetes-zfs-provisioner/templates/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if not .Values.ssh.externalSecretName -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "kubernetes-zfs-provisioner.fullname" . }}
labels:
{{- include "kubernetes-zfs-provisioner.labels" . | nindent 4 }}
stringData:
{{- with .Values.ssh.knownHosts }}
known_hosts: |
{{- range . }}
{{ .host }} {{ .pubKey }}
{{ end }}
{{- end }}
{{- with .Values.ssh.config }}
config: |
{{- . | nindent 4 }}
{{- end }}
{{- range $key,$value := .Values.ssh.identities }}
{{ $key -}}: {{ $value | toYaml | indent 2 }}
{{- end }}
{{- end }}
12 changes: 12 additions & 0 deletions kubernetes-zfs-provisioner/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "kubernetes-zfs-provisioner.serviceAccountName" . }}
labels:
{{- include "kubernetes-zfs-provisioner.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end -}}
70 changes: 70 additions & 0 deletions kubernetes-zfs-provisioner/test/deployment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package test

import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
"testing"
"unsafe"

"github.com/gruntwork-io/terratest/modules/helm"
appv1 "k8s.io/api/apps/v1"
)

var tplDeployment = []string{"templates/deployment.yaml"}

func Test_Deployment_ShouldRender_EnvironmentVariables(t *testing.T) {
options := &helm.Options{
ValuesFiles: []string{"values/deployment_1.yaml"},
}

expectedKeys := []string{"KEY1", "ANOTHER_KEY", "ZFS_PROVISIONER_INSTANCE"}
expectedValues := []string{"value", "another value", "pv.kubernetes.io/zfs"}

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

var deployment appv1.Deployment
helm.UnmarshalK8SYaml(t, output, &deployment)

envs := deployment.Spec.Template.Spec.Containers[0].Env
assert.Equal(t, len(envs), 3)
for i, _ := range envs {
require.Contains(t, envs, v1.EnvVar{
Name: expectedKeys[i],
Value: expectedValues[i],
})
}
}

func Test_Deployment_ShouldRender_SshVolumes_IfEnabled(t *testing.T) {
options := &helm.Options{
ValuesFiles: []string{"values/deployment_2.yaml"},
}

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

var deployment appv1.Deployment
helm.UnmarshalK8SYaml(t, output, &deployment)

volumeMounts := deployment.Spec.Template.Spec.Containers[0].VolumeMounts
require.Contains(t, volumeMounts, v1.VolumeMount{
Name: "ssh",
MountPath: "/home/zfs/.ssh",
})

volumes := deployment.Spec.Template.Spec.Volumes
require.Contains(t, volumes, v1.Volume{
Name: "ssh",
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: releaseName + "-kubernetes-zfs-provisioner",
DefaultMode: getIntPointer(0600),
},
},
})
}

func getIntPointer(mode int) *int32 {
i := *((*int32)(unsafe.Pointer(&mode)))
return &i
}
10 changes: 10 additions & 0 deletions kubernetes-zfs-provisioner/test/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module test

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
)
Loading

0 comments on commit c97d9bb

Please sign in to comment.