diff --git a/stable/hackmd/.helmignore b/stable/hackmd/.helmignore new file mode 100644 index 0000000000..f0c1319444 --- /dev/null +++ b/stable/hackmd/.helmignore @@ -0,0 +1,21 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/stable/hackmd/Chart.yaml b/stable/hackmd/Chart.yaml new file mode 100644 index 0000000000..132fd8c305 --- /dev/null +++ b/stable/hackmd/Chart.yaml @@ -0,0 +1,21 @@ +name: hackmd +apiVersion: v1 +version: "0.1.0" +appVersion: "1.0.1" +description: Realtime collaborative markdown notes on all platforms. +icon: https://hackmd.io/favicon.png +keywords: +- hackmd +- cms +- markdown +- http +- web +- application +home: https://hackmd.io +sources: +- https://github.com/hackmdio/hackmd +- https://github.com/hackmdio/docker-hackmd +maintainers: +- name: yuanying + email: yuanying@fraction.jp +engine: gotpl diff --git a/stable/hackmd/README.md b/stable/hackmd/README.md new file mode 100644 index 0000000000..9fbcaa404d --- /dev/null +++ b/stable/hackmd/README.md @@ -0,0 +1,53 @@ +# HackMD + +[HackMD](https://hackmd.io) is a realtime, multiplatform collaborative markdown note editor. + +## Introduction + +This chart bootstraps a [HackMD](https://github.com/hackmdio/docker-hackmd) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +It also packages the [PostgreSQL](https://github.com/kubernetes/charts/tree/master/stable/postgresql) which is required for bootstrapping a PostgreSQL deployment for the database requirements of the HackMD application. + +## Prerequisites + +- Kubernetes 1.8+ +- PV provisioner support in the underlying infrastructure + +## Install + +```console +$ git clone https://github.com/hackmdio/docker-hackmd.git +$ helm install stable/hackmd +``` + +## Configuration + +The following configurations may be set. It is recommended to use values.yaml for overwriting the hackmd config. + +Parameter | Description | Default +--------- | ----------- | ------- +`replicaCount` | How many replicas to run. | 1 +`image.repository` | Name of the image to run, without the tag. | [hackmdio/hackmd](https://github.com/hackmdio/docker-hackmd) +`image.tag` | The image tag to use. | 1.0.1-ce +`image.pullPolicy` | The kubernetes image pull policy. | IfNotPresent +`service.name` | The kubernetes service name to use. | hackmd +`service.type` | The kubernetes service type to use. | ClusterIP +`service.port` | Service port. | 3000 +`ingress.enabled` | If true, Ingress will be created | `false` +`ingress.annotations` | Ingress annotations | `[]` +`ingress.hosts` | Ingress hostnames | `[]` +`ingress.tls` | Ingress TLS configuration (YAML) | `[]` +`resources` | Resource requests and limits | `{}` +`persistence.enabled` | If true, Persistent Volume Claim will be created | `true` +`persistence.accessModes` | Persistent Volume access modes | `[ReadWriteOnce]` +`persistence.annotations` | Persistent Volume annotations | `{}` +`persistence.existingClaim` | Persistent Volume existing claim name | `""` +`persistence.size` | Persistent Volume size | `2Gi` +`persistence.storageClass` | Persistent Volume Storage Class | `unset` +`extraVars` | Hackmd's extra environment variables | `[]` +`postgresql.install` | Enable PostgreSQL as a chart dependency | `true` +`postgresql.imageTag` | The image tag for PostgreSQL | `9.6.2` +`postgresql.postgresUser` | PostgreSQL User to create | `hackmd` +`postgresql.postgresHost` | PostgreSQL host (if `postgresql.install == false`) | `nil` +`postgresql.postgresPassword` | PostgreSQL Password for the new user | random 10 characters +`postgresql.postgresDatabase` | PostgreSQL Database to create | `hackmd` diff --git a/stable/hackmd/requirements.lock b/stable/hackmd/requirements.lock new file mode 100644 index 0000000000..7e23131732 --- /dev/null +++ b/stable/hackmd/requirements.lock @@ -0,0 +1,6 @@ +dependencies: +- name: postgresql + repository: https://kubernetes-charts.storage.googleapis.com/ + version: 0.8.4 +digest: sha256:4a649476a4d3dd2e893b024b8149333a2ae60ea7bbaae08b2033984e82f4767e +generated: 2018-02-07T11:31:32.139844+09:00 diff --git a/stable/hackmd/requirements.yaml b/stable/hackmd/requirements.yaml new file mode 100644 index 0000000000..8f79653693 --- /dev/null +++ b/stable/hackmd/requirements.yaml @@ -0,0 +1,5 @@ +dependencies: +- name: postgresql + version: 0.8.4 + repository: https://kubernetes-charts.storage.googleapis.com/ + condition: postgresql.install diff --git a/stable/hackmd/templates/NOTES.txt b/stable/hackmd/templates/NOTES.txt new file mode 100644 index 0000000000..035a0fb4e9 --- /dev/null +++ b/stable/hackmd/templates/NOTES.txt @@ -0,0 +1,19 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "hackmd.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "hackmd.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "hackmd.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "hackmd.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/stable/hackmd/templates/_helpers.tpl b/stable/hackmd/templates/_helpers.tpl new file mode 100644 index 0000000000..6d15f460b4 --- /dev/null +++ b/stable/hackmd/templates/_helpers.tpl @@ -0,0 +1,52 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "hackmd.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 "hackmd.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 "hackmd.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified postgresql name. +We truncate at 24 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "hackmd.postgresql.fullname" -}} +{{- $name := default "postgresql" .Values.postgresql.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Determine database host based on use of postgresql dependency. +*/}} +{{- define "hackmd.database.host" -}} +{{- if .Values.postgresql.install -}} +{{- template "hackmd.postgresql.fullname" . -}} +{{- else -}} +{{- .Values.postgresql.postgresHost | quote -}} +{{- end -}} +{{- end -}} diff --git a/stable/hackmd/templates/deployment.yaml b/stable/hackmd/templates/deployment.yaml new file mode 100644 index 0000000000..ac3046e57d --- /dev/null +++ b/stable/hackmd/templates/deployment.yaml @@ -0,0 +1,79 @@ +apiVersion: apps/v1beta2 +kind: Deployment +metadata: + name: {{ template "hackmd.fullname" . }} + labels: + app: {{ template "hackmd.name" . }} + chart: {{ template "hackmd.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ template "hackmd.name" . }} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ template "hackmd.name" . }} + release: {{ .Release.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 3000 + protocol: TCP + livenessProbe: + httpGet: + path: /status + port: 3000 + initialDelaySeconds: 120 + readinessProbe: + httpGet: + path: /status + port: 3000 + initialDelaySeconds: 30 + env: + - name: HMD_DB_PASSWORD + {{- if .Values.postgresql.install }} + valueFrom: + secretKeyRef: + name: {{ template "hackmd.postgresql.fullname" . }} + key: postgres-password + {{- else }} + value: {{ .Values.postgresql.postgresPassword }} + {{- end }} + - name: HMD_DB_URL + value: postgres://{{ .Values.postgresql.postgresUser }}:$(HMD_DB_PASSWORD)@{{ template "hackmd.database.host" . }}:5432/{{ .Values.postgresql.postgresDatabase }} + {{- if .Values.extraVars }} +{{ toYaml .Values.extraVars | indent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: "/hackmd/public/uploads" + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + volumes: + - name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{- else }}{{ template "hackmd.fullname" . }}{{- end }} + {{- else }} + emptyDir: {} + {{- end }} diff --git a/stable/hackmd/templates/ingress.yaml b/stable/hackmd/templates/ingress.yaml new file mode 100644 index 0000000000..c721c52c99 --- /dev/null +++ b/stable/hackmd/templates/ingress.yaml @@ -0,0 +1,39 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "hackmd.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "hackmd.name" . }} + chart: {{ template "hackmd.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/stable/hackmd/templates/pvc.yaml b/stable/hackmd/templates/pvc.yaml new file mode 100644 index 0000000000..bde6db42ac --- /dev/null +++ b/stable/hackmd/templates/pvc.yaml @@ -0,0 +1,28 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "hackmd.fullname" . }} + labels: + app: {{ template "hackmd.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + annotations: + {{- if .Values.persistence.annotations }} +{{ toYaml .Values.persistence.annotations | indent 4 }} + {{- end }} +spec: + accessModes: +{{ toYaml .Values.persistence.accessModes | indent 4 }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} +{{- if .Values.persistence.storageClass }} +{{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" +{{- end }} +{{- end }} +{{- end -}} diff --git a/stable/hackmd/templates/service.yaml b/stable/hackmd/templates/service.yaml new file mode 100644 index 0000000000..50d7e94a9f --- /dev/null +++ b/stable/hackmd/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "hackmd.fullname" . }} + labels: + app: {{ template "hackmd.name" . }} + chart: {{ template "hackmd.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app: {{ template "hackmd.name" . }} + release: {{ .Release.Name }} diff --git a/stable/hackmd/values.yaml b/stable/hackmd/values.yaml new file mode 100644 index 0000000000..60a8b0400a --- /dev/null +++ b/stable/hackmd/values.yaml @@ -0,0 +1,84 @@ +# Default values for hackmd. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: hackmdio/hackmd + tag: 1.0.1-ce-alpine + pullPolicy: IfNotPresent + +service: + name: hackmd + type: ClusterIP + port: 3000 + +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + path: / + hosts: + - chart-example.local + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +persistence: + enabled: true + ## hackmd data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + annotations: {} + existingClaim: "" + size: 2Gi + ## A manually managed Persistent Volume and Claim + ## Requires persistence.enabled: true + ## If defined, PVC must be created manually before volume will be bound + # existingClaim: + + ## database data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + +extraVars: [] + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +## Configuration values for the postgresql dependency. +## ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md +## +postgresql: + install: true + imageTag: "9.6.2" + postgresUser: "hackmd" + postgresDatabase: "hackmd" + ## Default: random 10 character string + # postgresPassword: