nats chart provisoning

This commit is contained in:
plm 2024-11-29 10:30:47 +01:00
parent e86898eb44
commit 18f7a91bf3
55 changed files with 2821 additions and 4 deletions

View File

@ -5,13 +5,17 @@ type: application
version: 0.0.1
appVersion: "0.0.1"
# TODO: ldap, mongo, mongo-express, nats, ory hydra, keto, traefik
# TODO: ldap, mongo, mongo-express, nats, ory hydra, keto
dependencies:
- name: openldap
version: "2.0.4"
- name: openldap-stack-ha
version: "4.3.1"
repository: "https://jp-gouin.github.io/helm-openldap/"
condition: openldap.enabled
condition: openldap-stack-ha.enabled
- name: traefik
version: "33.0.0"
repository: "https://helm.traefik.io/traefik"
condition: traefik.enabled
- name: nats
version: "1.2.6"
repository: "https://nats-io.github.io/k8s/helm/charts/"
condition: nats.enabled

View File

@ -0,0 +1,26 @@
# 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/
# template tests
/test

View File

@ -0,0 +1,16 @@
apiVersion: v2
appVersion: 2.10.22
description: A Helm chart for the NATS.io High Speed Cloud Native Distributed Communications
Technology.
home: http://github.com/nats-io/k8s
icon: https://nats.io/img/nats-icon-color.png
keywords:
- nats
- messaging
- cncf
maintainers:
- email: info@nats.io
name: The NATS Authors
url: https://github.com/nats-io
name: nats
version: 1.2.6

View File

