Skip to content

Commit

Permalink
feat(helm-chart): add a Helm Chart to deploy Nx Cloud CE
Browse files Browse the repository at this point in the history
  • Loading branch information
clementguillot committed Apr 9, 2024
1 parent 468f8e9 commit fea40a2
Show file tree
Hide file tree
Showing 13 changed files with 726 additions and 3 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ Since Nx Cloud is a proprietary software from Narwhal Technologies Inc., it is h

## Project structure

| Application/library | Summary |
|------------------------------|---------------------------------------------------------------|
| [`apps/server`](apps/server) | Backend of Nx Cloud CE, handles requests from Nx Cloud client |
| Application/library | Summary |
|--------------------------------------|---------------------------------------------------------------|
| [`apps/helm-chart`](apps/helm-chart) | Helm Chart to deploy Nx Cloud CE on Kubernetes |
| [`apps/server`](apps/server) | Backend of Nx Cloud CE, handles requests from Nx Cloud client |

## External Code and Licenses

Expand Down
2 changes: 2 additions & 0 deletions apps/helm-chart/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
src/charts
*.tgz
34 changes: 34 additions & 0 deletions apps/helm-chart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# apps/helm-chart

This directory contains the [Helm](https://helm.sh/) chart for deploying Nx Cloud CE on a [Kubernetes](https://kubernetes.io/) cluster.

As an all-in-one package, this chart includes Bitnami's Helm Charts for MongoDB (DB) and NGINX (Reverse Proxy).

Everything is already configured, but you can fine-tune settings and use an external MongoDB connection (e.g. from MongoDB Community Operator).

## Prerequisites

- Kubernetes 1.16+
- Helm 3+

## Packaging the Helm Chart

The chart can be packaged using:

```shell script
nx build apps/helm-chart
```

It will download dependencies and create a tgz package at `apps/helm-chart/dist`.

## Install from source using Helm

For development purpose, you can install this chart using `helm`:

```shell script
helm install [release name] apps/helm-chart/src [-n [namespace]] [--set... | -f values.yaml]
```
## Configuration
Refer to [`values.yaml`](./src/values.yaml) for the exhaustive list of settings.
51 changes: 51 additions & 0 deletions apps/helm-chart/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"name": "apps/helm-chart",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"sourceRoot": "apps/helm-chart/src",
"targets": {
"dependency-build": {
"executor": "nx:run-commands",
"options": {
"cwd": "apps/helm-chart",
"commands": [
"helm repo add bitnami https://charts.bitnami.com/bitnami",
"helm dependency build src"
],
"parallel": false
},
"outputs": [
"{projectRoot}/src/charts"
]
},
"build": {
"dependsOn": ["dependency-build"],
"executor": "nx:run-commands",
"options": {
"cwd": "apps/helm-chart",
"commands": [
"mkdir -p dist",
"helm dependency build src",
"helm package src --destination dist"
],
"parallel": false
},
"outputs": [
"{projectRoot}/dist"
]
},
"lint": {
"dependsOn": ["dependency-build"],
"executor": "nx:run-commands",
"options": {
"cwd": "apps/helm-chart",
"commands": [
"helm dependency build src",
"helm lint src"
],
"parallel": false
}
}
},
"tags": []
}
22 changes: 22 additions & 0 deletions apps/helm-chart/src/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 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
.vscode/
9 changes: 9 additions & 0 deletions apps/helm-chart/src/Chart.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dependencies:
- name: mongodb
repository: https://charts.bitnami.com/bitnami
version: 15.1.3
- name: nginx
repository: https://charts.bitnami.com/bitnami
version: 16.0.1
digest: sha256:47c0810e833b112638436a3aef8eb3a46feda457d4e6a39fce82f5babea2adc7
generated: "2024-04-07T17:52:28.82188561+02:00"
23 changes: 23 additions & 0 deletions apps/helm-chart/src/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v2
name: nx-cloud-ce
description: Nx Cloud Community Edition Helm Chart
type: application
version: "0.0.1"
appVersion: "0.0.1"
keywords:
- nx-cloud-ce
home: https://github.com/clementguillot/nx-cloud-ce
maintainers:
- name: clementguillot
email: [email protected]
sources:
- https://github.com/clementguillot/nx-cloud-ce
dependencies:
- name: mongodb
version: 15.1.3
repository: https://charts.bitnami.com/bitnami
condition: mongodb.enabled
- name: nginx
version: 16.0.1
repository: https://charts.bitnami.com/bitnami
condition: nginx.enabled
147 changes: 147 additions & 0 deletions apps/helm-chart/src/templates/_common.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "nx-cloud-ce.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 "nx-cloud-ce.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 "nx-cloud-ce.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create Nx Cloud CE app version
*/}}
{{- define "nx-cloud-ce.defaultTag" -}}
{{- default .Chart.AppVersion .Values.global.image.tag }}
{{- end -}}

{{/*
Return valid version label
*/}}
{{- define "nx-cloud-ce.versionLabelValue" -}}
{{ regexReplaceAll "[^-A-Za-z0-9_.]" (include "nx-cloud-ce.defaultTag" .) "-" | trunc 63 | trimAll "-" | trimAll "_" | trimAll "." | quote }}
{{- end -}}

