Skip to content

Commit

Permalink
Add Ghost helm chart
Browse files Browse the repository at this point in the history
  • Loading branch information
marmila committed Jan 3, 2024
1 parent f4ba486 commit 0b31475
Show file tree
Hide file tree
Showing 19 changed files with 2,606 additions and 0 deletions.
21 changes: 21 additions & 0 deletions argocd/system/ghost/.helmignore
Original file line number Diff line number Diff line change
@@ -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
43 changes: 43 additions & 0 deletions argocd/system/ghost/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright VMware, Inc.
# SPDX-License-Identifier: APACHE-2.0

annotations:
category: CMS
licenses: Apache-2.0
images: |
- name: ghost
image: docker.io/bitnami/ghost:5.75.2-debian-11-r0
- name: os-shell
image: docker.io/bitnami/os-shell:11-debian-11-r92
apiVersion: v2
appVersion: 5.75.2
dependencies:
- condition: mysql.enabled
name: mysql
repository: oci://registry-1.docker.io/bitnamicharts
tags:
- ghost-database
version: 9.x.x
- name: common
repository: oci://registry-1.docker.io/bitnamicharts
tags:
- bitnami-common
version: 2.x.x
description: Ghost is an open source publishing platform designed to create blogs, magazines, and news sites. It includes a simple markdown editor with preview, theming, and SEO built-in to simplify editing.
home: https://bitnami.com
icon: https://bitnami.com/assets/stacks/ghost/img/ghost-stack-220x234.png
keywords:
- ghost
- blog
- http
- web
- application
- nodejs
- javascript
maintainers:
- name: VMware, Inc.
url: https://github.com/bitnami/charts
name: ghost
sources:
- https://github.com/bitnami/charts/tree/main/bitnami/ghost
version: 19.6.16
550 changes: 550 additions & 0 deletions argocd/system/ghost/README.md

Large diffs are not rendered by default.

149 changes: 149 additions & 0 deletions argocd/system/ghost/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
CHART NAME: {{ .Chart.Name }}
CHART VERSION: {{ .Chart.Version }}
APP VERSION: {{ .Chart.AppVersion }}

** Please be patient while the chart is being deployed **

{{- $ghostPasswordKey := ( include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "ghost-password") ) -}}
{{- $ghostSecretName := (include "common.names.fullname" .) -}}
{{- $databaseSecretName := include "ghost.databaseSecretName" . -}}

{{- if or .Values.mysql.enabled .Values.externalDatabase.host -}}

{{- if empty (include "ghost.host" .) -}}
###############################################################################
### ERROR: You did not provide an external host in your 'helm install' call ###
###############################################################################

This deployment will be incomplete until you configure Ghost with a resolvable
host. To configure Ghost with the URL of your service:

1. Get the Ghost URL by running:

{{- if contains "NodePort" .Values.service.type }}

export APP_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")

{{- else if contains "LoadBalancer" .Values.service.type }}

NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}'

export APP_HOST=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")

{{- end }}

{{ include "common.utils.secret.getvalue" (dict "secret" $ghostSecretName "field" $ghostPasswordKey "context" $) }}
{{ include "common.utils.secret.getvalue" (dict "secret" $databaseSecretName "field" "mysql-root-password" "context" $) }}
{{ include "common.utils.secret.getvalue" (dict "secret" $databaseSecretName "field" "mysql-password" "context" $) }}

2. Complete your Ghost deployment by running:

{{- if .Values.mysql.enabled }}

helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/{{ .Chart.Name }} \
--set service.type={{ .Values.service.type }},ghostHost=$APP_HOST,ghostPassword=$GHOST_PASSWORD,mysql.auth.rootPassword=$MYSQL_ROOT_PASSWORD,mysql.auth.password=$MYSQL_PASSWORD{{- if .Values.global }}{{- if .Values.global.imagePullSecrets }},global.imagePullSecrets={{ .Values.global.imagePullSecrets }}{{- end }}{{- end }}

{{- else }}

## PLEASE UPDATE THE EXTERNAL DATABASE CONNECTION PARAMETERS IN THE FOLLOWING COMMAND AS NEEDED ##

helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/{{ .Chart.Name }} \
--set service.type={{ .Values.service.type }},ghostHost=$APP_HOST,ghostPassword=$APP_PASSWORD,{{- if contains "NodePort" .Values.service.type }}service.nodePort=$APP_PORT,{{- end }}mysql.enabled=false{{- if not (empty .Values.externalDatabase.host) }},externalDatabase.host={{ .Values.externalDatabase.host }}{{- end }}{{- if not (empty .Values.externalDatabase.user) }},externalDatabase.user={{ .Values.externalDatabase.user }}{{- end }}{{- if not (empty .Values.externalDatabase.password) }},externalDatabase.password={{ .Values.externalDatabase.password }}{{- end }}{{- if not (empty .Values.externalDatabase.database) }},externalDatabase.database={{ .Values.externalDatabase.database }}{{- end }}

{{- end }}

{{- else -}}

{{- if .Values.ingress.enabled }}

1. Get the Ghost URL and associate its hostname to your cluster external IP:

export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters
echo "Ghost URL: http{{ if .Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.hostname }}"
echo "$CLUSTER_IP {{ .Values.ingress.hostname }}" | sudo tee -a /etc/hosts

{{- else }}

1. Get the Ghost URL by running:

{{- if eq .Values.service.type "ClusterIP" }}

echo Blog URL : http://127.0.0.1:{{ default "80" (coalesce .Values.service.ports.http .Values.service.port) }}{{ .Values.ghostPath }}
echo Admin URL : http://127.0.0.1:{{ default "80" (coalesce .Values.service.ports.http .Values.service.port) }}{{ default "/" .Values.ghostPath }}ghost
kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "common.names.fullname" . }} {{ default "80" (coalesce .Values.service.ports.http .Values.service.port) }}:{{ default "80" (coalesce .Values.service.ports.http .Values.service.port) }}

{{- else if eq .Values.service.type "NodePort" }}

export APP_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
export APP_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }})

echo Blog URL : http://$APP_HOST:$APP_PORT{{ .Values.ghostPath }}
echo Admin URL : http://$APP_HOST:$APP_PORT{{ default "/" .Values.ghostPath }}ghost

{{- else }}

echo Blog URL : http://{{ include "ghost.host" . }}
echo Admin URL : http://{{ include "ghost.host" . }}ghost

{{- end }}
{{- end }}

2. Get your Ghost login credentials by running:

echo Email: {{ .Values.ghostEmail }}
echo Password: $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} -o jsonpath="{.data.{{- $ghostPasswordKey -}}}" | base64 -d)

{{- end }}

{{- else -}}

########################################################################################
### ERROR: You did not provide an external database host in your 'helm install' call ###
########################################################################################

This deployment will be incomplete until you configure Ghost with a resolvable database
host. To configure Ghost to use and external database host:

1. Complete your Ghost deployment by running:

{{- if contains "NodePort" .Values.service.type }}

export APP_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")

{{- else if contains "LoadBalancer" .Values.service.type }}

NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}'

export APP_HOST=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")

{{- else }}

export APP_HOST=127.0.0.1

{{- end }}

{{ include "common.utils.secret.getvalue" (dict "secret" $ghostSecretName "field" $ghostPasswordKey "context" $) }}

## PLEASE UPDATE THE EXTERNAL DATABASE CONNECTION PARAMETERS IN THE FOLLOWING COMMAND AS NEEDED ##

helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} oci://registry-1.docker.io/bitnamicharts/{{ .Chart.Name }} \
--set ghostPassword=$APP_PASSWORD,ghostHost=$APP_HOST,service.type={{ .Values.service.type }},mysql.enabled=false{{- if not (empty .Values.externalDatabase.user) }},externalDatabase.user={{ .Values.externalDatabase.user }}{{- end }}{{- if not (empty .Values.externalDatabase.password) }},externalDatabase.password={{ .Values.externalDatabase.password }}{{- end }}{{- if not (empty .Values.externalDatabase.database) }},externalDatabase.database={{ .Values.externalDatabase.database }}{{- end }},externalDatabase.host=YOUR_EXTERNAL_DATABASE_HOST
{{- end }}

{{ include "common.warnings.rollingTag" .Values.image }}

{{- include "ghost.validateValues" . }}
{{- include "common.warnings.rollingTag" .Values.image }}
{{- $passwordValidationErrors := list -}}
{{- if not .Values.existingSecret -}}
{{- $requiredGhostPassword := dict "valueKey" "ghostPassword" "secret" $ghostSecretName "field" "ghost-password" "context" $ -}}
{{- $requiredGhostPasswordError := include "common.validations.values.single.empty" $requiredGhostPassword -}}
{{- $passwordValidationErrors = append $passwordValidationErrors $requiredGhostPasswordError -}}
{{- end -}}
{{- if .Values.mysql.enabled }}
{{- $mysqlPasswordValidationErrors := include "common.validations.values.mysql.passwords" (dict "secret" $databaseSecretName "subchart" true "context" $) -}}
{{- $passwordValidationErrors = append $passwordValidationErrors $mysqlPasswordValidationErrors -}}
{{- end }}
{{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $) -}}
164 changes: 164 additions & 0 deletions argocd/system/ghost/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
{{/*
Copyright VMware, Inc.
SPDX-License-Identifier: APACHE-2.0
*/}}

{{/* vim: set filetype=mustache: */}}

{{/*
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).
*/}}
{{- define "ghost.mysql.fullname" -}}
{{- include "common.names.dependency.fullname" (dict "chartName" "mysql" "chartValues" .Values.mysql "context" $) -}}
{{- end -}}

{{/*
Return the proper Ghost image name
*/}}
{{- define "ghost.image" -}}
{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }}
{{- end -}}

{{/*
Return the proper image name to change the volume permissions
*/}}
{{- define "ghost.volumePermissions.image" -}}
{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }}
{{- end -}}

{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "ghost.imagePullSecrets" -}}
{{ include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "global" .Values.global) }}
{{- end -}}

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

{{/*
Get the user defined LoadBalancerIP for this release.
Note, returns 127.0.0.1 if using ClusterIP.
*/}}
{{- define "ghost.serviceIP" -}}
{{- if eq .Values.service.type "ClusterIP" -}}
127.0.0.1
{{- else -}}
{{- .Values.service.loadBalancerIP | default "" -}}
{{- end -}}
{{- end -}}

{{/*
Gets the host to be used for this application.
If not using ClusterIP, or if a host or LoadBalancerIP is not defined, the value will be empty.
*/}}
{{- define "ghost.host" -}}
{{- if .Values.ingress.enabled }}
{{- printf "%s%s" .Values.ingress.hostname .Values.ingress.path | default "" -}}
{{- else if .Values.ghostHost -}}
{{- printf "%s%s" .Values.ghostHost .Values.ghostPath | default "" -}}
{{- else -}}
{{- include "ghost.serviceIP" . -}}
{{- end -}}
{{- end -}}

{{/*
Return the MySQL Hostname
*/}}
{{- define "ghost.databaseHost" -}}
{{- if .Values.mysql.enabled }}
{{- if eq .Values.mysql.architecture "replication" }}
{{- printf "%s-%s" (include "ghost.mysql.fullname" .) "primary" | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s" (include "ghost.mysql.fullname" .) -}}
{{- end -}}
{{- else -}}
{{- printf "%s" .Values.externalDatabase.host -}}
{{- end -}}
{{- end -}}

{{/*
Return the MySQL Port
*/}}
{{- define "ghost.databasePort" -}}
{{- if .Values.mysql.enabled }}
{{- printf "3306" -}}
{{- else -}}
{{- printf "%d" (.Values.externalDatabase.port | int ) -}}
{{- end -}}
{{- end -}}

{{/*
Return the MySQL Database Name
*/}}
{{- define "ghost.databaseName" -}}
{{- if .Values.mysql.enabled }}
{{- printf "%s" .Values.mysql.auth.database -}}
{{- else -}}
{{- printf "%s" .Values.externalDatabase.database -}}
{{- end -}}
{{- end -}}

{{/*
Return the MySQL User
*/}}
{{- define "ghost.databaseUser" -}}
{{- if .Values.mysql.enabled }}
{{- printf "%s" .Values.mysql.auth.username -}}
{{- else -}}
{{- printf "%s" .Values.externalDatabase.user -}}
{{- end -}}
{{- end -}}

{{/*
Return the MySQL Secret Name
*/}}
{{- define "ghost.databaseSecretName" -}}
{{- if .Values.mysql.enabled }}
{{- if .Values.mysql.auth.existingSecret -}}
{{- printf "%s" .Values.mysql.auth.existingSecret -}}
{{- else -}}
{{- printf "%s" (include "ghost.mysql.fullname" .) -}}
{{- end -}}
{{- else if .Values.externalDatabase.existingSecret -}}
{{- printf "%s" .Values.externalDatabase.existingSecret -}}
{{- else -}}
{{- printf "%s-externaldb" (include "common.names.fullname" .) -}}
{{- end -}}
{{- end -}}

{{/*
Compile all warnings into a single message.
*/}}
{{- define "ghost.validateValues" -}}
{{- $messages := list -}}
{{- $messages := append $messages (include "ghost.validateValues.database" .) -}}
{{- $messages := without $messages "" -}}
{{- $message := join "\n" $messages -}}
{{- if $message -}}
{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}}
{{- end -}}
{{- end -}}

{{/* Validate values of Ghost - Database */}}
{{- define "ghost.validateValues.database" -}}
{{- if and (not .Values.mysql.enabled) (or (empty .Values.externalDatabase.host) (empty .Values.externalDatabase.port) (empty .Values.externalDatabase.database)) -}}
ghost: database
You disable the MySQL installation but you did not provide the required parameters
to use an external database. To use an external database, please ensure you provide
(at least) the following values:

externalDatabase.host=DB_SERVER_HOST
externalDatabase.database=DB_NAME
externalDatabase.port=DB_SERVER_PORT
{{- end -}}
{{- end -}}
Loading

0 comments on commit 0b31475

Please sign in to comment.