@ -0,0 +1,329 @@
# NATS Server
---
[NATS](https://nats.io) is a simple, secure and performant communications system for digital systems, services and devices.
NATS is part of the Cloud Native Computing Foundation ([CNCF](https://cncf.io)).
NATS has over [30 client language implementations](https://nats.io/download/), and its server can run on-premise, in the cloud, at the edge, and even on a Raspberry Pi.
NATS can secure and simplify design and operation of modern distributed systems.
```shell
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
helm upgrade --install nats nats/nats
```
## Upgrade Nodes
- **Upgrading from 0.x**: The `values.yaml` schema changed significantly from 0.x to 1.x. Read [UPGRADING.md](UPGRADING.md) for instructions on upgrading a 0.x release to 1.x.
## Values
There are a handful of explicitly defined options which are documented with comments in the [values.yaml](values.yaml) file.
Everything in the NATS Config or Kubernetes Resources can be overridden by `merge` and `patch`, which is supported for the following values:
| key | type | enabled by default |
|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------|
| `config` | [NATS Config](https://docs.nats.io/running-a-nats-service/configuration) | yes |
| `config.cluster` | [NATS Cluster](https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config) | no |
| `config.cluster.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no |
| `config.jetstream` | [NATS JetStream](https://docs.nats.io/running-a-nats-service/configuration#jetstream) | no |
| `config.jetstream.fileStore.pvc` | [k8s PVC](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core) | yes, when `config.jetstream` is enabled |
| `config.nats.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no |
| `config.leafnodes` | [NATS LeafNodes](https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf) | no |
| `config.leafnodes.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no |
| `config.websocket` | [NATS WebSocket](https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf) | no |
| `config.websocket.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no |
| `config.websocket.ingress` | [k8s Ingress](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io) | no |
| `config.mqtt` | [NATS MQTT](https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config) | no |
| `config.mqtt.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no |
| `config.gateway` | [NATS Gateway](https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block) | no |
| `config.gateway.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no |
| `config.resolver` | [NATS Resolver](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver) | no |
| `config.resolver.pvc` | [k8s PVC](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core) | yes, when `config.resolver` is enabled |
| `container` | nats [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes |
| `reloader` | config reloader [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes |
| `promExporter` | prometheus exporter [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | no |
| `promExporter.podMonitor` | [prometheus PodMonitor](https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor) | no |
| `service` | [k8s Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | yes |
| `statefulSet` | [k8s StatefulSet](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps) | yes |
| `podTemplate` | [k8s PodTemplate](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core) | yes |
| `headlessService` | [k8s Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | yes |
| `configMap` | [k8s ConfigMap](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core) | yes |
| `natsBox.contexts.default` | [NATS Context](https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts) | yes |
| `natsBox.contexts.[name]` | [NATS Context](https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts) | no |
| `natsBox.container` | nats-box [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes |
| `natsBox.deployment` | [k8s Deployment](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps) | yes |
| `natsBox.podTemplate` | [k8s PodTemplate](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core) | yes |
| `natsBox.contextsSecret` | [k8s Secret](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core) | yes |
| `natsBox.contentsSecret` | [k8s Secret](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core) | yes |
### Merge
Merging is performed using the Helm `merge` function. Example - add NATS accounts and container resources:
```yaml
config:
merge:
accounts:
A:
users:
- {user: a, password: a}
B:
users:
- {user: b, password: b}
natsBox:
contexts:
a:
merge: {user: a, password: a}
b:
merge: {user: b, password: b}
defaultContextName: a
```
## Patch
Patching is performed using [JSON Patch](https://jsonpatch.com/). Example - add additional route to end of route list:
```yaml
config:
cluster:
enabled: true
patch:
- op: add
path: /routes/-
value: nats://demo.nats.io:6222
```
## Common Configurations
### JetStream Cluster on 3 separate hosts
```yaml
config:
cluster:
enabled: true
replicas: 3
jetstream:
enabled: true
fileStore:
pvc:
size: 10Gi
podTemplate:
topologySpreadConstraints:
kubernetes.io/hostname:
maxSkew: 1
whenUnsatisfiable: DoNotSchedule
```
### NATS Container Resources
```yaml
container:
env:
# different from k8s units, suffix must be B, KiB, MiB, GiB, or TiB
# should be ~90% of memory limit
GOMEMLIMIT: 7GiB
merge:
# recommended limit is at least 2 CPU cores and 8Gi Memory for production JetStream clusters
resources:
requests:
cpu: "2"
memory: 8Gi
limits:
cpu: "2"
memory: 8Gi
```
### Specify Image Version
```yaml
container:
image:
tag: x.y.z-alpine
```
### Operator Mode with NATS Resolver
Run `nsc generate config --nats-resolver` and replace the `OPERATOR_JWT`, `SYS_ACCOUNT_ID`, and `SYS_ACCOUNT_JWT` with your values.
Make sure that you do not include the trailing `,` in the `SYS_ACCOUNT_JWT`.
```
config:
resolver:
enabled: true
merge:
type: full
interval: 2m
timeout: 1.9s
merge:
operator: OPERATOR_JWT
system_account: SYS_ACCOUNT_ID
resolver_preload:
SYS_ACCOUNT_ID: SYS_ACCOUNT_JWT
```
## Accessing NATS
The chart contains 2 services by default, `service` and `headlessService`.
### `service`
The `service` is intended to be accessed by NATS Clients. It is a `ClusterIP` service by default, however it can easily be changed to a different service type.
The `nats`, `websocket`, `leafnodes`, and `mqtt` ports will be exposed through this service by default if they are enabled.
Example: change this service type to a `LoadBalancer`:
```yaml
service:
merge:
spec:
type: LoadBalancer
```
### `headlessService`
The `headlessService` is used for NATS Servers in the Stateful Set to discover one another. It is primarily intended to be used for Cluster Route connections.
### TLS Considerations
The TLS Certificate used for Client Connections should have a SAN covering DNS Name that clients access the `service` at.
The TLS Certificate used for Cluster Route Connections should have a SAN covering the DNS Name that routes access each other on the `headlessService` at. This is `*.<headless-service-name>` by default.
## Advanced Features
### Templating Values
Anything in `values.yaml` can be templated:
- maps matching the following syntax will be templated and parsed as YAML:
```yaml
$tplYaml: |
yaml template
```
- maps matching the follow syntax will be templated, parsed as YAML, and spread into the parent map/slice
```yaml
$tplYamlSpread: |
yaml template
```
Example - change service name:
```yaml
service:
name:
$tplYaml: >-
{{ include "nats.fullname" . }}-svc
```
### NATS Config Units and Variables
NATS configuration extends JSON, and can represent Units and Variables. They must be wrapped in `<< >>` in order to template correctly. Example:
```yaml
config:
merge:
authorization:
# variable
token: << $TOKEN >>
# units
max_payload: << 2MB >>
```
templates to the `nats.conf`:
```
{
"authorization": {
"token": $TOKEN
},
"max_payload": 2MB,
"port": 4222,
...
}
```
### NATS Config Includes
Any NATS Config key ending in `$include` will be replaced with an include directive. Included files should be in paths relative to `/etc/nats-config`. Multiple `$include` keys are supported by using a prefix, and will be sorted alphabetically. Example:
```yaml
config:
merge:
00$include: auth.conf
01$include: params.conf
configMap:
merge:
data:
auth.conf: |
accounts: {
A: {
users: [
{user: a, password: a}
]
},
B: {
users: [
{user: b, password: b}
]
},
}
params.conf: |
max_payload: 2MB
```
templates to the `nats.conf`:
```
include auth.conf;
"port": 4222,
...
include params.conf;
```
### Extra Resources
Enables adding additional arbitrary resources. Example - expose WebSocket via VirtualService in Istio:
```yaml
config:
websocket:
enabled: true
extraResources:
- apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
namespace:
$tplYamlSpread: >
{{ include "nats.metadataNamespace" $ }}
name:
$tplYaml: >
{{ include "nats.fullname" $ | quote }}
labels:
$tplYaml: |
{{ include "nats.labels" $ }}
spec:
hosts:
- demo.nats.io
gateways:
- my-gateway
http:
- name: default
match:
- name: root
uri:
exact: /
route:
- destination:
host:
$tplYaml: >
{{ .Values.service.name | quote }}
port:
number:
$tplYaml: >
{{ .Values.config.websocket.port }}
```

View File

@ -0,0 +1,155 @@
# Upgrading from 0.x to 1.x
Instructions for upgrading an existing `nats` 0.x release to 1.x.
## Rename Immutable Fields
There are a number of immutable fields in the NATS Stateful Set and NATS Box deployment. All 1.x `values.yaml` files targeting an existing 0.x release will require some or all of these settings:
```yaml
config:
# required if using JetStream file storage
jetstream:
# uncomment the next line if using JetStream file storage
# enabled: true
fileStore:
pvc:
name:
$tplYaml: >-
{{ include "nats.fullname" . }}-js-pvc
# set other PVC options here to make it match 0.x, refer to values.yaml for schema
# required if using a full or cache resolver
resolver:
# uncomment the next line if using a full or cache resolver
# enabled: true
pvc:
name: nats-jwt-pvc
# set other PVC options here to make it match 0.x, refer to values.yaml for schema
# required
statefulSet:
patch:
- op: remove
path: /spec/selector/matchLabels/app.kubernetes.io~1component
- $tplYamlSpread: |-
{{- if and
.Values.config.jetstream.enabled
.Values.config.jetstream.fileStore.enabled
.Values.config.jetstream.fileStore.pvc.enabled
.Values.config.resolver.enabled
.Values.config.resolver.pvc.enabled
}}
- op: move
from: /spec/volumeClaimTemplates/0
path: /spec/volumeClaimTemplates/1
{{- else}}
[]
{{- end }}
# required
headlessService:
name:
$tplYaml: >-
{{ include "nats.fullname" . }}
# required unless 0.x values explicitly set nats.serviceAccount.create=false
serviceAccount:
enabled: true
# required to use new ClusterIP service for Clients accessing NATS
# if using TLS, this may require adding another SAN
service:
# uncomment the next line to disable the new ClusterIP service
# enabled: false
name:
$tplYaml: >-
{{ include "nats.fullname" . }}-svc
# required if using NatsBox
natsBox:
deployment:
patch:
- op: replace
path: /spec/selector/matchLabels
value:
app: nats-box
- op: add
path: /spec/template/metadata/labels/app
value: nats-box
```
## Update NATS Config to new values.yaml schema
Most values that control the NATS Config have changed and moved under the `config` key. Refer to the 1.x Chart's [values.yaml](values.yaml) for the complete schema.
After migrating to the new values schema, ensure that changes you expect in the NATS Config files match by templating the old and new config files.
Template your old 0.x Config Map, this example uses a file called `values-old.yaml`:
```sh
helm template \
--version "0.x" \
-f values-old.yaml \
-s templates/configmap.yaml \
nats \
nats/nats
```
Template your new 1.x Config Map, this example uses a file called `values.yaml`:
```sh
helm template \
--version "^1-beta" \
-f values.yaml \
-s templates/config-map.yaml \
nats \
nats/nats
```
## Update Kubernetes Resources to new values.yaml schema
Most values that control Kubernetes Resources have been changed. Refer to the 1.x Chart's [values.yaml](values.yaml) for the complete schema.
After migrating to the new values schema, ensure that changes you expect in resources match by templating the old and new resources.
| Resource | 0.x Template File | 1.x Template File |
|-------------------------|---------------------------------|-------------------------------------------|
| Config Map | `templates/configmap.yaml` | `templates/config-map.yaml` |
| Stateful Set | `templates/statefulset.yaml` | `templates/stateful-set.yaml` |
| Headless Service | `templates/service.yaml` | `templates/headless-service.yaml` |
| ClusterIP Service | N/A | `templates/service.yaml` |
| Network Policy | `templates/networkpolicy.yaml` | N/A |
| Pod Disruption Budget | `templates/pdb.yaml` | `templates/pod-disruption-budget.yaml` |
| Service Account | `templates/rbac.yaml` | `templates/service-account.yaml` |
| Resource | `templates/` | `templates/` |
| Resource | `templates/` | `templates/` |
| Prometheus Monitor | `templates/serviceMonitor.yaml` | `templates/pod-monitor.yaml` |
| NatsBox Deployment | `templates/nats-box.yaml` | `templates/nats-box/deployment.yaml` |
| NatsBox Service Account | N/A | `templates/nats-box/service-account.yaml` |
| NatsBox Contents Secret | N/A | `templates/nats-box/contents-secret.yaml` |
| NatsBox Contexts Secret | N/A | `templates/nats-box/contexts-secret.yaml` |
For example, to check that the Stateful Set matches:
Template your old 0.x Stateful Set, this example uses a file called `values-old.yaml`:
```sh
helm template \
--version "0.x" \
-f values-old.yaml \
-s templates/statefulset.yaml \
nats \
nats/nats
```
Template your new 1.x Stateful Set, this example uses a file called `values.yaml`:
```sh
helm template \
--version "^1-beta" \
-f values.yaml \
-s templates/stateful-set.yaml \
nats \
nats/nats
```

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.configMap.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
data:
nats.conf: |
{{- include "nats.formatConfig" .config | nindent 4 }}

View File

@ -0,0 +1,32 @@
{{- with .Values.config.cluster }}
name: {{ $.Values.statefulSet.name }}
port: {{ .port }}
no_advertise: true
routes:
{{- $proto := ternary "tls" "nats" .tls.enabled }}
{{- $auth := "" }}
{{- if and .routeURLs.user .routeURLs.password }}
{{- $auth = printf "%s:%s@" (urlquery .routeURLs.user) (urlquery .routeURLs.password) -}}
{{- end }}
{{- $domain := $.Values.headlessService.name }}
{{- if .routeURLs.useFQDN }}
{{- $domain = printf "%s.%s.svc.%s" $domain (include "nats.namespace" $) .routeURLs.k8sClusterDomain }}
{{- end }}
{{- $port := (int .port) }}
{{- range $i, $_ := until (int .replicas) }}
- {{ printf "%s://%s%s-%d.%s:%d" $proto $auth $.Values.statefulSet.name $i $domain $port }}
{{- end }}
{{- if and .routeURLs.user .routeURLs.password }}
authorization:
user: {{ .routeURLs.user | quote }}
password: {{ .routeURLs.password | quote }}
{{- end }}
{{- with .tls }}
{{- if .enabled }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,114 @@
{{- with .Values.config }}
server_name: << $SERVER_NAME >>
lame_duck_grace_period: 10s
lame_duck_duration: 30s
pid_file: /var/run/nats/nats.pid
########################################
# NATS
########################################
{{- with .nats }}
port: {{ .port }}
{{- with .tls }}
{{- if .enabled }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}
########################################
# leafnodes
########################################
{{- with .leafnodes }}
{{- if .enabled }}
leafnodes:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/leafnodes.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
########################################
# websocket
########################################
{{- with .websocket }}
{{- if .enabled }}
websocket:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/websocket.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
########################################
# MQTT
########################################
{{- with .mqtt }}
{{- if .enabled }}
mqtt:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/mqtt.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
########################################
# cluster
########################################
{{- with .cluster }}
{{- if .enabled }}
cluster:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/cluster.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
########################################
# gateway
########################################
{{- with .gateway }}
{{- if .enabled }}
gateway:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/gateway.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
########################################
# monitor
########################################
{{- with .monitor }}
{{- if .enabled }}
{{- if .tls.enabled }}
https_port: {{ .port }}
{{- else }}
http_port: {{ .port }}
{{- end }}
{{- end }}
{{- end }}
########################################
# profiling
########################################
{{- with .profiling }}
{{- if .enabled }}
prof_port: {{ .port }}
{{- end }}
{{- end }}
########################################
# jetstream
########################################
{{- with $.Values.config.jetstream -}}
{{- if .enabled }}
jetstream:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/jetstream.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
########################################
# resolver
########################################
{{- with $.Values.config.resolver -}}
{{- if .enabled }}
resolver:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/resolver.yaml" "ctx" $) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,11 @@
{{- with .Values.config.gateway }}
name: {{ $.Values.statefulSet.name }}
port: {{ .port }}
{{- with .tls }}
{{- if .enabled }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,23 @@
{{- with .Values.config.jetstream }}
{{- with .memoryStore }}
{{- if .enabled }}
{{- with .maxSize }}
max_memory_store: << {{ . }} >>
{{- end }}
{{- else }}
max_memory_store: 0
{{- end }}
{{- end }}
{{- with .fileStore }}
{{- if .enabled }}
store_dir: {{ .dir }}
{{- if .maxSize }}
max_file_store: << {{ .maxSize }} >>
{{- else if .pvc.enabled }}
max_file_store: << {{ .pvc.size }} >>
{{- end }}
{{- else }}
max_file_store: 0
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,11 @@
{{- with .Values.config.leafnodes }}
port: {{ .port }}
no_advertise: true
{{- with .tls }}
{{- if .enabled }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,10 @@
{{- with .Values.config.mqtt }}
port: {{ .port }}
{{- with .tls }}
{{- if .enabled }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,10 @@
{{- with .protocol }}
port: {{ .port }}
{{- with .tls }}
{{- if .enabled }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,3 @@
{{- with .Values.config.resolver }}
dir: {{ .dir }}
{{- end }}

View File

@ -0,0 +1,16 @@
# tls
{{- with .tls }}
{{- if .secretName }}
{{- $dir := trimSuffix "/" .dir }}
cert_file: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }}
key_file: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }}
{{- end }}
{{- end }}
# tlsCA
{{- with $.Values.tlsCA }}
{{- if and .enabled (or .configMapName .secretName) }}
{{- $dir := trimSuffix "/" .dir }}
ca_file: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,12 @@
{{- with .Values.config.websocket }}
port: {{ .port }}
{{- if .tls.enabled }}
{{- with .tls }}
tls:
{{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }}
{{- end }}
{{- else }}
no_tls: true
{{- end }}
{{- end }}

View File

@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.headlessService.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
spec:
selector:
{{- include "nats.selectorLabels" $ | nindent 4 }}
clusterIP: None
publishNotReadyAddresses: true
ports:
{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }}
{{- $configProtocol := get $.Values.config $protocol }}
{{- if or (eq $protocol "nats") $configProtocol.enabled }}
{{- $tlsEnabled := false }}
{{- if hasKey $configProtocol "tls" }}
{{- $tlsEnabled = $configProtocol.tls.enabled }}
{{- end }}
{{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }}
- {{ dict "name" $protocol "port" $configProtocol.port "targetPort" $protocol "appProtocol" $appProtocol | toYaml | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,34 @@
{{- with .Values.config.websocket.ingress }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
spec:
{{- with .className }}
ingressClassName: {{ . | quote }}
{{- end }}
rules:
{{- $path := .path }}
{{- $pathType := .pathType }}
{{- range .hosts }}
- host: {{ . | quote }}
http:
paths:
- path: {{ $path | quote }}
pathType: {{ $pathType | quote }}
backend:
service:
name: {{ $.Values.service.name }}
port:
name: websocket
{{- end }}
{{- if .tlsSecretName }}
tls:
- secretName: {{ .tlsSecretName | quote }}
hosts:
{{- toYaml .hosts | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Secret
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.natsBox.contentsSecret.name }}
labels:
{{- include "natsBox.labels" $ | nindent 4 }}
type: Opaque
stringData:
{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }}
{{- range $secretKey, $secretVal := dict "creds" "creds" "nkey" "nk" }}
{{- $secret := get $ctxVal $secretKey }}
{{- if and $secret $secret.contents }}
"{{ $ctxKey }}.{{ $secretVal }}": {{ $secret.contents | quote }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,51 @@
{{- $contextName := .contextName }}
# url
{{- if .Values.service.enabled }}
url: nats://{{ .Values.service.name }}
{{- else }}
url: nats://{{ .Values.headlessService.name }}
{{- end }}
{{- with .context }}
# creds
{{- with .creds}}
{{- if .contents }}
creds: /etc/nats-contents/{{ $contextName }}.creds
{{- else if .secretName }}
{{- $dir := trimSuffix "/" .dir }}
creds: {{ printf "%s/%s" $dir (.key | default "nats.creds") | quote }}
{{- end }}
{{- end }}
# nkey
{{- with .nkey}}
{{- if .contents }}
nkey: /etc/nats-contents/{{ $contextName }}.nk
{{- else if .secretName }}
{{- $dir := trimSuffix "/" .dir }}
nkey: {{ printf "%s/%s" $dir (.key | default "nats.nk") | quote }}
{{- end }}
{{- end }}
# tls
{{- with .tls }}
{{- if .secretName }}
{{- $dir := trimSuffix "/" .dir }}
cert: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }}
key: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }}
{{- end }}
{{- end }}
# tlsCA
{{- if $.Values.config.nats.tls.enabled }}
{{- with $.Values.tlsCA }}
{{- if and .enabled (or .configMapName .secretName) }}
{{- $dir := trimSuffix "/" .dir }}
ca: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Secret
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.natsBox.contextsSecret.name }}
labels:
{{- include "natsBox.labels" $ | nindent 4 }}
type: Opaque
stringData:
{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }}
"{{ $ctxKey }}.json": |
{{- include "toPrettyRawJson" (include "nats.loadMergePatch" (dict "file" "nats-box/contexts-secret/context.yaml" "merge" (.merge | default dict) "patch" (.patch | default list) "ctx" (merge (dict "contextName" $ctxKey "context" $ctxVal) $)) | fromYaml) | nindent 4 }}
{{- end }}

View File

@ -0,0 +1,46 @@
name: nats-box
{{ include "nats.image" (merge (pick $.Values "global") .Values.natsBox.container.image) }}
{{- with .Values.natsBox.container.env }}
env:
{{- include "nats.env" . }}
{{- end }}
command:
- sh
- -ec
- |
work_dir="$(pwd)"
mkdir -p "$XDG_CONFIG_HOME/nats"
cd "$XDG_CONFIG_HOME/nats"
if ! [ -s context ]; then
ln -s /etc/nats-contexts context
fi
{{- if .Values.natsBox.defaultContextName }}
if ! [ -f context.txt ]; then
echo -n {{ .Values.natsBox.defaultContextName | quote }} > context.txt
fi
{{- end }}
cd "$work_dir"
exec /entrypoint.sh "$@"
- --
args:
- sh
- -ec
- trap true INT TERM; sleep infinity & wait
volumeMounts:
# contexts secret
- name: contexts
mountPath: /etc/nats-contexts
# contents secret
{{- if .hasContentsSecret }}
- name: contents
mountPath: /etc/nats-contents
{{- end }}
# tlsCA
{{- include "nats.tlsCAVolumeMount" $ }}
# secrets
{{- range (include "natsBox.secretNames" $ | fromJson).secretNames }}
- name: {{ .name | quote }}
mountPath: {{ .dir | quote }}
{{- end }}

View File

@ -0,0 +1,16 @@
apiVersion: apps/v1
kind: Deployment
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.natsBox.deployment.name }}
labels:
{{- include "natsBox.labels" $ | nindent 4 }}
spec:
selector:
matchLabels:
{{- include "natsBox.selectorLabels" $ | nindent 6 }}
replicas: 1
template:
{{- with .Values.natsBox.podTemplate }}
{{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/pod-template.yaml" "ctx" $) .) | nindent 4 }}
{{- end }}

View File

@ -0,0 +1,44 @@
metadata:
labels:
{{- include "natsBox.labels" $ | nindent 4 }}
spec:
containers:
{{- with .Values.natsBox.container }}
- {{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/container.yaml" "ctx" $) .) | nindent 4 }}
{{- end }}
# service discovery uses DNS; don't need service env vars
enableServiceLinks: false
{{- with .Values.global.image.pullSecretNames }}
imagePullSecrets:
{{- range . }}
- name: {{ . | quote }}
{{- end }}
{{- end }}
{{- with .Values.natsBox.serviceAccount }}
{{- if .enabled }}
serviceAccountName: {{ .name | quote }}
{{- end }}
{{- end }}
volumes:
# contexts secret
- name: contexts
secret:
secretName: {{ .Values.natsBox.contextsSecret.name }}
# contents secret
{{- if .hasContentsSecret }}
- name: contents
secret:
secretName: {{ .Values.natsBox.contentsSecret.name }}
{{- end }}
# tlsCA
{{- include "nats.tlsCAVolume" $ | nindent 2 }}
# secrets
{{- range (include "natsBox.secretNames" $ | fromJson).secretNames }}
- name: {{ .name | quote }}
secret:
secretName: {{ .secretName | quote }}
{{- end }}

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.natsBox.serviceAccount.name }}
labels:
{{- include "natsBox.labels" $ | nindent 4 }}

View File

@ -0,0 +1,12 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.podDisruptionBudget.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
spec:
maxUnavailable: 1
selector:
matchLabels:
{{- include "nats.selectorLabels" $ | nindent 6 }}

View File

@ -0,0 +1,13 @@
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.promExporter.podMonitor.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
spec:
selector:
matchLabels:
{{- include "nats.selectorLabels" $ | nindent 6 }}
podMetricsEndpoints:
- port: prom-metrics

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.serviceAccount.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}

View File

@ -0,0 +1,23 @@
apiVersion: v1
kind: Service
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.service.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
spec:
selector:
{{- include "nats.selectorLabels" $ | nindent 4 }}
ports:
{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }}
{{- $configProtocol := get $.Values.config $protocol }}
{{- $servicePort := get $.Values.service.ports $protocol }}
{{- if and (or (eq $protocol "nats") $configProtocol.enabled) $servicePort.enabled }}
{{- $tlsEnabled := false }}
{{- if hasKey $configProtocol "tls" }}
{{- $tlsEnabled = $configProtocol.tls.enabled }}
{{- end }}
{{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }}
- {{ merge (dict "name" $protocol "targetPort" $protocol "appProtocol" $appProtocol) (omit $servicePort "enabled") (dict "port" $configProtocol.port) | toYaml | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,13 @@
{{- with .Values.config.jetstream.fileStore.pvc }}
metadata:
name: {{ .name }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .size | quote }}
{{- with .storageClassName }}
storageClassName: {{ . | quote }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,106 @@
name: nats
{{ include "nats.image" (merge (pick $.Values "global") .Values.container.image) }}
ports:
{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }}
{{- $configProtocol := get $.Values.config $protocol }}
{{- $containerPort := get $.Values.container.ports $protocol }}
{{- if or (eq $protocol "nats") $configProtocol.enabled }}
- {{ merge (dict "name" $protocol "containerPort" $configProtocol.port) $containerPort | toYaml | nindent 2 }}
{{- end }}
{{- end }}
args:
- --config
- /etc/nats-config/nats.conf
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: SERVER_NAME
value: {{ printf "%s$(POD_NAME)" .Values.config.serverNamePrefix | quote }}
{{- with .Values.container.env }}
{{- include "nats.env" . }}
{{- end }}
lifecycle:
preStop:
exec:
# send the lame duck shutdown signal to trigger a graceful shutdown
command:
- nats-server
- -sl=ldm=/var/run/nats/nats.pid
{{- with .Values.config.monitor }}
{{- if .enabled }}
startupProbe:
httpGet:
path: /healthz
port: monitor
{{- if .tls.enabled }}
scheme: HTTPS
{{- end}}
initialDelaySeconds: 10
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 90
readinessProbe:
httpGet:
path: /healthz?js-server-only=true
port: monitor
{{- if .tls.enabled }}
scheme: HTTPS
{{- end}}
initialDelaySeconds: 10
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz?js-enabled-only=true
port: monitor
{{- if .tls.enabled }}
scheme: HTTPS
{{- end}}
initialDelaySeconds: 10
timeoutSeconds: 5
periodSeconds: 30
successThreshold: 1
failureThreshold: 3
{{- end }}
{{- end }}
volumeMounts:
# nats config
- name: config
mountPath: /etc/nats-config
# PID volume
- name: pid
mountPath: /var/run/nats
# JetStream PVC
{{- with .Values.config.jetstream }}
{{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }}
{{- with .fileStore }}
- name: {{ .pvc.name }}
mountPath: {{ .dir | quote }}
{{- end }}
{{- end }}
{{- end }}
# resolver PVC
{{- with .Values.config.resolver }}
{{- if and .enabled .pvc.enabled }}
- name: {{ .pvc.name }}
mountPath: {{ .dir | quote }}
{{- end }}
{{- end }}
# tlsCA
{{- include "nats.tlsCAVolumeMount" $ }}
# secrets
{{- range (include "nats.secretNames" $ | fromJson).secretNames }}
- name: {{ .name | quote }}
mountPath: {{ .dir | quote }}
{{- end }}

View File

@ -0,0 +1,71 @@
metadata:
labels:
{{- include "nats.labels" $ | nindent 4 }}
annotations:
{{- if .Values.podTemplate.configChecksumAnnotation }}
{{- $configMap := include "nats.loadMergePatch" (merge (dict "file" "config-map.yaml" "ctx" $) $.Values.configMap) }}
checksum/config: {{ sha256sum $configMap }}
{{- end }}
spec:
containers:
# nats
{{- $nats := dict }}
{{- with .Values.container }}
{{- $nats = include "nats.loadMergePatch" (merge (dict "file" "stateful-set/nats-container.yaml" "ctx" $) .) | fromYaml }}
- {{ toYaml $nats | nindent 4 }}
{{- end }}
# reloader
{{- with .Values.reloader }}
{{- if .enabled }}
- {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/reloader-container.yaml" "ctx" (merge (dict "natsVolumeMounts" $nats.volumeMounts) $)) .) | nindent 4 }}
{{- end }}
{{- end }}
{{- with .Values.promExporter }}
{{- if .enabled }}
- {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/prom-exporter-container.yaml" "ctx" $) .) | nindent 4 }}
{{- end }}
{{- end }}
# service discovery uses DNS; don't need service env vars
enableServiceLinks: false
{{- with .Values.global.image.pullSecretNames }}
imagePullSecrets:
{{- range . }}
- name: {{ . | quote }}
{{- end }}
{{- end }}
{{- with .Values.serviceAccount }}
{{- if .enabled }}
serviceAccountName: {{ .name | quote }}
{{- end }}
{{- end }}
{{- if .Values.reloader.enabled }}
shareProcessNamespace: true
{{- end }}
volumes:
# nats config
- name: config
configMap:
name: {{ .Values.configMap.name }}
# PID volume
- name: pid
emptyDir: {}
# tlsCA
{{- include "nats.tlsCAVolume" $ | nindent 2 }}
# secrets
{{- range (include "nats.secretNames" $ | fromJson).secretNames }}
- name: {{ .name | quote }}
secret:
secretName: {{ .secretName | quote }}
{{- end }}
{{- with .Values.podTemplate.topologySpreadConstraints }}
topologySpreadConstraints:
{{- range $k, $v := . }}
- {{ merge (dict "topologyKey" $k "labelSelector" (dict "matchLabels" (include "nats.selectorLabels" $ | fromYaml))) $v | toYaml | nindent 4 }}
{{- end }}
{{- end}}

View File

@ -0,0 +1,30 @@
name: prom-exporter
{{ include "nats.image" (merge (pick $.Values "global") .Values.promExporter.image) }}
ports:
- name: prom-metrics
containerPort: {{ .Values.promExporter.port }}
{{- with .Values.promExporter.env }}
env:
{{- include "nats.env" . }}
{{- end }}
args:
- -port={{ .Values.promExporter.port }}
- -connz
- -routez
- -subz
- -varz
- -prefix=nats
- -use_internal_server_id
{{- if .Values.config.jetstream.enabled }}
- -jsz=all
{{- end }}
{{- if .Values.config.leafnodes.enabled }}
- -leafz
{{- end }}
{{- if .Values.config.gateway.enabled }}
- -gatewayz
{{- end }}
- http://localhost:{{ .Values.config.monitor.port }}/

View File

@ -0,0 +1,27 @@
name: reloader
{{ include "nats.image" (merge (pick $.Values "global") .Values.reloader.image) }}
{{- with .Values.reloader.env }}
env:
{{- include "nats.env" . }}
{{- end }}
args:
- -pid
- /var/run/nats/nats.pid
- -config
- /etc/nats-config/nats.conf
{{ include "nats.reloaderConfig" (dict "config" .config "dir" "/etc/nats-config") }}
volumeMounts:
- name: pid
mountPath: /var/run/nats
{{- range $mnt := .natsVolumeMounts }}
{{- $found := false }}
{{- range $.Values.reloader.natsVolumeMountPrefixes }}
{{- if and (not $found) (hasPrefix . $mnt.mountPath) }}
{{- $found = true }}
- {{ toYaml $mnt | nindent 2}}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,13 @@
{{- with .Values.config.resolver.pvc }}
metadata:
name: {{ .name }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .size | quote }}
{{- with .storageClassName }}
storageClassName: {{ . | quote }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,37 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
{{- include "nats.metadataNamespace" $ | nindent 2 }}
name: {{ .Values.statefulSet.name }}
labels:
{{- include "nats.labels" $ | nindent 4 }}
spec:
selector:
matchLabels:
{{- include "nats.selectorLabels" $ | nindent 6 }}
{{- if .Values.config.cluster.enabled }}
replicas: {{ .Values.config.cluster.replicas }}
{{- else }}
replicas: 1
{{- end }}
serviceName: {{ .Values.headlessService.name }}
podManagementPolicy: Parallel
template:
{{- with .Values.podTemplate }}
{{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/pod-template.yaml" "ctx" $) .) | nindent 4 }}
{{- end }}
volumeClaimTemplates:
{{- with .Values.config.jetstream }}
{{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }}
{{- with .fileStore.pvc }}
- {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/jetstream-pvc.yaml" "ctx" $) .) | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.config.resolver }}
{{- if and .enabled .pvc.enabled }}
{{- with .pvc }}
- {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/resolver-pvc.yaml" "ctx" $) .) | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,281 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "nats.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 "nats.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 "nats.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Print the namespace
*/}}
{{- define "nats.namespace" -}}
{{- default .Release.Namespace .Values.namespaceOverride }}
{{- end }}
{{/*
Print the namespace for the metadata section
*/}}
{{- define "nats.metadataNamespace" -}}
{{- with .Values.namespaceOverride }}
namespace: {{ . | quote }}
{{- end }}
{{- end }}
{{/*
Set default values.
*/}}
{{- define "nats.defaultValues" }}
{{- if not .defaultValuesSet }}
{{- $name := include "nats.fullname" . }}
{{- with .Values }}
{{- $_ := set .config.jetstream.fileStore.pvc "name" (.config.jetstream.fileStore.pvc.name | default (printf "%s-js" $name)) }}
{{- $_ := set .config.resolver.pvc "name" (.config.resolver.pvc.name | default (printf "%s-resolver" $name)) }}
{{- $_ := set .config.websocket.ingress "name" (.config.websocket.ingress.name | default (printf "%s-ws" $name)) }}
{{- $_ := set .configMap "name" (.configMap.name | default (printf "%s-config" $name)) }}
{{- $_ := set .headlessService "name" (.headlessService.name | default (printf "%s-headless" $name)) }}
{{- $_ := set .natsBox.contentsSecret "name" (.natsBox.contentsSecret.name | default (printf "%s-box-contents" $name)) }}
{{- $_ := set .natsBox.contextsSecret "name" (.natsBox.contextsSecret.name | default (printf "%s-box-contexts" $name)) }}
{{- $_ := set .natsBox.deployment "name" (.natsBox.deployment.name | default (printf "%s-box" $name)) }}
{{- $_ := set .natsBox.serviceAccount "name" (.natsBox.serviceAccount.name | default (printf "%s-box" $name)) }}
{{- $_ := set .podDisruptionBudget "name" (.podDisruptionBudget.name | default $name) }}
{{- $_ := set .service "name" (.service.name | default $name) }}
{{- $_ := set .serviceAccount "name" (.serviceAccount.name | default $name) }}
{{- $_ := set .statefulSet "name" (.statefulSet.name | default $name) }}
{{- $_ := set .promExporter.podMonitor "name" (.promExporter.podMonitor.name | default $name) }}
{{- end }}
{{- $values := get (include "tplYaml" (dict "doc" .Values "ctx" $) | fromJson) "doc" }}
{{- $_ := set . "Values" $values }}
{{- $hasContentsSecret := false }}
{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }}
{{- range $secretKey, $secretVal := dict "creds" "nats-creds" "nkey" "nats-nkeys" "tls" "nats-certs" }}
{{- $secret := get $ctxVal $secretKey }}
{{- if $secret }}
{{- $_ := set $secret "dir" ($secret.dir | default (printf "/etc/%s/%s" $secretVal $ctxKey)) }}
{{- if and (ne $secretKey "tls") $secret.contents }}
{{- $hasContentsSecret = true }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- $_ := set $ "hasContentsSecret" $hasContentsSecret }}
{{- with .Values.config }}
{{- $config := include "nats.loadMergePatch" (merge (dict "file" "config/config.yaml" "ctx" $) .) | fromYaml }}
{{- $_ := set $ "config" $config }}
{{- end }}
{{- $_ := set . "defaultValuesSet" true }}
{{- end }}
{{- end }}
{{/*
NATS labels
*/}}
{{- define "nats.labels" -}}
{{- with .Values.global.labels -}}
{{ toYaml . }}
{{ end -}}
helm.sh/chart: {{ include "nats.chart" . }}
{{ include "nats.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
NATS selector labels
*/}}
{{- define "nats.selectorLabels" -}}
app.kubernetes.io/name: {{ include "nats.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: nats
{{- end }}
{{/*
NATS Box labels
*/}}
{{- define "natsBox.labels" -}}
{{- with .Values.global.labels -}}
{{ toYaml . }}
{{ end -}}
helm.sh/chart: {{ include "nats.chart" . }}
{{ include "natsBox.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
NATS Box selector labels
*/}}
{{- define "natsBox.selectorLabels" -}}
app.kubernetes.io/name: {{ include "nats.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: nats-box
{{- end }}
{{/*
Print the image
*/}}
{{- define "nats.image" }}
{{- $image := printf "%s:%s" .repository .tag }}
{{- if or .registry .global.image.registry }}
{{- $image = printf "%s/%s" (.registry | default .global.image.registry) $image }}
{{- end -}}
image: {{ $image }}
{{- if or .pullPolicy .global.image.pullPolicy }}
imagePullPolicy: {{ .pullPolicy | default .global.image.pullPolicy }}
{{- end }}
{{- end }}
{{- define "nats.secretNames" -}}
{{- $secrets := list }}
{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" }}
{{- $configProtocol := get $.Values.config $protocol }}
{{- if and (or (eq $protocol "nats") $configProtocol.enabled) $configProtocol.tls.enabled $configProtocol.tls.secretName }}
{{- $secrets = append $secrets (merge (dict "name" (printf "%s-tls" $protocol)) $configProtocol.tls) }}
{{- end }}
{{- end }}
{{- toJson (dict "secretNames" $secrets) }}
{{- end }}
{{- define "natsBox.secretNames" -}}
{{- $secrets := list }}
{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }}
{{- range $secretKey, $secretVal := dict "creds" "nats-creds" "nkey" "nats-nkeys" "tls" "nats-certs" }}
{{- $secret := get $ctxVal $secretKey }}
{{- if and $secret $secret.secretName }}
{{- $secrets = append $secrets (merge (dict "name" (printf "ctx-%s-%s" $ctxKey $secretKey)) $secret) }}
{{- end }}
{{- end }}
{{- end }}
{{- toJson (dict "secretNames" $secrets) }}
{{- end }}
{{- define "nats.tlsCAVolume" -}}
{{- with .Values.tlsCA }}
{{- if and .enabled (or .configMapName .secretName) }}
- name: tls-ca
{{- if .configMapName }}
configMap:
name: {{ .configMapName | quote }}
{{- else if .secretName }}
secret:
secretName: {{ .secretName | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- define "nats.tlsCAVolumeMount" -}}
{{- with .Values.tlsCA }}
{{- if and .enabled (or .configMapName .secretName) }}
- name: tls-ca
mountPath: {{ .dir | quote }}
{{- end }}
{{- end }}
{{- end }}
{{/*
translates env var map to list
*/}}
{{- define "nats.env" -}}
{{- range $k, $v := . }}
{{- if kindIs "string" $v }}
- name: {{ $k | quote }}
value: {{ $v | quote }}
{{- else if kindIs "map" $v }}
- {{ merge (dict "name" $k) $v | toYaml | nindent 2 }}
{{- else }}
{{- fail (cat "env var" $k "must be string or map, got" (kindOf $v)) }}
{{- end }}
{{- end }}
{{- end }}
{{- /*
nats.loadMergePatch
input: map with 4 keys:
- file: name of file to load
- ctx: context to pass to tpl
- merge: interface{} to merge
- patch: []interface{} valid JSON Patch document
output: JSON encoded map with 1 key:
- doc: interface{} patched json result
*/}}
{{- define "nats.loadMergePatch" -}}
{{- $doc := tpl (.ctx.Files.Get (printf "files/%s" .file)) .ctx | fromYaml | default dict -}}
{{- $doc = mergeOverwrite $doc (deepCopy (.merge | default dict)) -}}
{{- get (include "jsonpatch" (dict "doc" $doc "patch" (.patch | default list)) | fromJson ) "doc" | toYaml -}}
{{- end }}
{{- /*
nats.reloaderConfig
input: map with 2 keys:
- config: interface{} nats config
- dir: dir config file is in
output: YAML list of reloader config files
*/}}
{{- define "nats.reloaderConfig" -}}
{{- $dir := trimSuffix "/" .dir -}}
{{- with .config -}}
{{- if kindIs "map" . -}}
{{- range $k, $v := . -}}
{{- if or (eq $k "cert_file") (eq $k "key_file") (eq $k "ca_file") }}
- -config
- {{ $v }}
{{- else if hasSuffix "$include" $k }}
- -config
- {{ clean (printf "%s/%s" $dir $v) }}
{{- else }}
{{- include "nats.reloaderConfig" (dict "config" $v "dir" $dir) }}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- /*
nats.formatConfig
input: map[string]interface{}
output: string with following format rules
1. keys ending in $natsRaw are unquoted
2. keys ending in $natsInclude are converted to include directives
*/}}
{{- define "nats.formatConfig" -}}
{{-
(regexReplaceAll "\"<<\\s+(.*)\\s+>>\""
(regexReplaceAll "\".*\\$include\": \"(.*)\",?" (include "toPrettyRawJson" .) "include ${1};")
"${1}")
-}}
{{- end -}}

View File

@ -0,0 +1,219 @@
{{- /*
jsonpatch
input: map with 2 keys:
- doc: interface{} valid JSON document
- patch: []interface{} valid JSON Patch document
output: JSON encoded map with 1 key:
- doc: interface{} patched json result
*/}}
{{- define "jsonpatch" -}}
{{- $params := fromJson (toJson .) -}}
{{- $patches := $params.patch -}}
{{- $docContainer := pick $params "doc" -}}
{{- range $patch := $patches -}}
{{- if not (hasKey $patch "op") -}}
{{- fail "patch is missing op key" -}}
{{- end -}}
{{- if and (ne $patch.op "add") (ne $patch.op "remove") (ne $patch.op "replace") (ne $patch.op "copy") (ne $patch.op "move") (ne $patch.op "test") -}}
{{- fail (cat "patch has invalid op" $patch.op) -}}
{{- end -}}
{{- if not (hasKey $patch "path") -}}
{{- fail "patch is missing path key" -}}
{{- end -}}
{{- if and (or (eq $patch.op "add") (eq $patch.op "replace") (eq $patch.op "test")) (not (hasKey $patch "value")) -}}
{{- fail (cat "patch with op" $patch.op "is missing value key") -}}
{{- end -}}
{{- if and (or (eq $patch.op "copy") (eq $patch.op "move")) (not (hasKey $patch "from")) -}}
{{- fail (cat "patch with op" $patch.op "is missing from key") -}}
{{- end -}}
{{- $opPathKeys := list "path" -}}
{{- if or (eq $patch.op "copy") (eq $patch.op "move") -}}
{{- $opPathKeys = append $opPathKeys "from" -}}
{{- end -}}
{{- $reSlice := list -}}
{{- range $opPathKey := $opPathKeys -}}
{{- $obj := $docContainer -}}
{{- if and (eq $patch.op "copy") (eq $opPathKey "from") -}}
{{- $obj = (fromJson (toJson $docContainer)) -}}
{{- end -}}
{{- $key := "doc" -}}
{{- $lastMap := dict "root" $obj -}}
{{- $lastKey := "root" -}}
{{- $paths := (splitList "/" (get $patch $opPathKey)) -}}
{{- $firstPath := index $paths 0 -}}
{{- if ne (index $paths 0) "" -}}
{{- fail (cat "invalid" $opPathKey (get $patch $opPathKey) "must be empty string or start with /") -}}
{{- end -}}
{{- $paths = slice $paths 1 -}}
{{- range $path := $paths -}}
{{- $path = replace "~1" "/" $path -}}
{{- $path = replace "~0" "~" $path -}}
{{- if kindIs "slice" $obj -}}
{{- $mapObj := dict -}}
{{- range $i, $v := $obj -}}
{{- $_ := set $mapObj (toString $i) $v -}}
{{- end -}}
{{- $obj = $mapObj -}}
{{- $_ := set $lastMap $lastKey $obj -}}
{{- $reSlice = prepend $reSlice (dict "lastMap" $lastMap "lastKey" $lastKey "mapObj" $obj) -}}
{{- end -}}
{{- if kindIs "map" $obj -}}
{{- if not (hasKey $obj $key) -}}
{{- fail (cat "key" $key "does not exist") -}}
{{- end -}}
{{- $lastKey = $key -}}
{{- $lastMap = $obj -}}
{{- $obj = index $obj $key -}}
{{- $key = $path -}}
{{- else -}}
{{- fail (cat "cannot iterate into path" $key "on type" (kindOf $obj)) -}}
{{- end -}}
{{- end -}}
{{- $_ := set $patch (printf "%sKey" $opPathKey) $key -}}
{{- $_ := set $patch (printf "%sLastKey" $opPathKey) $lastKey -}}
{{- $_ = set $patch (printf "%sLastMap" $opPathKey) $lastMap -}}
{{- end -}}
{{- if eq $patch.op "move" }}
{{- if and (ne $patch.path $patch.from) (hasPrefix (printf "%s/" $patch.path) (printf "%s/" $patch.from)) -}}
{{- fail (cat "from" $patch.from "may not be a child of path" $patch.path) -}}
{{- end -}}
{{- end -}}
{{- if or (eq $patch.op "move") (eq $patch.op "copy") (eq $patch.op "test") }}
{{- $key := $patch.fromKey -}}
{{- $lastMap := $patch.fromLastMap -}}
{{- $lastKey := $patch.fromLastKey -}}
{{- $setKey := "value" -}}
{{- if eq $patch.op "test" }}
{{- $key = $patch.pathKey -}}
{{- $lastMap = $patch.pathLastMap -}}
{{- $lastKey = $patch.pathLastKey -}}
{{- $setKey = "testValue" -}}
{{- end -}}
{{- $obj := index $lastMap $lastKey -}}
{{- if kindIs "map" $obj -}}
{{- if not (hasKey $obj $key) -}}
{{- fail (cat $key "does not exist") -}}
{{- end -}}
{{- $_ := set $patch $setKey (index $obj $key) -}}
{{- else if kindIs "slice" $obj -}}
{{- $i := atoi $key -}}
{{- if ne $key (toString $i) -}}
{{- fail (cat "cannot convert" $key "to int") -}}
{{- end -}}
{{- if lt $i 0 -}}
{{- fail "slice index <0" -}}
{{- else if lt $i (len $obj) -}}
{{- $_ := set $patch $setKey (index $obj $i) -}}
{{- else -}}
{{- fail "slice index >= slice length" -}}
{{- end -}}
{{- else -}}
{{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}}
{{- end -}}
{{- end -}}
{{- if or (eq $patch.op "remove") (eq $patch.op "replace") (eq $patch.op "move") }}
{{- $key := $patch.pathKey -}}
{{- $lastMap := $patch.pathLastMap -}}
{{- $lastKey := $patch.pathLastKey -}}
{{- if eq $patch.op "move" }}
{{- $key = $patch.fromKey -}}
{{- $lastMap = $patch.fromLastMap -}}
{{- $lastKey = $patch.fromLastKey -}}
{{- end -}}
{{- $obj := index $lastMap $lastKey -}}
{{- if kindIs "map" $obj -}}
{{- if not (hasKey $obj $key) -}}
{{- fail (cat $key "does not exist") -}}
{{- end -}}
{{- $_ := unset $obj $key -}}
{{- else if kindIs "slice" $obj -}}
{{- $i := atoi $key -}}
{{- if ne $key (toString $i) -}}
{{- fail (cat "cannot convert" $key "to int") -}}
{{- end -}}
{{- if lt $i 0 -}}
{{- fail "slice index <0" -}}
{{- else if eq $i 0 -}}
{{- $_ := set $lastMap $lastKey (slice $obj 1) -}}
{{- else if lt $i (sub (len $obj) 1) -}}
{{- $_ := set $lastMap $lastKey (concat (slice $obj 0 $i) (slice $obj (add $i 1) (len $obj))) -}}
{{- else if eq $i (sub (len $obj) 1) -}}
{{- $_ := set $lastMap $lastKey (slice $obj 0 (sub (len $obj) 1)) -}}
{{- else -}}
{{- fail "slice index >= slice length" -}}
{{- end -}}
{{- else -}}
{{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}}
{{- end -}}
{{- end -}}
{{- if or (eq $patch.op "add") (eq $patch.op "replace") (eq $patch.op "move") (eq $patch.op "copy") }}
{{- $key := $patch.pathKey -}}
{{- $lastMap := $patch.pathLastMap -}}
{{- $lastKey := $patch.pathLastKey -}}
{{- $value := $patch.value -}}
{{- $obj := index $lastMap $lastKey -}}
{{- if kindIs "map" $obj -}}
{{- $_ := set $obj $key $value -}}
{{- else if kindIs "slice" $obj -}}
{{- $i := 0 -}}
{{- if eq $key "-" -}}
{{- $i = len $obj -}}
{{- else -}}
{{- $i = atoi $key -}}
{{- if ne $key (toString $i) -}}
{{- fail (cat "cannot convert" $key "to int") -}}
{{- end -}}
{{- end -}}
{{- if lt $i 0 -}}
{{- fail "slice index <0" -}}
{{- else if eq $i 0 -}}
{{- $_ := set $lastMap $lastKey (prepend $obj $value) -}}
{{- else if lt $i (len $obj) -}}
{{- $_ := set $lastMap $lastKey (concat (append (slice $obj 0 $i) $value) (slice $obj $i)) -}}
{{- else if eq $i (len $obj) -}}
{{- $_ := set $lastMap $lastKey (append $obj $value) -}}
{{- else -}}
{{- fail "slice index > slice length" -}}
{{- end -}}
{{- else -}}
{{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}}
{{- end -}}
{{- end -}}
{{- if eq $patch.op "test" }}
{{- if not (deepEqual $patch.value $patch.testValue) }}
{{- fail (cat "test failed, expected" (toJson $patch.value) "but got" (toJson $patch.testValue)) -}}
{{- end -}}
{{- end -}}
{{- range $reSliceOp := $reSlice -}}
{{- $sliceObj := list -}}
{{- range $i := until (len $reSliceOp.mapObj) -}}
{{- $sliceObj = append $sliceObj (index $reSliceOp.mapObj (toString $i)) -}}
{{- end -}}
{{- $_ := set $reSliceOp.lastMap $reSliceOp.lastKey $sliceObj -}}
{{- end -}}
{{- end -}}
{{- toJson $docContainer -}}
{{- end -}}

View File

@ -0,0 +1,28 @@
{{- /*
toPrettyRawJson
input: interface{} valid JSON document
output: pretty raw JSON string
*/}}
{{- define "toPrettyRawJson" -}}
{{- include "toPrettyRawJsonStr" (toPrettyJson .) -}}
{{- end -}}
{{- /*
toPrettyRawJsonStr
input: pretty JSON string
output: pretty raw JSON string
*/}}
{{- define "toPrettyRawJsonStr" -}}
{{- $s :=
(regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u003e"
(regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u003c"
(regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u0026" . "${1}&")
"${1}<")
"${1}>")
-}}
{{- if regexMatch "([^\\\\](?:\\\\\\\\)*)\\\\u00(26|3c|3e)" $s -}}
{{- include "toPrettyRawJsonStr" $s -}}
{{- else -}}
{{- $s -}}
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,114 @@
{{- /*
tplYaml
input: map with 2 keys:
- doc: interface{}
- ctx: context to pass to tpl function
output: JSON encoded map with 1 key:
- doc: interface{} with any keys called tpl or tplSpread values templated and replaced
maps matching the following syntax will be templated and parsed as YAML
{
$tplYaml: string
}
maps matching the follow syntax will be templated, parsed as YAML, and spread into the parent map/slice
{
$tplYamlSpread: string
}
*/}}
{{- define "tplYaml" -}}
{{- $patch := get (include "tplYamlItr" (dict "ctx" .ctx "parentKind" "" "parentPath" "" "path" "/" "value" .doc) | fromJson) "patch" -}}
{{- include "jsonpatch" (dict "doc" .doc "patch" $patch) -}}
{{- end -}}
{{- /*
tplYamlItr
input: map with 4 keys:
- path: string JSONPath to current element
- parentKind: string kind of parent element
- parentPath: string JSONPath to parent element
- value: interface{}
- ctx: context to pass to tpl function
output: JSON encoded map with 1 key:
- patch: list of patches to apply in order to template
*/}}
{{- define "tplYamlItr" -}}
{{- $params := . -}}
{{- $kind := kindOf $params.value -}}
{{- $patch := list -}}
{{- $joinPath := $params.path -}}
{{- if eq $params.path "/" -}}
{{- $joinPath = "" -}}
{{- end -}}
{{- $joinParentPath := $params.parentPath -}}
{{- if eq $params.parentPath "/" -}}
{{- $joinParentPath = "" -}}
{{- end -}}
{{- if eq $kind "slice" -}}
{{- $iAdj := 0 -}}
{{- range $i, $v := $params.value -}}
{{- $iPath := printf "%s/%d" $joinPath (add $i $iAdj) -}}
{{- $itrPatch := get (include "tplYamlItr" (dict "ctx" $params.ctx "parentKind" $kind "parentPath" $params.path "path" $iPath "value" $v) | fromJson) "patch" -}}
{{- $itrLen := len $itrPatch -}}
{{- if gt $itrLen 0 -}}
{{- $patch = concat $patch $itrPatch -}}
{{- if eq (get (index $itrPatch 0) "op") "remove" -}}
{{- $iAdj = add $iAdj (sub $itrLen 2) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- else if eq $kind "map" -}}
{{- if and (eq (len $params.value) 1) (or (hasKey $params.value "$tplYaml") (hasKey $params.value "$tplYamlSpread")) -}}
{{- $tpl := get $params.value "$tplYaml" -}}
{{- $spread := false -}}
{{- if hasKey $params.value "$tplYamlSpread" -}}
{{- if eq $params.path "/" -}}
{{- fail "cannot $tplYamlSpread on root object" -}}
{{- end -}}
{{- $tpl = get $params.value "$tplYamlSpread" -}}
{{- $spread = true -}}
{{- end -}}
{{- $res := tpl $tpl $params.ctx -}}
{{- $res = get (fromYaml (tpl "tpl: {{ nindent 2 .res }}" (merge (dict "res" $res) $params.ctx))) "tpl" -}}
{{- if eq $spread false -}}
{{- $patch = append $patch (dict "op" "replace" "path" $params.path "value" $res) -}}
{{- else -}}
{{- $resKind := kindOf $res -}}
{{- if and (ne $resKind "invalid") (ne $resKind $params.parentKind) -}}
{{- fail (cat "can only $tplYamlSpread slice onto a slice or map onto a map; attempted to spread" $resKind "on" $params.parentKind "at path" $params.path) -}}
{{- end -}}
{{- $patch = append $patch (dict "op" "remove" "path" $params.path) -}}
{{- if eq $resKind "invalid" -}}
{{- /* no-op */ -}}
{{- else if eq $resKind "slice" -}}
{{- range $v := reverse $res -}}
{{- $patch = append $patch (dict "op" "add" "path" $params.path "value" $v) -}}
{{- end -}}
{{- else -}}
{{- range $k, $v := $res -}}
{{- $kPath := replace "~" "~0" $k -}}
{{- $kPath = replace "/" "~1" $kPath -}}
{{- $kPath = printf "%s/%s" $joinParentPath $kPath -}}
{{- $patch = append $patch (dict "op" "add" "path" $kPath "value" $v) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- else -}}
{{- range $k, $v := $params.value -}}
{{- $kPath := replace "~" "~0" $k -}}
{{- $kPath = replace "/" "~1" $kPath -}}
{{- $kPath = printf "%s/%s" $joinPath $kPath -}}
{{- $itrPatch := get (include "tplYamlItr" (dict "ctx" $params.ctx "parentKind" $kind "parentPath" $params.path "path" $kPath "value" $v) | fromJson) "patch" -}}
{{- if gt (len $itrPatch) 0 -}}
{{- $patch = concat $patch $itrPatch -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- toJson (dict "patch" $patch) -}}
{{- end -}}

View File

@ -0,0 +1,4 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.configMap }}
{{- include "nats.loadMergePatch" (merge (dict "file" "config-map.yaml" "ctx" $) .) }}
{{- end }}

View File

@ -0,0 +1,5 @@
{{- include "nats.defaultValues" . }}
{{- range .Values.extraResources }}
---
{{ . | toYaml }}
{{- end }}

View File

@ -0,0 +1,4 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.headlessService }}
{{- include "nats.loadMergePatch" (merge (dict "file" "headless-service.yaml" "ctx" $) .) }}
{{- end }}

View File

@ -0,0 +1,6 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.config.websocket.ingress }}
{{- if and .enabled .hosts $.Values.config.websocket.enabled $.Values.service.enabled $.Values.service.ports.websocket.enabled }}
{{- include "nats.loadMergePatch" (merge (dict "file" "ingress.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,10 @@
{{- include "nats.defaultValues" . }}
{{- if .hasContentsSecret }}
{{- with .Values.natsBox }}
{{- if .enabled }}
{{- with .contentsSecret}}
{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/contents-secret.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,8 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.natsBox }}
{{- if .enabled }}
{{- with .contextsSecret}}
{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/contexts-secret/contexts-secret.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,8 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.natsBox }}
{{- if .enabled }}
{{- with .deployment }}
{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/deployment.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,8 @@
{{- include "nats.defaultValues" . }}
{{- if .Values.natsBox.enabled }}
{{- with .Values.natsBox.serviceAccount }}
{{- if .enabled }}
{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/service-account.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,6 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.podDisruptionBudget }}
{{- if .enabled }}
{{- include "nats.loadMergePatch" (merge (dict "file" "pod-disruption-budget.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,8 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.promExporter }}
{{- if and .enabled .podMonitor.enabled }}
{{- with .podMonitor }}
{{- include "nats.loadMergePatch" (merge (dict "file" "pod-monitor.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,6 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.serviceAccount }}
{{- if .enabled }}
{{- include "nats.loadMergePatch" (merge (dict "file" "service-account.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,6 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.service }}
{{- if .enabled }}
{{- include "nats.loadMergePatch" (merge (dict "file" "service.yaml" "ctx" $) .) }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,4 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.statefulSet }}
{{- include "nats.loadMergePatch" (merge (dict "file" "stateful-set/stateful-set.yaml" "ctx" $) .) }}
{{- end }}

View File

@ -0,0 +1,37 @@
{{- include "nats.defaultValues" . }}
{{- with .Values.natsBox | deepCopy }}
{{- $natsBox := . }}
{{- if .enabled -}}
apiVersion: v1
kind: Pod
{{- with .container }}
{{- $_ := set . "merge" (dict
"args" (list
"sh"
"-ec"
"nats reply --echo echo & pid=\"$!\"; sleep 1; nats request echo hi > /tmp/resp; kill \"$pid\"; wait; grep -qF hi /tmp/resp"
)
) }}
{{- $_ := set . "patch" list }}
{{- end }}
{{- with .podTemplate }}
{{- $_ := set . "merge" (dict
"metadata" (dict
"name" (printf "%s-test-request-reply" $.Values.statefulSet.name)
"labels" (dict
"app.kubernetes.io/component" "test-request-reply"
)
"annotations" (dict
"helm.sh/hook" "test"
"helm.sh/hook-delete-policy" "before-hook-creation,hook-succeeded"
)
)
"spec" (dict
"restartPolicy" "Never"
)
) }}
{{- $_ := set . "patch" list }}
{{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/pod-template.yaml" "ctx" (merge (dict "Values" (dict "natsBox" $natsBox)) $)) .) }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,669 @@
################################################################################
# Global options
################################################################################
global:
image:
# global image pull policy to use for all container images in the chart
# can be overridden by individual image pullPolicy
pullPolicy:
# global list of secret names to use as image pull secrets for all pod specs in the chart
# secrets must exist in the same namespace
# https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
pullSecretNames: []
# global registry to use for all container images in the chart
# can be overridden by individual image registry
registry:
# global labels will be applied to all resources deployed by the chart
labels: {}
################################################################################
# Common options
################################################################################
# override name of the chart
nameOverride:
# override full name of the chart+release
fullnameOverride:
# override the namespace that resources are installed into
namespaceOverride:
# reference a common CA Certificate or Bundle in all nats config `tls` blocks and nats-box contexts
# note: `tls.verify` still must be set in the appropriate nats config `tls` blocks to require mTLS
tlsCA:
enabled: false
# set configMapName in order to mount an existing configMap to dir
configMapName:
# set secretName in order to mount an existing secretName to dir
secretName:
# directory to mount the configMap or secret to
dir: /etc/nats-ca-cert
# key in the configMap or secret that contains the CA Certificate or Bundle
key: ca.crt
################################################################################
# NATS Stateful Set and associated resources
################################################################################
############################################################
# NATS config
############################################################
config:
cluster:
enabled: false
port: 6222
# must be 2 or higher when jetstream is enabled
replicas: 3
# apply to generated route URLs that connect to other pods in the StatefulSet
routeURLs:
# if both user and password are set, they will be added to route URLs
# and the cluster authorization block
user:
password:
# set to true to use FQDN in route URLs
useFQDN: false
k8sClusterDomain: cluster.local
tls:
enabled: false
# set secretName in order to mount an existing secret to dir
secretName:
dir: /etc/nats-certs/cluster
cert: tls.crt
key: tls.key
# merge or patch the tls config
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
merge: {}
patch: []
# merge or patch the cluster config
# https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config
merge: {}
patch: []
jetstream:
enabled: false
fileStore:
enabled: true
dir: /data
############################################################
# stateful set -> volume claim templates -> jetstream pvc
############################################################
pvc:
enabled: true
size: 10Gi
storageClassName:
# merge or patch the jetstream pvc
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-js"
name:
# defaults to the PVC size
maxSize:
memoryStore:
enabled: false
# ensure that container has a sufficient memory limit greater than maxSize
maxSize: 1Gi
# merge or patch the jetstream config
# https://docs.nats.io/running-a-nats-service/configuration#jetstream
merge: {}
patch: []
nats:
port: 4222
tls:
enabled: false
# set secretName in order to mount an existing secret to dir
secretName:
dir: /etc/nats-certs/nats
cert: tls.crt
key: tls.key
# merge or patch the tls config
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
merge: {}
patch: []
leafnodes:
enabled: false
port: 7422
tls:
enabled: false
# set secretName in order to mount an existing secret to dir
secretName:
dir: /etc/nats-certs/leafnodes
cert: tls.crt
key: tls.key
# merge or patch the tls config
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
merge: {}
patch: []
# merge or patch the leafnodes config
# https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf
merge: {}
patch: []
websocket:
enabled: false
port: 8080
tls:
enabled: false
# set secretName in order to mount an existing secret to dir
secretName:
dir: /etc/nats-certs/websocket
cert: tls.crt
key: tls.key
# merge or patch the tls config
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
merge: {}
patch: []
############################################################
# ingress
############################################################
# service must be enabled also
ingress:
enabled: false
# must contain at least 1 host otherwise ingress will not be created
hosts: []
path: /
pathType: Exact
# sets to the ingress class name
className:
# set to an existing secret name to enable TLS on the ingress; applies to all hosts
tlsSecretName:
# merge or patch the ingress
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-ws"
name:
# merge or patch the websocket config
# https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf
merge: {}
patch: []
mqtt:
enabled: false
port: 1883
tls:
enabled: false
# set secretName in order to mount an existing secret to dir
secretName:
dir: /etc/nats-certs/mqtt
cert: tls.crt
key: tls.key
# merge or patch the tls config
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
merge: {}
patch: []
# merge or patch the mqtt config
# https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config
merge: {}
patch: []
gateway:
enabled: false
port: 7222
tls:
enabled: false
# set secretName in order to mount an existing secret to dir
secretName:
dir: /etc/nats-certs/gateway
cert: tls.crt
key: tls.key
# merge or patch the tls config
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
merge: {}
patch: []
# merge or patch the gateway config
# https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block
merge: {}
patch: []
monitor:
enabled: true
port: 8222
tls:
# config.nats.tls must be enabled also
# when enabled, monitoring port will use HTTPS with the options from config.nats.tls
enabled: false
profiling:
enabled: false
port: 65432
resolver:
enabled: false
dir: /data/resolver
############################################################
# stateful set -> volume claim templates -> resolver pvc
############################################################
pvc:
enabled: true
size: 1Gi
storageClassName:
# merge or patch the pvc
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-resolver"
name:
# merge or patch the resolver
# https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver
merge: {}
patch: []
# adds a prefix to the server name, which defaults to the pod name
# helpful for ensuring server name is unique in a super cluster
serverNamePrefix: ""
# merge or patch the nats config
# https://docs.nats.io/running-a-nats-service/configuration
# following special rules apply
# 1. strings that start with << and end with >> will be unquoted
# use this for variables and numbers with units
# 2. keys ending in $include will be switched to include directives
# keys are sorted alphabetically, use prefix before $includes to control includes ordering
# paths should be relative to /etc/nats-config/nats.conf
# example:
#
# merge:
# $include: ./my-config.conf
# zzz$include: ./my-config-last.conf
# server_name: nats
# authorization:
# token: << $TOKEN >>
# jetstream:
# max_memory_store: << 1GB >>
#
# will yield the config:
# {
# include ./my-config.conf;
# "authorization": {
# "token": $TOKEN
# },
# "jetstream": {
# "max_memory_store": 1GB
# },
# "server_name": "nats",
# include ./my-config-last.conf;
# }
merge: {}
patch: []
############################################################
# stateful set -> pod template -> nats container
############################################################
container:
image:
repository: nats
tag: 2.10.22-alpine
pullPolicy:
registry:
# container port options
# must be enabled in the config section also
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#containerport-v1-core
ports:
nats: {}
leafnodes: {}
websocket: {}
mqtt: {}
cluster: {}
gateway: {}
monitor: {}
profiling: {}
# map with key as env var name, value can be string or map
# example:
#
# env:
# GOMEMLIMIT: 7GiB
# TOKEN:
# valueFrom:
# secretKeyRef:
# name: nats-auth
# key: token
env: {}
# merge or patch the container
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
merge: {}
patch: []
############################################################
# stateful set -> pod template -> reloader container
############################################################
reloader:
enabled: true
image:
repository: natsio/nats-server-config-reloader
tag: 0.16.0
pullPolicy:
registry:
# env var map, see nats.env for an example
env: {}
# all nats container volume mounts with the following prefixes
# will be mounted into the reloader container
natsVolumeMountPrefixes:
- /etc/
# merge or patch the container
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
merge: {}
patch: []
############################################################
# stateful set -> pod template -> prom-exporter container
############################################################
# config.monitor must be enabled
promExporter:
enabled: false
image:
repository: natsio/prometheus-nats-exporter
tag: 0.15.0
pullPolicy:
registry:
port: 7777
# env var map, see nats.env for an example
env: {}
# merge or patch the container
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
merge: {}
patch: []
############################################################
# prometheus pod monitor
############################################################
podMonitor:
enabled: false
# merge or patch the pod monitor
# https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}"
name:
############################################################
# service
############################################################
service:
enabled: true
# service port options
# additional boolean field enable to control whether port is exposed in the service
# must be enabled in the config section also
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceport-v1-core
ports:
nats:
enabled: true
leafnodes:
enabled: true
websocket:
enabled: true
mqtt:
enabled: true
cluster:
enabled: false
gateway:
enabled: false
monitor:
enabled: false
profiling:
enabled: false
# merge or patch the service
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}"
name:
############################################################
# other nats extension points
############################################################
# stateful set
statefulSet:
# merge or patch the stateful set
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}"
name:
# stateful set -> pod template
podTemplate:
# adds a hash of the ConfigMap as a pod annotation
# this will cause the StatefulSet to roll when the ConfigMap is updated
configChecksumAnnotation: true
# map of topologyKey: topologySpreadConstraint
# labelSelector will be added to match StatefulSet pods
#
# topologySpreadConstraints:
# kubernetes.io/hostname:
# maxSkew: 1
#
topologySpreadConstraints: {}
# merge or patch the pod template
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core
merge: {}
patch: []
# headless service
headlessService:
# merge or patch the headless service
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-headless"
name:
# config map
configMap:
# merge or patch the config map
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-config"
name:
# pod disruption budget
podDisruptionBudget:
enabled: true
# merge or patch the pod disruption budget
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#poddisruptionbudget-v1-policy
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}"
name:
# service account
serviceAccount:
enabled: false
# merge or patch the service account
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}"
name:
############################################################
# natsBox
#
# NATS Box Deployment and associated resources
############################################################
natsBox:
enabled: true
############################################################
# NATS contexts
############################################################
contexts:
default:
creds:
# set contents in order to create a secret with the creds file contents
contents:
# set secretName in order to mount an existing secret to dir
secretName:
# defaults to /etc/nats-creds/<context-name>
dir:
key: nats.creds
nkey:
# set contents in order to create a secret with the nkey file contents
contents:
# set secretName in order to mount an existing secret to dir
secretName:
# defaults to /etc/nats-nkeys/<context-name>
dir:
key: nats.nk
# used to connect with client certificates
tls:
# set secretName in order to mount an existing secret to dir
secretName:
# defaults to /etc/nats-certs/<context-name>
dir:
cert: tls.crt
key: tls.key
# merge or patch the context
# https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts
merge: {}
patch: []
# name of context to select by default
defaultContextName: default
############################################################
# deployment -> pod template -> nats-box container
############################################################
container:
image:
repository: natsio/nats-box
tag: 0.14.5
pullPolicy:
registry:
# env var map, see nats.env for an example
env: {}
# merge or patch the container
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
merge: {}
patch: []
############################################################
# other nats-box extension points
############################################################
# deployment
deployment:
# merge or patch the deployment
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-box"
name:
# deployment -> pod template
podTemplate:
# merge or patch the pod template
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core
merge: {}
patch: []
# contexts secret
contextsSecret:
# merge or patch the context secret
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-box-contexts"
name:
# contents secret
contentsSecret:
# merge or patch the contents secret
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-box-contents"
name:
# service account
serviceAccount:
enabled: false
# merge or patch the service account
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core
merge: {}
patch: []
# defaults to "{{ include "nats.fullname" $ }}-box"
name:
################################################################################
# Extra user-defined resources
################################################################################
#
# add arbitrary user-generated resources
# example:
#
# config:
# websocket:
# enabled: true
# extraResources:
# - apiVersion: networking.istio.io/v1beta1
# kind: VirtualService
# metadata:
# name:
# $tplYaml: >
# {{ include "nats.fullname" $ | quote }}
# labels:
# $tplYaml: |
# {{ include "nats.labels" $ }}
# spec:
# hosts:
# - demo.nats.io
# gateways:
# - my-gateway
# http:
# - name: default
# match:
# - name: root
# uri:
# exact: /
# route:
# - destination:
# host:
# $tplYaml: >
# {{ .Values.service.name | quote }}
# port:
# number:
# $tplYaml: >
# {{ .Values.config.websocket.port }}
#
extraResources: []