{{/*
Common labels
*/}}
{{- define "nx-cloud-ce.labels" -}}
helm.sh/chart: {{ include "nx-cloud-ce.chart" .context }}
{{ include "nx-cloud-ce.selectorLabels" (dict "context" .context "component" .component "name" .name) }}
app.kubernetes.io/managed-by: {{ .context.Release.Service }}
app.kubernetes.io/part-of: nx-cloud-ce
app.kubernetes.io/version: {{ include "nx-cloud-ce.versionLabelValue" .context }}
{{- with .context.Values.global.additionalLabels }}
{{ toYaml . }}
{{- end }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "nx-cloud-ce.selectorLabels" -}}
{{- if .name -}}
app.kubernetes.io/name: {{ include "nx-cloud-ce.name" .context }}-{{ .name }}
{{ end -}}
app.kubernetes.io/instance: {{ .context.Release.Name }}
{{- if .component }}
app.kubernetes.io/component: {{ .component }}
{{- end }}
{{- end }}

{{/*
Common affinity definition
Pod affinity
- Soft prefers different nodes
- Hard requires different nodes and prefers different availibility zones
Node affinity
- Soft prefers given user expressions
- Hard requires given user expressions
*/}}
{{- define "nx-cloud-ce.affinity" -}}
{{- with .component.affinity -}}
{{- toYaml . -}}
{{- else -}}
{{- $preset := .context.Values.global.affinity -}}
{{- if (eq $preset.podAntiAffinity "soft") }}
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ include "nx-cloud-ce.name" .context }}-{{ .component.name }}
topologyKey: kubernetes.io/hostname
{{- else if (eq $preset.podAntiAffinity "hard") }}
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ include "nx-cloud-ce.name" .context }}-{{ .component.name }}
topologyKey: topology.kubernetes.io/zone
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: {{ include "nx-cloud-ce.name" .context }}-{{ .component.name }}
topologyKey: kubernetes.io/hostname
{{- end }}
{{- with $preset.nodeAffinity.matchExpressions }}
{{- if (eq $preset.nodeAffinity.type "soft") }}
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
{{- toYaml . | nindent 6 }}
{{- else if (eq $preset.nodeAffinity.type "hard") }}
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Common deployment strategy definition
- Recreate don't have additional fields, we need to remove them if added by the mergeOverwrite
*/}}
{{- define "nx-cloud-ce.strategy" -}}
{{- $preset := . -}}
{{- if (eq (toString $preset.type) "Recreate") }}
type: Recreate
{{- else if (eq (toString $preset.type) "RollingUpdate") }}
type: RollingUpdate
{{- with $preset.rollingUpdate }}
rollingUpdate:
{{- toYaml . | nindent 2 }}
{{- end }}
{{- end }}
{{- end -}}
33 changes: 33 additions & 0 deletions apps/helm-chart/src/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Create server name and version as used by the chart label.
Truncated at 52 chars because Deployment label 'server-revision-hash' is limited
to 63 chars and it includes 10 chars of hash and a separating '-'.
*/}}
{{- define "nx-cloud-ce.server.fullname" -}}
{{- printf "%s-%s" (include "nx-cloud-ce.fullname" .) .Values.server.name | trunc 52 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create the default port of the server.
*/}}
{{- define "nx-cloud-ce.server.port" -}}
{{- default "80" .Values.server.service.servicePortHttp -}}
{{- end -}}

{{/*
Create the MongoDB connection string of the server.
*/}}
{{- define "nx-cloud-ce.server.database.connection-string" -}}
{{- if .Values.mongodb.enabled }}
valueFrom:
secretKeyRef:
name: {{ template "nx-cloud-ce.name" . }}-mongodb-svcbind-0
key: uri
{{- else }}
valueFrom:
secretKeyRef:
name: {{ .Values.server.database.connectionStringSecretName | quote }}
key: {{ .Values.server.database.connectionStringSecretKeyRef | quote }}
{{- end -}}
{{- end -}}
34 changes: 34 additions & 0 deletions apps/helm-chart/src/templates/nginx/config-map.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
apiVersion: v1
kind: ConfigMap

metadata:
name: {{ template "nx-cloud-ce.fullname" . }}-nginx
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "nx-cloud-ce.labels" (dict "context" . "component" .Values.server.name "name" "nginx") | nindent 4 }}

data:
nginx-server-block.conf: |-
upstream server {
server {{ template "nx-cloud-ce.server.fullname" . }}:{{ template "nx-cloud-ce.server.port". }};
}
server {
listen {{ .Values.nginx.containerPorts.http }};
location = / {
auth_basic off;
}
{{- if .Values.nginx.extraServerBlockConfiguration }}
{{ .Values.nginx.extraServerBlockConfiguration | nindent 6 }}
{{- end }}
location ^~ /nx-cloud/private {
return 404;
}
location ^~ /nx-cloud {
proxy_pass http://server;
}
}
Loading

0 comments on commit fea40a2

Please sign in to comment.