little reorganization

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
This commit is contained in:
Andrei Kvapil
2024-01-11 14:30:55 +01:00
parent f59bc19a34
commit 73fd64903b
112 changed files with 94 additions and 106570 deletions

1
dashboards/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.tmp

View File

@@ -1 +0,0 @@
grafana-dashboards

View File

@@ -1 +0,0 @@
grafana-dashboards

View File

@@ -5,22 +5,3 @@ update:
helm pull grafana/oncall --untar --untardir charts
rm -rf charts/oncall/charts
hack/download-dashboards.sh
define dashboards_show
@git diff --exit-code .helmignore
@trap 'git checkout .helmignore' EXIT INT && \
sed -i.bak '/grafana-dashboards/d' .helmignore && \
make show | yq e "select(.kind|downcase == \"grafanadashboard\")"
endef
.PHONY=dashboards-show
dashboards-show:
$(call dashboards_show)
.PHONY=dashboards-apply
dashboards-apply:
$(call dashboards_show) | kubectl apply --server-side=true --force-conflicts -f -
.PHONY=dashboards-diff
dashboards-diff:
$(call dashboards_show) | kubectl diff --server-side=true --force-conflicts -f -

View File

@@ -1,26 +0,0 @@
# 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/
# exclude helm unit tests
tests/

View File

@@ -1,24 +0,0 @@
dependencies:
- name: cert-manager
repository: https://charts.jetstack.io
version: v1.8.0
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 12.2.5
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 11.9.10
- name: rabbitmq
repository: https://charts.bitnami.com/bitnami
version: 12.0.0
- name: redis
repository: https://charts.bitnami.com/bitnami
version: 16.13.2
- name: grafana
repository: https://grafana.github.io/helm-charts
version: 6.57.1
- name: ingress-nginx
repository: https://kubernetes.github.io/ingress-nginx
version: 4.1.4
digest: sha256:6b136c450f79c04fb0593d34d625c3a6405b941582dd57dd1465423ba6ce6b06
generated: "2023-12-11T11:06:56.602853945Z"

View File

@@ -1,35 +0,0 @@
apiVersion: v2
appVersion: v1.3.76
dependencies:
- condition: cert-manager.enabled
name: cert-manager
repository: https://charts.jetstack.io
version: v1.8.0
- condition: mariadb.enabled
name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 12.2.5
- condition: postgresql.enabled
name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 11.9.10
- condition: rabbitmq.enabled
name: rabbitmq
repository: https://charts.bitnami.com/bitnami
version: 12.0.0
- condition: redis.enabled
name: redis
repository: https://charts.bitnami.com/bitnami
version: 16.13.2
- condition: grafana.enabled
name: grafana
repository: https://grafana.github.io/helm-charts
version: 6.57.1
- condition: ingress-nginx.enabled
name: ingress-nginx
repository: https://kubernetes.github.io/ingress-nginx
version: 4.1.4
description: Developer-friendly incident response with brilliant Slack integration
name: oncall
type: application
version: 1.3.76

View File

@@ -1,431 +0,0 @@
# Grafana OnCall Helm Chart
This Grafana OnCall Chart is the best way to operate Grafana OnCall on Kubernetes.
It will deploy Grafana OnCall engine and celery workers, along with RabbitMQ cluster, Redis Cluster, and MySQL 5.7 database.
It will also deploy cert manager and nginx ingress controller, as Grafana OnCall backend might need to be externally available
to receive alerts from other monitoring systems. Grafana OnCall engine acts as a backend and can be connected to the
Grafana frontend plugin named Grafana OnCall.
Architecture diagram can be found [here](https://raw.githubusercontent.com/grafana/oncall/dev/docs/img/architecture_diagram.png)
## Production usage
**Default helm chart configuration is not intended for production.**
The helm chart includes all the services into a single release, which is not recommended for production usage.
It is recommended to run stateful services such as MySQL and RabbitMQ separately from this release or use managed
PaaS solutions. It will significantly reduce the overhead of managing them.
Here are the instructions on how to set up your own [ingress](#set-up-external-access), [MySQL](#connect-external-mysql),
[RabbitMQ](#connect-external-rabbitmq), [Redis](#connect-external-redis)
### Cluster requirements
- ensure you can run x86-64/amd64 workloads. arm64 architecture is currently not supported
- kubernetes version 1.25+ is not supported, if cert-manager is enabled
## Install
### Prepare the repo
```bash
# Add the repository
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
```
### Installing the helm chart
```bash
# Install the chart
helm install \
--wait \
--set base_url=example.com \
--set grafana."grafana\.ini".server.domain=example.com \
release-oncall \
grafana/oncall
```
Follow the `helm install` output to finish setting up Grafana OnCall backend and Grafana OnCall frontend plugin e.g.
```bash
👋 Your Grafana OnCall instance has been successfully deployed
❗ Set up a DNS record for your domain (use A Record and "@" to point a root domain to the IP address)
Get the external IP address by running the following commands and point example.com to it:
kubectl get ingress release-oncall -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
Wait until the dns record got propagated.
NOTE: Check with the following command: nslookup example.com
Try reaching https://example.com/ready/ from the browser, make sure it is not cached locally
🦎 Grafana was installed as a part of this helm release. Open https://example.com/grafana/plugins/grafana-oncall-app
The User is admin
Get password by running this command:
kubectl get secret --namespace default release-oncall-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
🔗 Connect Grafana OnCall Plugin to Grafana OnCall backend:
Fill the Grafana OnCall Backend URL:
http://release-oncall-engine:8080
🎉🎉🎉 Done! 🎉🎉🎉
```
## Configuration
You can edit values.yml to make changes to the helm chart configuration and re-deploy the release with the following command:
```bash
helm upgrade \
--install \
--wait \
--set base_url=example.com \
--set grafana."grafana\.ini".server.domain=example.com \
release-oncall \
grafana/oncall
```
### Passwords and external secrets
As OnCall subcharts are Bitname charts, there is a common approach to secrets. Bundled charts allow specifying passwords
in values.yaml explicitly or as K8s secret value. OnCall chart refers either to secret created in sub-chart or
to specified external secret.
Similarly, if component chart is disabled, the password(s) can be supplied in `external<Component>` value
(e.g. externalMysql) explicitly or as K8s secret value. In the first case, the secret is created with the specified
value. In the second case the external secret is used.
- If `<subchart>.auth.existingSecret` is non-empty, then this secret is used. Secret keys are pre-defined by chart.
- If subchart supports password files and `<subchart>.customPasswordFiles` dictionary is non-empty, then password files
are used. Dictionary keys are pre-defined per sub-chart. Password files are not supported by OnCall chart and should
not be used with bundled sub-charts.
- Passwords are specified via `auth` section values, e.g. `auth.password`. K8s secret is created.
- If `<subchart>.auth.forcePassword` is `true`, then passwords MUST be specified. Otherwise, missing passwords
are generated.
If external component is used instead of the bundled one:
- If existingSecret within appropriate external component values is non-empty (e.g. `externalMysql.existingSecret`) then
it is used together with corresponding key names, e.g. `externalMysql.passwordKey`.
- Otherwise, corresponding password values are used, e.g. `externalMysql.password`. K8s secret is created by OnCall chart.
Below is the summary for the dependent charts.
MySQL/MariaDB:
```yaml
database:
type: "mysql" # This is default
mariaDB:
enabled: true # Default
auth:
existingSecret: ""
forcePassword: false
# Secret name: `<release>-mariadb`
rootPassword: "" # Secret key: mariadb-root-password
password: "" # Secret key: mariadb-password
replicationPassword: "" # Secret key: mariadb-replication-password
externalMysql:
password: ""
existingSecret: ""
passwordKey: ""
```
Postgres:
```yaml
database:
type: postgresql
mariadb:
enabled: false # Must be set to false for Postgres
postgresql:
enabled: true # Must be set to true for bundled Postgres
auth:
existingSecret: ""
secretKeys:
adminPasswordKey: ""
userPasswordKey: "" # Not needed
replicationPasswordKey: "" # Not needed with disabled replication
# Secret name: `<release>-postgresql`
postgresPassword: "" # password for admin user postgres. As non-admin user is not created, only this one is relevant.
password: "" # Not needed
replicationPassword: "" # Not needed with disabled replication
externalPostgresql:
user: ""
password: ""
existingSecret: ""
passwordKey: ""
```
Rabbitmq:
```yaml
rabbitmq:
enabled: true
auth:
existingPasswordSecret: "" # Must contain `rabbitmq-password` key
existingErlangSecret: "" # Must contain `rabbitmq-erlang-cookie` key
# Secret name: `<release>-rabbitmq`
password: ""
erlangCookie: ""
externalRabbitmq:
user: ""
password: ""
existingSecret: ""
passwordKey: ""
usernameKey: ""
```
Redis:
```yaml
redis:
enabled: true
auth:
existingSecret: ""
existingSecretPasswordKey: ""
# Secret name: `<release>-redis`
password: ""
externalRedis:
password: ""
existingSecret: ""
passwordKey: ""
```
### Running split ingestion and API services
You can run a detached service for handling integrations by setting up the following variables:
```yaml
detached_integrations:
enabled: true
detached_integrations_service:
enabled: true
```
This will run an integrations-only service listening by default in port 30003.
### Set up Slack and Telegram
You can set up Slack connection via following variables:
```yaml
oncall:
slack:
enabled: true
commandName: oncall
clientId: ~
clientSecret: ~
signingSecret: ~
existingSecret: ""
clientIdKey: ""
clientSecretKey: ""
signingSecretKey: ""
redirectHost: ~
```
`oncall.slack.commandName` is used for changing default bot slash command,
`oncall`. In slack, it could be called via `/<oncall.slack.commandName>`.
To set up Telegram token and webhook url use:
```yaml
oncall:
telegram:
enabled: true
token: ~
webhookUrl: ~
```
To use Telegram long polling instead of webhook use:
```yaml
telegramPolling:
enabled: true
```
### Set up external access
Grafana OnCall can be connected to the external monitoring systems or grafana deployed to the other cluster.
Nginx Ingress Controller and Cert Manager charts are included in the helm chart with the default configuration.
If you set the DNS A Record pointing to the external IP address of the installation with the Hostname matching
base_url parameter, https will be automatically set up. If grafana is enabled in the chart values, it will also be
available on `https://<base_url>/grafana/`. See the details in `helm install` output.
To use a different ingress controller or tls certificate management system, set the following values to
false and edit ingress settings
```yaml
ingress-nginx:
enabled: false
cert-manager:
enabled: false
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/issuer: "letsencrypt-prod"
```
### Use PostgreSQL instead of MySQL
It is possible to use PostgreSQL instead of MySQL. To do so, set mariadb.enabled to `false`,
postgresql.enabled to `true` and database.type to `postgresql`.
```yaml
mariadb:
enabled: false
postgresql:
enabled: true
database:
type: postgresql
```
### Connect external MySQL
It is recommended to use the managed MySQL 5.7 database provided by your cloud provider
Make sure to create the database with the following parameters before installing this chart
```sql
CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```
To use an external MySQL instance set mariadb.enabled to `false` and configure the `externalMysql` parameters.
```yaml
mariadb:
enabled: false
# Make sure to create the database with the following parameters:
# CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
externalMysql:
host:
port:
db_name:
user:
password:
existingSecret: ""
usernameKey: username
passwordKey: password
```
### Connect external PostgreSQL
To use an external PostgreSQL instance set mariadb.enabled to `false`,
postgresql.enabled to `false`, database.type to `postgresql` and configure
the `externalPostgresql` parameters.
```yaml
mariadb:
enabled: false
postgresql:
enabled: false
database:
type: postgresql
# Make sure to create the database with the following parameters:
# CREATE DATABASE oncall WITH ENCODING UTF8;
externalPostgresql:
host:
port:
db_name:
user:
password:
existingSecret: ""
passwordKey: password
```
### Connect external RabbitMQ
Option 1. Install RabbitMQ separately into the cluster using the [official documentation](https://www.rabbitmq.com/kubernetes/operator/operator-overview.html)
Option 2. Use managed solution such as [CloudAMPQ](https://www.cloudamqp.com/)
To use an external RabbitMQ instance set rabbitmq.enabled to `false` and configure the `externalRabbitmq` parameters.
```yaml
rabbitmq:
enabled: false # Disable the RabbitMQ dependency from the release
externalRabbitmq:
host:
port:
user:
password:
protocol:
vhost:
existingSecret: ""
passwordKey: password
usernameKey: username
```
### Connect external Redis
To use an external Redis instance set redis.enabled to `false` and configure the `externalRedis` parameters.
```yaml
redis:
enabled: false # Disable the Redis dependency from the release
externalRedis:
host:
password:
existingSecret: ""
passwordKey: password
```
## Update
```bash
# Add & upgrade the repository
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# Re-deploy
helm upgrade \
--install \
--wait \
--set base_url=example.com \
--set grafana."grafana\.ini".server.domain=example.com \
release-oncall \
grafana/oncall
```
After re-deploying, please also update the Grafana OnCall plugin on the plugin version page.
See [Grafana docs](https://grafana.com/docs/grafana/latest/administration/plugin-management/#update-a-plugin) for
more info on updating Grafana plugins.
## Uninstall
### Uninstalling the helm chart
```bash
helm delete release-oncall
```
### Clean up PVC's
```bash
kubectl delete pvc data-release-oncall-mariadb-0 data-release-oncall-rabbitmq-0 \
redis-data-release-oncall-redis-master-0 redis-data-release-oncall-redis-replicas-0 \
redis-data-release-oncall-redis-replicas-1 redis-data-release-oncall-redis-replicas-2
```
### Clean up secrets
```bash
kubectl delete secrets certificate-tls release-oncall-cert-manager-webhook-ca release-oncall-ingress-nginx-admission
```
## Troubleshooting
### Issues during initial configuration
In the event that you run into issues during initial configuration, it is possible that mismatching versions between
your OnCall backend and UI is the culprit. Ensure that the versions match, and if not,
consider updating your `helm` deployment.

View File

@@ -1,41 +0,0 @@
=================================================================
📞 Grafana OnCall Notes
=================================================================
👋 Your Grafana OnCall instance has been successfully deployed
{{- if not .Values.migrate.enabled }}
🤖 To migrate the database run these commands:
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oncall.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=engine" -o jsonpath="{.items[0].metadata.name}")
kubectl exec -it $POD_NAME -c wait-for-db -- bash -c "python manage.py migrate;"
{{- end }}
❗ Set up a DNS record for your domain (use A Record and "@" to point a root domain to the IP address)
Get the external IP address by running the following commands and point {{ .Values.base_url }} to it:
kubectl get ingress {{ include "oncall.fullname" . }} -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
Wait until the dns record got propagated.
NOTE: Check with the following command: nslookup {{ .Values.base_url }}
Try reaching https://{{ .Values.base_url }}/ready/ from the browser, make sure it is not cached locally
{{- if .Values.grafana.enabled }}
🦎 Grafana was installed as a part of this helm release. Open https://{{ .Values.base_url }}/grafana/plugins/grafana-oncall-app
The User is {{ .Values.grafana.adminUser }}
Get password by running this command:
kubectl get secret --namespace {{ .Release.Namespace }} {{ template "oncall.grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
{{- else }}
🦎 Grafana was NOT installed as a part of this helm release. Open external Grafana, go to "Configuration" - "Plugins" and find Grafana OnCall plugin
NOTE: Make sure your external Grafana is available by the network for the containers installed by this release.
{{- end }}
🔗 Connect Grafana OnCall Plugin to Grafana OnCall backend:
Fill the Grafana OnCall Backend URL:
http://{{ include "oncall.engine.fullname" . }}:8080
🎉🎉🎉 Done! 🎉🎉🎉

View File

@@ -1,656 +0,0 @@
{{- define "snippet.oncall.env" -}}
- name: BASE_URL
value: {{ .Values.base_url_protocol }}://{{ .Values.base_url }}
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "snippet.oncall.secret.name" . }}
key: {{ include "snippet.oncall.secret.secretKey" . | quote }}
- name: MIRAGE_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "snippet.oncall.secret.name" . }}
key: {{ include "snippet.oncall.secret.mirageSecretKey" . | quote }}
- name: MIRAGE_CIPHER_IV
value: {{ .Values.oncall.mirageCipherIV | default "1234567890abcdef" | quote }}
- name: DJANGO_SETTINGS_MODULE
value: "settings.helm"
- name: AMIXR_DJANGO_ADMIN_PATH
value: "admin"
- name: OSS
value: "True"
- name: DETACHED_INTEGRATIONS_SERVER
value: {{ .Values.detached_integrations.enabled | toString | title | quote }}
{{- include "snippet.oncall.uwsgi" . }}
- name: BROKER_TYPE
value: {{ .Values.broker.type | default "rabbitmq" }}
- name: GRAFANA_API_URL
value: {{ include "snippet.grafana.url" . | quote }}
{{- end }}
{{- define "snippet.oncall.secret.name" -}}
{{ if .Values.oncall.secrets.existingSecret -}}
{{ .Values.oncall.secrets.existingSecret }}
{{- else -}}
{{ include "oncall.fullname" . }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.secret.secretKey" -}}
{{ if .Values.oncall.secrets.existingSecret -}}
{{ required "oncall.secrets.secretKey is required if oncall.secret.existingSecret is not empty" .Values.oncall.secrets.secretKey }}
{{- else -}}
SECRET_KEY
{{- end }}
{{- end }}
{{- define "snippet.oncall.secret.mirageSecretKey" -}}
{{ if .Values.oncall.secrets.existingSecret -}}
{{ required "oncall.secrets.mirageSecretKey is required if oncall.secret.existingSecret is not empty" .Values.oncall.secrets.mirageSecretKey }}
{{- else -}}
MIRAGE_SECRET_KEY
{{- end }}
{{- end }}
{{- define "snippet.oncall.uwsgi" -}}
{{- if .Values.uwsgi }}
{{- range $key, $value := .Values.uwsgi }}
- name: UWSGI_{{ $key | upper | replace "-" "_" }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.slack.env" -}}
- name: FEATURE_SLACK_INTEGRATION_ENABLED
value: {{ .Values.oncall.slack.enabled | toString | title | quote }}
{{- if .Values.oncall.slack.enabled }}
- name: SLACK_SLASH_COMMAND_NAME
value: "/{{ .Values.oncall.slack.commandName | default "oncall" }}"
{{- if .Values.oncall.slack.existingSecret }}
- name: SLACK_CLIENT_OAUTH_ID
valueFrom:
secretKeyRef:
name: {{ .Values.oncall.slack.existingSecret }}
key: {{ required "oncall.slack.clientIdKey is required if oncall.slack.existingSecret is not empty" .Values.oncall.slack.clientIdKey | quote }}
- name: SLACK_CLIENT_OAUTH_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.oncall.slack.existingSecret }}
key: {{ required "oncall.slack.clientSecretKey is required if oncall.slack.existingSecret is not empty" .Values.oncall.slack.clientSecretKey | quote }}
- name: SLACK_SIGNING_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.oncall.slack.existingSecret }}
key: {{ required "oncall.slack.signingSecretKey is required if oncall.slack.existingSecret is not empty" .Values.oncall.slack.signingSecretKey | quote }}
{{- else }}
- name: SLACK_CLIENT_OAUTH_ID
value: {{ .Values.oncall.slack.clientId | default "" | quote }}
- name: SLACK_CLIENT_OAUTH_SECRET
value: {{ .Values.oncall.slack.clientSecret | default "" | quote }}
- name: SLACK_SIGNING_SECRET
value: {{ .Values.oncall.slack.signingSecret | default "" | quote }}
{{- end }}
- name: SLACK_INSTALL_RETURN_REDIRECT_HOST
value: {{ .Values.oncall.slack.redirectHost | default (printf "https://%s" .Values.base_url) | quote }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.telegram.env" -}}
{{- if .Values.telegramPolling.enabled -}}
{{- $_ := set .Values.oncall.telegram "enabled" true -}}
{{- end -}}
- name: FEATURE_TELEGRAM_INTEGRATION_ENABLED
value: {{ .Values.oncall.telegram.enabled | toString | title | quote }}
{{- if .Values.oncall.telegram.enabled }}
{{- if .Values.telegramPolling.enabled }}
- name: FEATURE_TELEGRAM_LONG_POLLING_ENABLED
value: {{ .Values.telegramPolling.enabled | toString | title | quote }}
{{- end }}
- name: TELEGRAM_WEBHOOK_HOST
value: {{ .Values.oncall.telegram.webhookUrl | default (printf "https://%s" .Values.base_url) | quote }}
{{- if .Values.oncall.telegram.existingSecret }}
- name: TELEGRAM_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.oncall.telegram.existingSecret }}
key: {{ required "oncall.telegram.tokenKey is required if oncall.telegram.existingSecret is not empty" .Values.oncall.telegram.tokenKey | quote }}
{{- else }}
- name: TELEGRAM_TOKEN
value: {{ .Values.oncall.telegram.token | default "" | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.twilio.env" }}
{{- with .Values.oncall.twilio }}
{{- if .existingSecret }}
- name: TWILIO_ACCOUNT_SID
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ required "oncall.twilio.accountSid is required if oncall.twilio.existingSecret is not empty" .accountSid | quote }}
{{- if .authTokenKey }}
- name: TWILIO_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ required "oncall.twilio.authTokenKey is required if oncall.twilio.existingSecret is not empty" .authTokenKey | quote }}
{{- end }}
- name: TWILIO_NUMBER
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ required "oncall.twilio.phoneNumberKey is required if oncall.twilio.existingSecret is not empty" .phoneNumberKey | quote }}
- name: TWILIO_VERIFY_SERVICE_SID
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ required "oncall.twilio.verifySidKey is required if oncall.twilio.existingSecret is not empty" .verifySidKey | quote }}
{{- if and .apiKeySidKey .apiKeySecretKey }}
- name: TWILIO_API_KEY_SID
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ required "oncall.twilio.apiKeySidKey is required if oncall.twilio.existingSecret is not empty" .apiKeySidKey | quote }}
- name: TWILIO_API_KEY_SECRET
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ required "oncall.twilio.apiKeySecretKey is required if oncall.twilio.existingSecret is not empty" .apiKeySecretKey | quote }}
{{- end }}
{{- else }}
{{- if .accountSid }}
- name: TWILIO_ACCOUNT_SID
value: {{ .accountSid | quote }}
{{- end }}
{{- if .authToken }}
- name: TWILIO_AUTH_TOKEN
value: {{ .authToken | quote }}
{{- end }}
{{- if .phoneNumber }}
- name: TWILIO_NUMBER
value: {{ .phoneNumber | quote }}
{{- end }}
{{- if .verifySid }}
- name: TWILIO_VERIFY_SERVICE_SID
value: {{ .verifySid | quote }}
{{- end }}
{{- if .apiKeySid }}
- name: TWILIO_API_KEY_SID
value: {{ .apiKeySid | quote }}
{{- end }}
{{- if .apiKeySecret }}
- name: TWILIO_API_KEY_SECRET
value: {{ .apiKeySecret | quote }}
{{- end }}
{{- end }}
{{- if .limitPhone }}
- name: PHONE_NOTIFICATIONS_LIMIT
value: {{ .limitPhone | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.celery.env" }}
{{- if .Values.celery.worker_queue }}
- name: CELERY_WORKER_QUEUE
value: {{ .Values.celery.worker_queue | quote }}
{{- end }}
{{- if .Values.celery.worker_concurrency }}
- name: CELERY_WORKER_CONCURRENCY
value: {{ .Values.celery.worker_concurrency | quote }}
{{- end }}
{{- if .Values.celery.worker_max_tasks_per_child }}
- name: CELERY_WORKER_MAX_TASKS_PER_CHILD
value: {{ .Values.celery.worker_max_tasks_per_child | quote }}
{{- end }}
{{- if .Values.celery.worker_beat_enabled }}
- name: CELERY_WORKER_BEAT_ENABLED
value: {{ .Values.celery.worker_beat_enabled | quote }}
{{- end }}
{{- if .Values.celery.worker_shutdown_interval }}
- name: CELERY_WORKER_SHUTDOWN_INTERVAL
value: {{ .Values.celery.worker_shutdown_interval | quote }}
{{- end }}
{{- end }}
{{- define "snippet.grafana.url" -}}
{{ if .Values.grafana.enabled -}}
http://{{ include "oncall.grafana.fullname" . }}
{{- else -}}
{{ required "externalGrafana.url is required when not grafana.enabled" .Values.externalGrafana.url }}
{{- end }}
{{- end }}
{{- define "snippet.mysql.env" -}}
- name: MYSQL_HOST
value: {{ include "snippet.mysql.host" . | quote }}
- name: MYSQL_PORT
value: {{ include "snippet.mysql.port" . | quote }}
- name: MYSQL_DB_NAME
value: {{ include "snippet.mysql.db" . | quote }}
- name: MYSQL_USER
{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.existingSecret .Values.externalMysql.usernameKey (not .Values.externalMysql.user) }}
valueFrom:
secretKeyRef:
name: {{ include "snippet.mysql.password.secret.name" . }}
key: {{ .Values.externalMysql.usernameKey | quote }}
{{- else }}
value: {{ include "snippet.mysql.user" . | quote }}
{{- end }}
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.mysql.password.secret.name" . }}
key: {{ include "snippet.mysql.password.secret.key" . | quote }}
{{- if not .Values.mariadb.enabled }}
{{- with .Values.externalMysql.options }}
- name: MYSQL_OPTIONS
value: {{ . | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.mysql.password.secret.name" -}}
{{ if .Values.mariadb.enabled -}}
{{ if .Values.mariadb.auth.existingSecret -}}
{{ .Values.mariadb.auth.existingSecret }}
{{- else -}}
{{ include "oncall.mariadb.fullname" . }}
{{- end }}
{{- else -}}
{{ if .Values.externalMysql.existingSecret -}}
{{ .Values.externalMysql.existingSecret }}
{{- else -}}
{{ include "oncall.fullname" . }}-mysql-external
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.mysql.password.secret.key" -}}
{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.existingSecret .Values.externalMysql.passwordKey -}}
{{ .Values.externalMysql.passwordKey }}
{{- else -}}
mariadb-root-password
{{- end }}
{{- end }}
{{- define "snippet.mysql.host" -}}
{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.host -}}
{{ .Values.externalMysql.host }}
{{- else -}}
{{ include "oncall.mariadb.fullname" . }}
{{- end }}
{{- end }}
{{- define "snippet.mysql.port" -}}
{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.port -}}
{{ .Values.externalMysql.port }}
{{- else -}}
3306
{{- end }}
{{- end }}
{{- define "snippet.mysql.db" -}}
{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.db_name -}}
{{ .Values.externalMysql.db_name }}
{{- else -}}
{{ .Values.mariadb.auth.database | default "oncall" }}
{{- end }}
{{- end }}
{{- define "snippet.mysql.user" -}}
{{ if and (not .Values.mariadb.enabled) .Values.externalMysql.user -}}
{{ .Values.externalMysql.user }}
{{- else -}}
{{ .Values.mariadb.auth.username | default "root" }}
{{- end }}
{{- end }}
{{- define "snippet.postgresql.env" -}}
- name: DATABASE_TYPE
value: {{ .Values.database.type | quote }}
- name: DATABASE_HOST
value: {{ include "snippet.postgresql.host" . | quote }}
- name: DATABASE_PORT
value: {{ include "snippet.postgresql.port" . | quote }}
- name: DATABASE_NAME
value: {{ include "snippet.postgresql.db" . | quote }}
- name: DATABASE_USER
value: {{ include "snippet.postgresql.user" . | quote }}
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.postgresql.password.secret.name" . }}
key: {{ include "snippet.postgresql.password.secret.key" . | quote }}
{{- if not .Values.postgresql.enabled }}
{{- with .Values.externalPostgresql.options }}
- name: DATABASE_OPTIONS
value: {{ . | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.sqlite.env" -}}
- name: DATABASE_TYPE
value: sqlite3
- name: DATABASE_NAME
value: /etc/app/oncall.db
{{- end }}
{{- define "snippet.postgresql.password.secret.name" -}}
{{ if .Values.postgresql.enabled -}}
{{ if .Values.postgresql.auth.existingSecret -}}
{{ .Values.postgresql.auth.existingSecret }}
{{- else -}}
{{ include "oncall.postgresql.fullname" . }}
{{- end }}
{{- else -}}
{{ if .Values.externalPostgresql.existingSecret -}}
{{ .Values.externalPostgresql.existingSecret }}
{{- else -}}
{{ include "oncall.fullname" . }}-postgresql-external
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.postgresql.password.secret.key" -}}
{{ if .Values.postgresql.enabled -}}
{{ if .Values.postgresql.auth.existingSecret -}}
{{ required "postgresql.auth.secretKeys.adminPasswordKey is required if database.type=postgres and postgresql.enabled and postgresql.auth.existingSecret" .Values.postgresql.auth.secretKeys.adminPasswordKey }}
{{- else -}}
{{ include "postgresql.userPasswordKey" .Subcharts.postgresql }}
{{- end }}
{{- else -}}
{{ if .Values.externalPostgresql.existingSecret -}}
{{ required "externalPostgresql.passwordKey is required if database.type=postgres and not postgresql.enabled and postgresql.auth.existingSecret" .Values.externalPostgresql.passwordKey }}
{{- else -}}
postgres-password
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.postgresql.host" -}}
{{ if not .Values.postgresql.enabled -}}
{{ required "externalPostgresql.host is required if database.type=postgres and not postgresql.enabled" .Values.externalPostgresql.host }}
{{- else -}}
{{ include "oncall.postgresql.fullname" . }}
{{- end }}
{{- end }}
{{- define "snippet.postgresql.port" -}}
{{ if and (not .Values.postgresql.enabled) .Values.externalPostgresql.port -}}
{{ .Values.externalPostgresql.port }}
{{- else -}}
5432
{{- end }}
{{- end }}
{{- define "snippet.postgresql.db" -}}
{{ if not .Values.postgresql.enabled -}}
{{ .Values.externalPostgresql.db_name | default "oncall" }}
{{- else -}}
{{ .Values.postgresql.auth.database | default "oncall" }}
{{- end }}
{{- end }}
{{- define "snippet.postgresql.user" -}}
{{ if not .Values.postgresql.enabled -}}
{{ .Values.externalPostgresql.user | default "postgres" }}
{{- else -}}
{{ .Values.postgresql.auth.username | default "postgres" }}
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.env" }}
- name: RABBITMQ_USERNAME
{{- if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.existingSecret .Values.externalRabbitmq.usernameKey (not .Values.externalRabbitmq.user) }}
valueFrom:
secretKeyRef:
name: {{ include "snippet.rabbitmq.password.secret.name" . }}
key: {{ .Values.externalRabbitmq.usernameKey | quote }}
{{- else }}
value: {{ include "snippet.rabbitmq.user" . | quote }}
{{- end }}
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.rabbitmq.password.secret.name" . }}
key: {{ include "snippet.rabbitmq.password.secret.key" . | quote }}
- name: RABBITMQ_HOST
value: {{ include "snippet.rabbitmq.host" . | quote }}
- name: RABBITMQ_PORT
value: {{ include "snippet.rabbitmq.port" . | quote }}
- name: RABBITMQ_PROTOCOL
value: {{ include "snippet.rabbitmq.protocol" . | quote }}
- name: RABBITMQ_VHOST
value: {{ include "snippet.rabbitmq.vhost" . | quote }}
{{- end }}
{{- define "snippet.rabbitmq.user" -}}
{{ if not .Values.rabbitmq.enabled -}}
{{ required "externalRabbitmq.user is required if not rabbitmq.enabled" .Values.externalRabbitmq.user }}
{{- else -}}
user
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.host" -}}
{{ if not .Values.rabbitmq.enabled -}}
{{ required "externalRabbitmq.host is required if not rabbitmq.enabled" .Values.externalRabbitmq.host }}
{{- else -}}
{{ include "oncall.rabbitmq.fullname" . }}
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.port" -}}
{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.port -}}
{{ required "externalRabbitmq.port is required if not rabbitmq.enabled" .Values.externalRabbitmq.port }}
{{- else -}}
5672
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.protocol" -}}
{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.protocol -}}
{{ .Values.externalRabbitmq.protocol }}
{{- else -}}
amqp
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.vhost" -}}
{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.vhost -}}
{{ .Values.externalRabbitmq.vhost }}
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.password.secret.name" -}}
{{ if .Values.rabbitmq.enabled -}}
{{ if .Values.rabbitmq.auth.existingPasswordSecret -}}
{{ .Values.rabbitmq.auth.existingPasswordSecret }}
{{- else -}}
{{ include "oncall.rabbitmq.fullname" . }}
{{- end }}
{{- else -}}
{{ if .Values.externalRabbitmq.existingSecret -}}
{{ .Values.externalRabbitmq.existingSecret }}
{{- else -}}
{{ include "oncall.fullname" . }}-rabbitmq-external
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.rabbitmq.password.secret.key" -}}
{{ if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.passwordKey -}}
{{ .Values.externalRabbitmq.passwordKey }}
{{- else -}}
rabbitmq-password
{{- end }}
{{- end }}
{{- define "snippet.redis.protocol" -}}
{{ default "redis" .Values.externalRedis.protocol | quote }}
{{- end }}
{{- define "snippet.redis.host" -}}
{{ if not .Values.redis.enabled -}}
{{ required "externalRedis.host is required if not redis.enabled" .Values.externalRedis.host | quote }}
{{- else -}}
{{ include "oncall.redis.fullname" . }}-master
{{- end }}
{{- end }}
{{- define "snippet.redis.port" -}}
{{ default 6379 .Values.externalRedis.port | quote }}
{{- end }}
{{- define "snippet.redis.database" -}}
{{ default 0 .Values.externalRedis.database | quote }}
{{- end }}
{{- define "snippet.redis.password.secret.name" -}}
{{ if .Values.redis.enabled -}}
{{ if .Values.redis.auth.existingSecret -}}
{{ .Values.redis.auth.existingSecret }}
{{- else -}}
{{ include "oncall.redis.fullname" . }}
{{- end }}
{{- else -}}
{{ if .Values.externalRedis.existingSecret -}}
{{ .Values.externalRedis.existingSecret }}
{{- else -}}
{{ include "oncall.fullname" . }}-redis-external
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.redis.password.secret.key" -}}
{{ if .Values.redis.enabled -}}
{{ if .Values.redis.auth.existingSecret -}}
{{ required "redis.auth.existingSecretPasswordKey is required if redis.auth.existingSecret is non-empty" .Values.redis.auth.existingSecretPasswordKey }}
{{- else -}}
redis-password
{{- end }}
{{- else -}}
{{ if .Values.externalRedis.existingSecret -}}
{{ required "externalRedis.passwordKey is required if externalRedis.existingSecret is non-empty" .Values.externalRedis.passwordKey }}
{{- else -}}
redis-password
{{- end }}
{{- end }}
{{- end }}
{{- define "snippet.redis.env" -}}
- name: REDIS_PROTOCOL
value: {{ include "snippet.redis.protocol" . }}
- name: REDIS_HOST
value: {{ include "snippet.redis.host" . }}
- name: REDIS_PORT
value: {{ include "snippet.redis.port" . }}
- name: REDIS_DATABASE
value: {{ include "snippet.redis.database" . }}
- name: REDIS_USERNAME
value: {{ default "" .Values.externalRedis.username | quote }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.redis.password.secret.name" . }}
key: {{ include "snippet.redis.password.secret.key" . | quote}}
{{- if and (not .Values.redis.enabled) .Values.externalRedis.ssl_options.enabled }}
- name: REDIS_USE_SSL
value: "true"
{{- with .Values.externalRedis.ssl_options.ca_certs }}
- name: REDIS_SSL_CA_CERTS
value: {{ . | quote }}
{{- end }}
{{- with .Values.externalRedis.ssl_options.certfile }}
- name: REDIS_SSL_CERTFILE
value: {{ . | quote }}
{{- end }}
{{- with .Values.externalRedis.ssl_options.keyfile }}
- name: REDIS_SSL_KEYFILE
value: {{ . | quote }}
{{- end }}
{{- with .Values.externalRedis.ssl_options.cert_reqs }}
- name: REDIS_SSL_CERT_REQS
value: {{ . | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- /*
when broker.type != rabbitmq, we do not need to include rabbitmq environment variables
*/}}
{{- define "snippet.broker.env" -}}
{{- include "snippet.redis.env" . }}
{{- if eq .Values.broker.type "rabbitmq" -}}
{{- include "snippet.rabbitmq.env" . }}
{{- end }}
{{- end }}
{{- define "snippet.db.env" -}}
{{- if eq .Values.database.type "mysql" }}
{{- include "snippet.mysql.env" . }}
{{- else if eq .Values.database.type "postgresql" }}
{{- include "snippet.postgresql.env" . }}
{{- else if eq .Values.database.type "sqlite" -}}
{{- include "snippet.sqlite.env" . }}
{{- else -}}
{{- fail "value for .Values.db.type must be either 'mysql', 'postgresql', or 'sqlite'" }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.smtp.env" -}}
- name: FEATURE_EMAIL_INTEGRATION_ENABLED
value: {{ .Values.oncall.smtp.enabled | toString | title | quote }}
{{- if .Values.oncall.smtp.enabled }}
- name: EMAIL_HOST
value: {{ .Values.oncall.smtp.host | quote }}
- name: EMAIL_PORT
value: {{ .Values.oncall.smtp.port | default "587" | quote }}
- name: EMAIL_HOST_USER
value: {{ .Values.oncall.smtp.username | quote }}
- name: EMAIL_HOST_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "oncall.fullname" . }}-smtp
key: smtp-password
optional: true
- name: EMAIL_USE_TLS
value: {{ .Values.oncall.smtp.tls | default true | toString | title | quote }}
- name: EMAIL_FROM_ADDRESS
value: {{ .Values.oncall.smtp.fromEmail | quote }}
- name: EMAIL_NOTIFICATIONS_LIMIT
value: {{ .Values.oncall.smtp.limitEmail | default "200" | quote }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.exporter.env" -}}
{{ if .Values.oncall.exporter.enabled -}}
- name: FEATURE_PROMETHEUS_EXPORTER_ENABLED
value: {{ .Values.oncall.exporter.enabled | toString | title | quote }}
- name: PROMETHEUS_EXPORTER_SECRET
valueFrom:
secretKeyRef:
name: {{ include "oncall.fullname" . }}-exporter
key: exporter-secret
optional: true
{{- else -}}
- name: FEATURE_PROMETHEUS_EXPORTER_ENABLED
value: {{ .Values.oncall.exporter.enabled | toString | title | quote }}
{{- end }}
{{- end }}
{{- define "snippet.oncall.engine.env" -}}
{{ include "snippet.oncall.env" . }}
{{ include "snippet.oncall.slack.env" . }}
{{ include "snippet.oncall.telegram.env" . }}
{{ include "snippet.oncall.smtp.env" . }}
{{ include "snippet.oncall.twilio.env" . }}
{{ include "snippet.oncall.exporter.env" . }}
{{ include "snippet.db.env" . }}
{{ include "snippet.broker.env" . }}
{{ include "oncall.extraEnvs" . }}
{{- end }}

View File

@@ -1,121 +0,0 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "oncall.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 "oncall.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 "oncall.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "oncall.labels" -}}
helm.sh/chart: {{ include "oncall.chart" . }}
{{ include "oncall.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "oncall.selectorLabels" -}}
app.kubernetes.io/name: {{ include "oncall.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "oncall.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "oncall.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/* Generate the fullname of mariadb subchart */}}
{{- define "oncall.mariadb.fullname" -}}
{{- printf "%s-%s" .Release.Name "mariadb" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Generate the fullname of postgresql subchart */}}
{{- define "oncall.postgresql.fullname" -}}
{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "oncall.grafana.fullname" -}}
{{- printf "%s-%s" .Release.Name "grafana" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Generate the fullname of rabbitmq subchart */}}
{{- define "oncall.rabbitmq.fullname" -}}
{{- printf "%s-%s" .Release.Name "rabbitmq" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Generate the fullname of redis subchart */}}
{{- define "oncall.redis.fullname" -}}
{{- printf "%s-%s" .Release.Name "redis" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/* Generate engine image name */}}
{{- define "oncall.engine.image" -}}
{{- printf "%s:%s" .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) }}
{{- end }}
{{- define "oncall.initContainer" }}
- name: wait-for-db
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ['sh', '-c', "until (python manage.py migrate --check); do echo Waiting for database migrations; sleep 2; done"]
securityContext:
{{ toYaml .Values.init.securityContext | nindent 4 }}
resources:
{{ toYaml .Values.init.resources | nindent 4 }}
env:
{{- include "snippet.oncall.env" . | nindent 4 }}
{{- include "snippet.db.env" . | nindent 4 }}
{{- include "snippet.broker.env" . | nindent 4 }}
{{- include "oncall.extraEnvs" . | nindent 4 }}
{{- end }}
{{- define "oncall.extraEnvs" -}}
{{- if .Values.env }}
{{- if (kindIs "map" .Values.env) }}
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value }}
{{- end -}}
{{/* support previous schema */}}
{{- else }}
{{- toYaml .Values.env }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -1,26 +0,0 @@
{{/*
Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "oncall.celery.name" -}}
{{ include "oncall.name" . | trunc 55 }}-celery
{{- end }}
{{- define "oncall.celery.fullname" -}}
{{ include "oncall.fullname" . | trunc 55 }}-celery
{{- end }}
{{/*
Engine common labels
*/}}
{{- define "oncall.celery.labels" -}}
{{ include "oncall.labels" . }}
app.kubernetes.io/component: celery
{{- end }}
{{/*
Engine selector labels
*/}}
{{- define "oncall.celery.selectorLabels" -}}
{{ include "oncall.selectorLabels" . }}
app.kubernetes.io/component: celery
{{- end }}

View File

@@ -1,89 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "oncall.celery.fullname" . }}
labels:
{{- include "oncall.celery.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.celery.replicaCount }}
selector:
matchLabels:
{{- include "oncall.celery.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
random-annotation: {{ randAlphaNum 10 | lower }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "oncall.celery.selectorLabels" . | nindent 8 }}
{{- if .Values.celery.podLabels }}
{{- toYaml .Values.celery.podLabels | nindent 8}}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "oncall.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
{{- include "oncall.initContainer" . | indent 8 }}
{{- with .Values.celery.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.celery.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.celery.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.celery.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.celery.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: {{ include "oncall.engine.image" . }}
{{- if .Values.oncall.devMode }}
command: ["python", "manage.py", "start_celery"]
{{- else }}
command: ["./celery_with_exporter.sh"]
{{- end }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
{{- include "snippet.celery.env" . | nindent 12 }}
{{- include "snippet.oncall.engine.env" . | nindent 12 }}
{{- if .Values.celery.livenessProbe.enabled }}
livenessProbe:
exec:
command: [
"bash",
"-c",
"celery -A engine inspect ping -d celery@$HOSTNAME"
]
initialDelaySeconds: {{ .Values.celery.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.celery.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.celery.livenessProbe.timeoutSeconds }}
{{- end }}
resources:
{{- toYaml .Values.celery.resources | nindent 12 }}
{{- with .Values.celery.extraVolumeMounts }}
volumeMounts: {{- . | toYaml | nindent 12 }}
{{- end }}
{{- with .Values.celery.extraContainers }}
{{- tpl . $ | nindent 8 }}
{{- end }}
{{- with .Values.celery.extraVolumes }}
volumes: {{- . | toYaml | nindent 8 }}
{{- end }}

View File

@@ -1,22 +0,0 @@
{{- if (index .Values "cert-manager").enabled }}
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-prod
annotations:
"helm.sh/hook": post-install,post-upgrade
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: no-reply@{{ .Values.base_url }}
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
{{- end }}

View File

@@ -1,26 +0,0 @@
{{/*
Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "oncall.engine.name" -}}
{{ include "oncall.name" . | trunc 55 }}-engine
{{- end }}
{{- define "oncall.engine.fullname" -}}
{{ include "oncall.fullname" . | trunc 55 }}-engine
{{- end }}
{{/*
Engine common labels
*/}}
{{- define "oncall.engine.labels" -}}
{{ include "oncall.labels" . }}
app.kubernetes.io/component: engine
{{- end }}
{{/*
Engien selector labels
*/}}
{{- define "oncall.engine.selectorLabels" -}}
{{ include "oncall.selectorLabels" . }}
app.kubernetes.io/component: engine
{{- end }}

View File

@@ -1,98 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "oncall.engine.fullname" . }}
labels:
{{- include "oncall.engine.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.engine.replicaCount }}
selector:
matchLabels:
{{- include "oncall.engine.selectorLabels" . | nindent 6 }}
strategy:
{{- toYaml .Values.engine.updateStrategy | nindent 4 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
random-annotation: {{ randAlphaNum 10 | lower }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "oncall.engine.selectorLabels" . | nindent 8 }}
{{- if .Values.engine.podLabels }}
{{- toYaml .Values.engine.podLabels | nindent 8}}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "oncall.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
{{- include "oncall.initContainer" . | indent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: {{ include "oncall.engine.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.oncall.devMode }}
command: ["sh", "-c", "uwsgi --disable-logging --py-autoreload 3 --ini uwsgi.ini"]
{{- end }}
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
{{- include "snippet.oncall.engine.env" . | nindent 12 }}
livenessProbe:
httpGet:
path: /health/
port: http
periodSeconds: 60
timeoutSeconds: 3
readinessProbe:
httpGet:
path: /ready/
port: http
periodSeconds: 60
timeoutSeconds: 3
startupProbe:
httpGet:
path: /startupprobe/
port: http
periodSeconds: 10
timeoutSeconds: 3
resources:
{{- toYaml .Values.engine.resources | nindent 12 }}
{{- with .Values.engine.extraVolumeMounts }}
volumeMounts: {{- . | toYaml | nindent 12 }}
{{- end }}
{{- with .Values.engine.extraContainers }}
{{- tpl . $ | nindent 8 }}
{{- end }}
{{- with .Values.engine.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.engine.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.engine.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.engine.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.engine.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
{{- with .Values.engine.extraVolumes }}
volumes: {{- . | toYaml | nindent 8 }}
{{- end }}

View File

@@ -1,102 +0,0 @@
{{- if .Values.migrate.enabled -}}
apiVersion: batch/v1
kind: Job
metadata:
{{- if .Values.migrate.useHook }}
name: {{ printf "%s-migrate" (include "oncall.engine.fullname" .) }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-1"
{{- with .Values.migrate.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- else }}
name: {{ printf "%s-migrate-%s" (include "oncall.engine.fullname" .) (now | date "2006-01-02-15-04-05") }}
{{- with .Values.migrate.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
labels:
{{- include "oncall.engine.labels" . | nindent 4 }}
spec:
backoffLimit: 15
{{- if .Values.migrate.ttlSecondsAfterFinished }}
ttlSecondsAfterFinished: {{ .Values.migrate.ttlSecondsAfterFinished }}
{{- end }}
template:
metadata:
name: {{ printf "%s-migrate-%s" (include "oncall.engine.fullname" .) (now | date "2006-01-02-15-04-05") }}
{{- with .Values.podAnnotations }}
annotations:
random-annotation: {{ randAlphaNum 10 | lower }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "oncall.engine.selectorLabels" . | nindent 8 }}
spec:
restartPolicy: Never
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "oncall.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
{{- with .Values.migrate.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.migrate.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.migrate.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}-migrate
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: {{ include "oncall.engine.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- /bin/sh
- -c
{{- if eq .Values.database.type "mysql" }}
- |
until (nc -vz $MYSQL_HOST $MYSQL_PORT);
do
echo "waiting for MySQL"; sleep 1;
done
python manage.py migrate
{{- else if eq .Values.database.type "postgresql" }}
- |
until (nc -vz $DATABASE_HOST $DATABASE_PORT);
do
echo "waiting for PostgreSQL"; sleep 1;
done
python manage.py migrate
{{- else }}
- python manage.py migrate
{{- end }}
env:
{{- include "snippet.oncall.env" . | nindent 12 }}
{{- include "snippet.oncall.smtp.env" . | nindent 12 }}
{{- include "snippet.oncall.exporter.env" . | nindent 12 }}
{{- include "snippet.db.env" . | nindent 12 }}
{{- include "snippet.broker.env" . | nindent 12 }}
{{- include "oncall.extraEnvs" . | nindent 12 }}
resources:
{{- toYaml .Values.migrate.resources | nindent 12 }}
{{- with .Values.migrate.extraVolumeMounts }}
volumeMounts: {{- . | toYaml | nindent 10 }}
{{- end }}
{{- with .Values.migrate.extraContainers }}
{{- tpl . $ | nindent 6 }}
{{- end }}
{{- with .Values.migrate.extraVolumes }}
volumes: {{- . | toYaml | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -1,24 +0,0 @@
{{- if .Values.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "oncall.engine.fullname" . }}-external
labels:
{{- include "oncall.engine.labels" . | nindent 4 }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
{{- if and (eq .Values.service.type "NodePort") (.Values.service.nodePort) }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector:
{{- include "oncall.engine.selectorLabels" . | nindent 4 }}
{{- end }}

View File

@@ -1,15 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "oncall.engine.fullname" . }}
labels:
{{- include "oncall.engine.labels" . | nindent 4 }}
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: http
protocol: TCP
name: http
selector:
{{- include "oncall.engine.selectorLabels" . | nindent 4 }}

View File

@@ -1,65 +0,0 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "oncall.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "oncall.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- tpl (toYaml .Values.ingress.tls) . | nindent 4 }}
{{- end }}
rules:
- host: {{ .Values.base_url | quote }}
http:
paths:
{{- if .Values.ingress.extraPaths }}
{{ toYaml .Values.ingress.extraPaths | indent 6}}
{{- end }}
- path: /
pathType: Prefix
backend:
service:
name: {{ include "oncall.engine.fullname" . }}
port:
number: 8080
{{ if .Values.grafana.enabled }}
- path: /grafana
pathType: Prefix
backend:
service:
name: {{ include "oncall.grafana.fullname" . }}
port:
number: 80
{{- end }}
{{ if .Values.detached_integrations.enabled }}
- path: /integrations
pathType: Prefix
backend:
service:
name: {{ include "oncall.detached_integrations.fullname" . }}
port:
number: 8080
{{- end }}
{{- end }}

View File

@@ -1,26 +0,0 @@
{{/*
Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "oncall.detached_integrations.name" -}}
{{ include "oncall.name" . | trunc 55 }}-integrations
{{- end }}
{{- define "oncall.detached_integrations.fullname" -}}
{{ include "oncall.fullname" . | trunc 55 }}-integrations
{{- end }}
{{/*
Integrations common labels
*/}}
{{- define "oncall.detached_integrations.labels" -}}
{{ include "oncall.labels" . }}
app.kubernetes.io/component: integrations
{{- end }}
{{/*
Integrations selector labels
*/}}
{{- define "oncall.detached_integrations.selectorLabels" -}}
{{ include "oncall.selectorLabels" . }}
app.kubernetes.io/component: integrations
{{- end }}

View File

@@ -1,99 +0,0 @@
{{- if .Values.detached_integrations.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "oncall.detached_integrations.fullname" . }}
labels:
{{- include "oncall.detached_integrations.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.detached_integrations.replicaCount }}
selector:
matchLabels:
{{- include "oncall.detached_integrations.selectorLabels" . | nindent 6 }}
strategy:
{{- toYaml .Values.detached_integrations.updateStrategy | nindent 4 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
random-annotation: {{ randAlphaNum 10 | lower }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "oncall.detached_integrations.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "oncall.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
{{- include "oncall.initContainer" . | indent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: {{ include "oncall.engine.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.oncall.devMode }}
command: ["sh", "-c", "uwsgi --disable-logging --py-autoreload 3 --ini uwsgi.ini"]
{{- end }}
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
{{- include "snippet.oncall.engine.env" . | nindent 12 }}
- name: ROOT_URLCONF
value: "engine.integrations_urls"
livenessProbe:
httpGet:
path: /health/
port: http
periodSeconds: 60
timeoutSeconds: 3
readinessProbe:
httpGet:
path: /ready/
port: http
periodSeconds: 60
timeoutSeconds: 3
startupProbe:
httpGet:
path: /startupprobe/
port: http
periodSeconds: 10
timeoutSeconds: 3
resources:
{{- toYaml .Values.detached_integrations.resources | nindent 12 }}
{{- with .Values.detached_integrations.extraVolumeMounts }}
volumeMounts: {{- . | toYaml | nindent 12 }}
{{- end }}
{{- with .Values.detached_integrations.extraContainers }}
{{- tpl . $ | nindent 8 }}
{{- end }}
{{- with .Values.detached_integrations.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.detached_integrations.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.detached_integrations.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.detached_integrations.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.detached_integrations.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
{{- with .Values.detached_integrations.extraVolumes }}
volumes: {{- . | toYaml | nindent 8 }}
{{- end }}
{{- end -}}

View File

@@ -1,24 +0,0 @@
{{- if .Values.detached_integrations_service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "oncall.detached_integrations.fullname" . }}-external
labels:
{{- include "oncall.detached_integrations.labels" . | nindent 4 }}
{{- with .Values.detached_integrations_service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.detached_integrations_service.type }}
ports:
- port: {{ .Values.detached_integrations_service.port }}
targetPort: http
protocol: TCP
name: http
{{- if and (eq .Values.detached_integrations_service.type "NodePort") (.Values.detached_integrations_service.nodePort) }}
nodePort: {{ .Values.detached_integrations_service.nodePort }}
{{- end }}
selector:
{{- include "oncall.detached_integrations.selectorLabels" . | nindent 4 }}
{{- end }}

View File

@@ -1,17 +0,0 @@
{{- if .Values.detached_integrations.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "oncall.detached_integrations.fullname" . }}
labels:
{{- include "oncall.detached_integrations.labels" . | nindent 4 }}
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: http
protocol: TCP
name: http
selector:
{{- include "oncall.detached_integrations.selectorLabels" . | nindent 4 }}
{{- end -}}

View File

@@ -1,98 +0,0 @@
{{- if not .Values.oncall.secrets.existingSecret }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}
labels:
{{- include "oncall.labels" . | nindent 4 }}
{{- if .Values.migrate.useHook }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
{{- end }}
type: Opaque
data:
{{ include "snippet.oncall.secret.secretKey" . }}: {{ randAlphaNum 40 | b64enc | quote }}
{{ include "snippet.oncall.secret.mirageSecretKey" . }}: {{ randAlphaNum 40 | b64enc | quote }}
---
{{- end }}
{{- if and (eq .Values.database.type "mysql") (not .Values.mariadb.enabled) (not .Values.externalMysql.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-mysql-external
{{- if .Values.migrate.useHook }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
{{- end }}
type: Opaque
data:
mariadb-root-password: {{ required "externalMysql.password is required if not mariadb.enabled and not externalMysql.existingSecret" .Values.externalMysql.password | b64enc | quote }}
---
{{- end }}
{{- if and (not .Values.postgresql.enabled) (eq .Values.database.type "postgresql") (not .Values.externalPostgresql.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-postgresql-external
{{- if .Values.migrate.useHook }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
{{- end }}
type: Opaque
data:
postgres-password: {{ required "externalPostgresql.password is required if not postgresql.enabled and not externalPostgresql.existingSecret" .Values.externalPostgresql.password | b64enc | quote }}
---
{{- end }}
{{- if and (eq .Values.broker.type "rabbitmq") (not .Values.rabbitmq.enabled) (not .Values.externalRabbitmq.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-rabbitmq-external
{{- if .Values.migrate.useHook }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
{{- end }}
type: Opaque
data:
rabbitmq-password: {{ .Values.externalRabbitmq.password | b64enc | quote }}
---
{{- end }}
{{- if and (eq .Values.broker.type "redis") (not .Values.redis.enabled) (not .Values.externalRedis.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-redis-external
{{- if .Values.migrate.useHook }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
{{- end }}
type: Opaque
data:
redis-password: {{ .Values.externalRedis.password | b64enc | quote }}
---
{{- end }}
{{- if and .Values.oncall.smtp.enabled .Values.oncall.smtp.password }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-smtp
type: Opaque
data:
smtp-password: {{ .Values.oncall.smtp.password | b64enc | quote }}
---
{{- end }}
{{- if and .Values.oncall.exporter.enabled .Values.oncall.exporter.authToken }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-exporter
type: Opaque
data:
exporter-secret: {{ .Values.oncall.exporter.authToken | b64enc | quote }}
---
{{- end }}

View File

@@ -1,18 +0,0 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "oncall.serviceAccountName" . }}
labels:
{{- include "oncall.labels" . | nindent 4 }}
{{- if or (.Values.migrate.useHook) (.Values.serviceAccount.annotations) }}
annotations:
{{- if .Values.migrate.useHook }}
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
{{- end }}
{{- with .Values.serviceAccount.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -1,22 +0,0 @@
{{/*
Maximum of 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "oncall.telegramPolling.fullname" -}}
{{ include "oncall.fullname" . | trunc 45 }}-telegram-polling
{{- end }}
{{/*
Telegram polling common labels
*/}}
{{- define "oncall.telegramPolling.labels" -}}
{{ include "oncall.labels" . }}
app.kubernetes.io/component: telegram-polling
{{- end }}
{{/*
Telegram polling selector labels
*/}}
{{- define "oncall.telegramPolling.selectorLabels" -}}
{{ include "oncall.selectorLabels" . }}
app.kubernetes.io/component: telegram-polling
{{- end }}

View File

@@ -1,53 +0,0 @@
{{- if .Values.telegramPolling.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "oncall.telegramPolling.fullname" . }}
labels:
{{- include "oncall.telegramPolling.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
{{- include "oncall.telegramPolling.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "oncall.telegramPolling.selectorLabels" . | nindent 8 }}
{{- if .Values.telegramPolling.podLabels }}
{{- toYaml .Values.telegramPolling.podLabels | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "oncall.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
{{- include "oncall.initContainer" . | nindent 8 }}
containers:
- name: telegram-polling
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: {{ include "oncall.engine.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ['sh', '-c', 'python manage.py start_telegram_polling']
env:
{{- include "snippet.oncall.env" . | nindent 12 }}
{{- include "snippet.oncall.telegram.env" . | nindent 12 }}
{{- include "snippet.db.env" . | nindent 12 }}
{{- include "snippet.broker.env" . | nindent 12 }}
{{- include "oncall.extraEnvs" . | nindent 12 }}
{{- with .Values.telegramPolling.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.telegramPolling.extraVolumeMounts }}
volumeMounts: {{- . | toYaml | nindent 12 }}
{{- end }}
{{- with .Values.telegramPolling.extraVolumes }}
volumes: {{- . | toYaml | nindent 8 }}
{{- end }}
{{- end -}}

View File

@@ -1,8 +0,0 @@
{{- define "ui.env" -}}
{{- if .Values.ui.env }}
{{- range $key, $value := .Values.ui.env }}
- name: {{ $key }}
value: "{{ $value }}"
{{- end -}}
{{- end }}
{{- end }}

View File

@@ -1,31 +0,0 @@
{{- if .Values.ui.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: oncall-ui
labels:
app.kubernetes.io/component: oncall-ui
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: oncall-ui
template:
metadata:
labels:
app.kubernetes.io/component: oncall-ui
spec:
containers:
- name: oncall-ui
image: "{{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: IfNotPresent
env:
{{- include "ui.env" . | nindent 12 }}
volumeMounts:
- mountPath: /etc/app
name: hot-reloaded-plugin
volumes:
- name: hot-reloaded-plugin
hostPath:
path: /oncall-plugin
{{- end }}

View File

@@ -1,710 +0,0 @@
# Values for configuring the deployment of Grafana OnCall
# Set the domain name Grafana OnCall will be installed on.
# If you want to install grafana as a part of this release make sure to configure grafana.grafana.ini.server.domain too
base_url: example.com
base_url_protocol: https
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
## e.g:
## imagePullSecrets:
## - name: myRegistryKeySecretName
imagePullSecrets: []
image:
# Grafana OnCall docker image repository
repository: grafana/oncall
tag:
pullPolicy: Always
# Whether to create additional service for external connections
# ClusterIP service is always created
service:
enabled: false
type: LoadBalancer
port: 8080
annotations: {}
# Engine pods configuration
engine:
replicaCount: 1
resources:
{}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Labels for engine pods
podLabels: {}
## Deployment update strategy
## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
updateStrategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0
type: RollingUpdate
## Affinity for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
affinity: {}
## Node labels for pod assignment
## ref: https://kubernetes.io/docs/user-guide/node-selection/
nodeSelector: {}
## Tolerations for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
## Topology spread constraints for pod assignment
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
topologySpreadConstraints: []
## Priority class for the pods
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
priorityClassName: ""
# Extra containers which runs as sidecar
extraContainers: ""
# extraContainers: |
# - name: cloud-sql-proxy
# image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2
# args:
# - --private-ip
# - --port=5432
# - example:europe-west3:grafana-oncall-db
# Extra volume mounts for the main app container
extraVolumeMounts: []
# - name: postgres-tls
# configMap:
# name: my-postgres-tls
# defaultMode: 0640
# - name: redis-tls
# configMap:
# name: my-redis-tls
# defaultMode: 0640
# Extra volumes for the pod
extraVolumes: []
# - mountPath: /mnt/postgres-tls
# name: postgres-tls
# - mountPath: /mnt/redis-tls
# name: redis-tls
detached_integrations_service:
enabled: false
type: LoadBalancer
port: 8080
annotations: {}
# Integrations pods configuration
detached_integrations:
enabled: false
replicaCount: 1
resources:
{}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
## Deployment update strategy
## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
updateStrategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0
type: RollingUpdate
## Affinity for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
affinity: {}
## Node labels for pod assignment
## ref: https://kubernetes.io/docs/user-guide/node-selection/
nodeSelector: {}
## Tolerations for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
## Topology spread constraints for pod assignment
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
topologySpreadConstraints: []
## Priority class for the pods
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
priorityClassName: ""
# Extra containers which runs as sidecar
extraContainers: ""
# extraContainers: |
# - name: cloud-sql-proxy
# image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2
# args:
# - --private-ip
# - --port=5432
# - example:europe-west3:grafana-oncall-db
# Extra volume mounts for the container
extraVolumeMounts: []
# - name: postgres-tls
# configMap:
# name: my-postgres-tls
# defaultMode: 0640
# - name: redis-tls
# configMap:
# name: my-redis-tls
# defaultMode: 0640
# Extra volumes for the pod
extraVolumes: []
# - mountPath: /mnt/postgres-tls
# name: postgres-tls
# - mountPath: /mnt/redis-tls
# name: redis-tls
# Celery workers pods configuration
celery:
replicaCount: 1
worker_queue: "default,critical,long,slack,telegram,webhook,celery,grafana"
worker_concurrency: "1"
worker_max_tasks_per_child: "100"
worker_beat_enabled: "True"
## Restart of the celery workers once in a given interval as an additional precaution to the probes
## If this setting is enabled TERM signal will be sent to celery workers
## It will lead to warm shutdown (waiting for the tasks to complete) and restart the container
## If this setting is set numbers of pod restarts will increase
## Comment this line out if you want to remove restarts
worker_shutdown_interval: "65m"
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 300
timeoutSeconds: 10
resources:
{}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Labels for celery pods
podLabels: {}
## Affinity for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
affinity: {}
## Node labels for pod assignment
## ref: https://kubernetes.io/docs/user-guide/node-selection/
nodeSelector: {}
## Tolerations for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
## Topology spread constraints for pod assignment
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
topologySpreadConstraints: []
## Priority class for the pods
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
priorityClassName: ""
# Extra containers which runs as sidecar
extraContainers: ""
# extraContainers: |
# - name: cloud-sql-proxy
# image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2
# args:
# - --private-ip
# - --port=5432
# - example:europe-west3:grafana-oncall-db
# Extra volume mounts for the main container
extraVolumeMounts: []
# - name: postgres-tls
# configMap:
# name: my-postgres-tls
# defaultMode: 0640
# - name: redis-tls
# configMap:
# name: my-redis-tls
# defaultMode: 0640
# Extra volumes for the pod
extraVolumes: []
# - mountPath: /mnt/postgres-tls
# name: postgres-tls
# - mountPath: /mnt/redis-tls
# name: redis-tls
# Telegram polling pod configuration
telegramPolling:
enabled: false
resources:
{}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Labels for telegram-polling pods
podLabels: {}
# Extra volume mounts for the main container
extraVolumeMounts: []
# - name: postgres-tls
# configMap:
# name: my-postgres-tls
# defaultMode: 0640
# - name: redis-tls
# configMap:
# name: my-redis-tls
# defaultMode: 0640
# Extra volumes for the pod
extraVolumes: []
# - mountPath: /mnt/postgres-tls
# name: postgres-tls
# - mountPath: /mnt/redis-tls
# name: redis-tls
oncall:
# this is intended to be used for local development. In short, it will mount the ./engine dir into
# any backend related containers, to allow hot-reloading + also run the containers with slightly modified
# startup commands (which configures the hot-reloading)
devMode: false
# Override default MIRAGE_CIPHER_IV (must be 16 bytes long)
# For existing installation, this should not be changed.
# mirageCipherIV: 1234567890abcdef
# oncall secrets
secrets:
# Use existing secret. (secretKey and mirageSecretKey is required)
existingSecret: ""
# The key in the secret containing secret key
secretKey: ""
# The key in the secret containing mirage secret key
mirageSecretKey: ""
# Slack configures the Grafana Oncall Slack ChatOps integration.
slack:
# Enable the Slack ChatOps integration for the Oncall Engine.
enabled: false
# Sets the Slack bot slash-command
commandName: oncall
# clientId configures the Slack app OAuth2 client ID.
# api.slack.com/apps/<yourApp> -> Basic Information -> App Credentials -> Client ID
clientId: ~
# clientSecret configures the Slack app OAuth2 client secret.
# api.slack.com/apps/<yourApp> -> Basic Information -> App Credentials -> Client Secret
clientSecret: ~
# signingSecret - configures the Slack app signature secret used to sign
# requests comming from Slack.
# api.slack.com/apps/<yourApp> -> Basic Information -> App Credentials -> Signing Secret
signingSecret: ~
# Use existing secret for clientId, clientSecret and signingSecret.
# clientIdKey, clientSecretKey and signingSecretKey are required
existingSecret: ""
# The key in the secret containing OAuth2 client ID
clientIdKey: ""
# The key in the secret containing OAuth2 client secret
clientSecretKey: ""
# The key in the secret containing the Slack app signature secret
signingSecretKey: ""
# OnCall external URL
redirectHost: ~
telegram:
enabled: false
token: ~
webhookUrl: ~
# Use existing secret. (tokenKey is required)
existingSecret: ""
# The key in the secret containing Telegram token
tokenKey: ""
smtp:
enabled: true
host: ~
port: ~
username: ~
password: ~
tls: ~
fromEmail: ~
exporter:
enabled: false
authToken: ~
twilio:
# Twilio account SID/username to allow OnCall to send SMSes and make phone calls
accountSid: ""
# Twilio password to allow OnCall to send SMSes and make calls
authToken: ""
# Number from which you will receive calls and SMS
# (NOTE: must be quoted, otherwise would be rendered as float value)
phoneNumber: ""
# SID of Twilio service for number verification. You can create a service in Twilio web interface.
# twilio.com -> verify -> create new service
verifySid: ""
# Twilio API key SID/username to allow OnCall to send SMSes and make phone calls
apiKeySid: ""
# Twilio API key secret/password to allow OnCall to send SMSes and make phone calls
apiKeySecret: ""
# Use existing secret for authToken, phoneNumber, verifySid, apiKeySid and apiKeySecret.
existingSecret: ""
# Twilio password to allow OnCall to send SMSes and make calls
# The key in the secret containing the auth token
authTokenKey: ""
# The key in the secret containing the phone number
phoneNumberKey: ""
# The key in the secret containing verify service sid
verifySidKey: ""
# The key in the secret containing api key sid
apiKeySidKey: ""
# The key in the secret containing the api key secret
apiKeySecretKey: ""
# Phone notifications limit (the only non-secret value).
# TODO: rename to phoneNotificationLimit
limitPhone:
# Whether to run django database migrations automatically
migrate:
enabled: true
# TTL can be unset by setting ttlSecondsAfterFinished: ""
ttlSecondsAfterFinished: 20
# use a helm hook to manage the migration job
useHook: false
annotations: {}
## Affinity for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
affinity: {}
## Node labels for pod assignment
## ref: https://kubernetes.io/docs/user-guide/node-selection/
nodeSelector: {}
## Tolerations for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
# Extra containers which runs as sidecar
extraContainers: ""
# extraContainers: |
# - name: cloud-sql-proxy
# image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2
# args:
# - --private-ip
# - --port=5432
# - example:europe-west3:grafana-oncall-db
resources:
{}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Extra volume mounts for the main container
extraVolumeMounts: []
# - name: postgres-tls
# configMap:
# name: my-postgres-tls
# defaultMode: 0640
# - name: redis-tls
# configMap:
# name: my-redis-tls
# defaultMode: 0640
# Extra volumes for the pod
extraVolumes: []
# - mountPath: /mnt/postgres-tls
# name: postgres-tls
# - mountPath: /mnt/redis-tls
# name: redis-tls
# Sets environment variables with name capitalized and prefixed with UWSGI_,
# and dashes are substituted with underscores.
# see more: https://uwsgi-docs.readthedocs.io/en/latest/Configuration.html#environment-variables
# Set null to disable all UWSGI environment variables
uwsgi:
listen: 1024
# Additional env variables to add to deployments
env: {}
# Enable ingress object for external access to the resources
ingress:
enabled: true
# className: ""
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/issuer: "letsencrypt-prod"
tls:
- hosts:
- "{{ .Values.base_url }}"
secretName: certificate-tls
# Extra paths to prepend to the host configuration. If using something
# like an ALB ingress controller, you may want to configure SSL redirects
extraPaths: []
# - path: /*
# backend:
# serviceName: ssl-redirect
# servicePort: use-annotation
## Or for k8s > 1.19
# - path: /*
# pathType: Prefix
# backend:
# service:
# name: ssl-redirect
# port:
# name: use-annotation
# Whether to install ingress controller
ingress-nginx:
enabled: true
# Install cert-manager as a part of the release
cert-manager:
enabled: true
# Instal CRD resources
installCRDs: true
webhook:
timeoutSeconds: 30
# cert-manager tries to use the already used port, changing to another one
# https://github.com/cert-manager/cert-manager/issues/3237
# https://cert-manager.io/docs/installation/compatibility/
securePort: 10260
# Fix self-checks https://github.com/jetstack/cert-manager/issues/4286
podDnsPolicy: None
podDnsConfig:
nameservers:
- 8.8.8.8
- 1.1.1.1
database:
# can be either mysql or postgresql
type: mysql
# MySQL is included into this release for the convenience.
# It is recommended to host it separately from this release
# Set mariadb.enabled = false and configure externalMysql
mariadb:
enabled: true
auth:
database: oncall
existingSecret:
primary:
extraEnvVars:
- name: MARIADB_COLLATE
value: utf8mb4_unicode_ci
- name: MARIADB_CHARACTER_SET
value: utf8mb4
secondary:
extraEnvVars:
- name: MARIADB_COLLATE
value: utf8mb4_unicode_ci
- name: MARIADB_CHARACTER_SET
value: utf8mb4
# Make sure to create the database with the following parameters:
# CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
externalMysql:
host:
port:
db_name:
user:
password:
# Use an existing secret for the mysql password.
existingSecret:
# The key in the secret containing the mysql username
usernameKey:
# The key in the secret containing the mysql password
passwordKey:
# Extra options (see example below)
# Reference: https://pymysql.readthedocs.io/en/latest/modules/connections.html
options:
# options: >-
# ssl_verify_cert=true
# ssl_verify_identity=true
# ssl_ca=/mnt/mysql-tls/ca.crt
# ssl_cert=/mnt/mysql-tls/client.crt
# ssl_key=/mnt/mysql-tls/client.key
# PostgreSQL is included into this release for the convenience.
# It is recommended to host it separately from this release
# Set postgresql.enabled = false and configure externalPostgresql
postgresql:
enabled: false
auth:
database: oncall
existingSecret:
# Make sure to create the database with the following parameters:
# CREATE DATABASE oncall WITH ENCODING UTF8;
externalPostgresql:
host:
port:
db_name:
user:
password:
# Use an existing secret for the database password
existingSecret:
# The key in the secret containing the database password
passwordKey:
# Extra options (see example below)
# Reference: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
options:
# options: >-
# sslmode=verify-full
# sslrootcert=/mnt/postgres-tls/ca.crt
# sslcert=/mnt/postgres-tls/client.crt
# sslkey=/mnt/postgres-tls/client.key
# RabbitMQ is included into this release for the convenience.
# It is recommended to host it separately from this release
# Set rabbitmq.enabled = false and configure externalRabbitmq
rabbitmq:
enabled: true
auth:
existingPasswordSecret:
broker:
type: rabbitmq
externalRabbitmq:
host:
port:
user:
password:
protocol:
vhost:
# Use an existing secret for the rabbitmq password
existingSecret:
# The key in the secret containing the rabbitmq password
passwordKey: ""
# The key in the secret containing the rabbitmq username
usernameKey: username
# Redis is included into this release for the convenience.
# It is recommended to host it separately from this release
redis:
enabled: true
auth:
existingSecret:
externalRedis:
protocol:
host:
port:
database:
username:
password:
# Use an existing secret for the redis password
existingSecret:
# The key in the secret containing the redis password
passwordKey:
# SSL options
ssl_options:
enabled: false
# CA certificate
ca_certs:
# Client SSL certs
certfile:
keyfile:
# SSL verification mode: "cert_none" | "cert_optional" | "cert_required"
cert_reqs:
# Grafana is included into this release for the convenience.
# It is recommended to host it separately from this release
grafana:
enabled: true
grafana.ini:
server:
domain: example.com
root_url: "%(protocol)s://%(domain)s/grafana"
serve_from_sub_path: true
persistence:
enabled: true
# Disable psp as PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
rbac:
pspEnabled: false
plugins:
- grafana-oncall-app
externalGrafana:
# Example: https://grafana.mydomain.com
url:
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podSecurityContext:
{}
# fsGroup: 2000
securityContext:
{}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsGroup: 2000
# runAsUser: 1000
init:
securityContext:
{}
# allowPrivilegeEscalation: false
# capabilities:
# drop:
# - ALL
# privileged: false
# readOnlyRootFilesystem: true
# runAsGroup: 2000
# runAsNonRoot: true
# runAsUser: 1000
resources:
{}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
ui:
# this is intended to be used for local development. In short, it will spin up an additional container
# running the plugin frontend, such that hot reloading can be enabled
enabled: false
image:
repository: oncall/ui
tag: dev
# Additional env vars for the ui container
env: {}

View File

@@ -1,611 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "Track whether the cluster can be upgraded to the newer Kubernetes versions",
"editable": false,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
"id": 30,
"iteration": 1656060742701,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"fieldConfig": {
"defaults": {
"color": {
"fixedColor": "blue",
"mode": "fixed"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 5,
"w": 5,
"x": 0,
"y": 0
},
"id": 9,
"options": {
"colorMode": "value",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "name"
},
"pluginVersion": "8.5.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"editorMode": "code",
"expr": "topk(1, sum by (git_version) (kubernetes_build_info{job=\"kube-apiserver\"}))",
"legendFormat": "{{ git_version }}",
"range": true,
"refId": "A"
}
],
"title": "Current K8s version",
"transformations": [
{
"id": "reduce",
"options": {
"labelsToFields": false,
"reducers": []
}
}
],
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"from": 1,
"result": {
"index": 0,
"text": "Cannot be upgraded"
},
"to": 1000000000000000000
},
"type": "range"
},
{
"options": {
"match": "null+nan",
"result": {
"index": 1,
"text": "Can be upgraded"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 5,
"w": 7,
"x": 5,
"y": 0
},
"id": 4,
"options": {
"colorMode": "value",
"graphMode": "none",
"justifyMode": "center",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "8.5.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum(\n ceil(\n sum by(removed_release, resource, group, version) (\n sum by(removed_release, resource, group, version) \n (apiserver_requested_deprecated_apis{removed_release=\"$k8s\"}) \n *\n on(group,version,resource,subresource)\n group_right() (increase(apiserver_request_total[1h]))\n )\n )\n) or vector(0)\n+ \nsum(\n sum by (api_version, kind, helm_release_name, helm_release_namespace)\n (resource_versions_compatibility{k8s_version=~\"$k8s\"})\n) or vector(0)\n> 0",
"instant": true,
"range": false,
"refId": "A"
}
],
"title": "Upgrade to desired version status",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"gridPos": {
"h": 5,
"w": 5,
"x": 12,
"y": 0
},
"id": 7,
"options": {
"content": "<br>\n\n#### Follow instructions to migrate from using **deprecated APIs**\n\nhttps://kubernetes.io/docs/reference/using-api/deprecation-guide/",
"mode": "markdown"
},
"pluginVersion": "8.5.2",
"type": "text"
},
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"gridPos": {
"h": 5,
"w": 7,
"x": 17,
"y": 0
},
"id": 11,
"options": {
"content": "1. Enabled audit logs: [deckhouse.io/#how-do-i-configure-additional-audit-policies](https://deckhouse.io/documentation/v1/modules/040-control-plane-manager/faq.html#how-do-i-configure-additional-audit-policies).\n\n2. Run the following command on each master node:\n```sh\ncat /var/log/kube-audit/audit.log \\\n | grep '\"k8s.io/deprecated\":\"true\"' \\\n | jq -rc 'del(.objectRef.namespace) | {user: .user.username, objectRef: .objectRef}' \\\n | sort | uniq\n```",
"mode": "markdown"
},
"pluginVersion": "8.5.2",
"title": "How to find who sends requests to deprecated APIs",
"type": "text"
},
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"align": "auto",
"displayMode": "color-background",
"filterable": false,
"inspect": false,
"minWidth": 100
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "super-light-orange",
"value": null
},
{
"color": "light-orange",
"value": 50
},
{
"color": "orange",
"value": 200
},
{
"color": "semi-dark-orange",
"value": 500
},
{
"color": "dark-orange",
"value": 1000
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Group"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Version"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Resource"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
}
]
},
"gridPos": {
"h": 13,
"w": 12,
"x": 0,
"y": 5
},
"id": 2,
"options": {
"footer": {
"enablePagination": false,
"fields": "",
"reducer": [
"sum"
],
"show": false
},
"showHeader": true,
"sortBy": []
},
"pluginVersion": "8.5.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"editorMode": "code",
"exemplar": false,
"expr": "ceil(\n sum by(removed_release, resource, group, version)(\n sum by(removed_release, resource, group, version) \n (apiserver_requested_deprecated_apis{removed_release=~\"$k8s\"}) \n * \n on(group,version,resource,subresource)\n group_right() (increase(apiserver_request_total[3h]))\n )\n) > 0",
"format": "table",
"instant": true,
"range": false,
"refId": "A"
}
],
"title": "Requests to kube-apiserver (last 3 hours)",
"transformations": [
{
"id": "filterFieldsByName",
"options": {
"include": {
"names": [
"group",
"removed_release",
"resource",
"version",
"Value"
]
}
}
},
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {
"Value": 4,
"group": 0,
"removed_release": 3,
"resource": 2,
"version": 1
},
"renameByName": {
"Value": "",
"group": "Group",
"removed_release": "Removed Release",
"resource": "Resource",
"version": "Version"
}
}
},
{
"id": "sortBy",
"options": {
"fields": {},
"sort": [
{
"desc": true,
"field": "Value"
}
]
}
}
],
"type": "table"
},
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"align": "auto",
"displayMode": "color-background",
"filterable": false,
"inspect": false,
"minWidth": 100
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "super-light-orange",
"value": null
},
{
"color": "#EAB839",
"value": 5
},
{
"color": "orange",
"value": 15
},
{
"color": "dark-orange",
"value": 50
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "API version"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Helm release"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Helm release namespace"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Kind"
},
"properties": [
{
"id": "custom.displayMode",
"value": "auto"
}
]
}
]
},
"gridPos": {
"h": 13,
"w": 12,
"x": 12,
"y": 5
},
"id": 5,
"options": {
"footer": {
"enablePagination": false,
"fields": "",
"reducer": [
"sum"
],
"show": false
},
"showHeader": true,
"sortBy": []
},
"pluginVersion": "8.5.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum by (api_version, kind, helm_release_name, helm_release_namespace) (resource_versions_compatibility{k8s_version=~\"$k8s\"})",
"format": "table",
"instant": true,
"legendFormat": "__auto",
"range": false,
"refId": "A"
}
],
"title": "Helm releases",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Time": true
},
"indexByName": {},
"renameByName": {
"Time": "",
"Value": "Quantity",
"api_version": "API version",
"helm_release_name": "Helm release",
"helm_release_namespace": "Helm release namespace",
"kind": "Kind"
}
}
},
{
"id": "sortBy",
"options": {
"fields": {},
"sort": [
{
"desc": true,
"field": "Quantity"
}
]
}
}
],
"type": "table"
}
],
"schemaVersion": 36,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"definition": "label_values(apiserver_requested_deprecated_apis, removed_release)",
"hide": 0,
"includeAll": false,
"label": "Desired K8s version",
"multi": false,
"name": "k8s",
"options": [],
"query": {
"query": "label_values(apiserver_requested_deprecated_apis, removed_release)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
}
]
},
"time": {
"from": "now-3h",
"to": "now"
},
"timepicker": {
"hidden": true,
"refresh_intervals": [
"30s"
]
},
"timezone": "",
"title": "Deprecated APIs",
"uid": "B0d1Wt3nk",
"version": 2,
"weekStart": ""
}

View File

@@ -1,53 +0,0 @@
apiVersion: mariadb.mmontes.io/v1alpha1
kind: MariaDB
metadata:
name: grafana-db
spec:
rootPasswordSecretKeyRef:
name: grafana-db
key: root-password
database: grafana-db
username: grafana
passwordSecretKeyRef:
name: grafana-db
key: password
image: "mariadb:11.0.3"
port: 3306
replicas: 3
replication:
enabled: true
#galera:
# enabled: true
# recovery:
# enabled: true
# clusterHealthyTimeout: 5m
# clusterBootstrapTimeout: 10m
# podRecoveryTimeout: 5m
# podSyncTimeout: 10m
# #primary:
# # automaticFailover: true
# # podIndex: 0
podSecurityContext:
runAsUser: 0
volumeClaimTemplate:
resources:
requests:
storage: 30Gi #-- depends on https://github.com/mariadb-operator/mariadb-operator/issues/262
accessModes:
- ReadWriteOnce
---
apiVersion: v1
kind: Secret
metadata:
name: grafana-db
stringData:
password: oohaNgaph1kaeTaebooh
root-password: hoh3Eif9shev5sei0oo6

View File

@@ -1,41 +0,0 @@
---
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Database
metadata:
name: grafana-oncall-db
spec:
mariaDbRef:
name: grafana-db
---
apiVersion: v1
kind: Secret
metadata:
name: grafana-oncall-db
stringData:
password: iengohwedae8hah9Shee
---
apiVersion: mariadb.mmontes.io/v1alpha1
kind: User
metadata:
name: oncall
spec:
mariaDbRef:
name: grafana-db
passwordSecretKeyRef:
name: grafana-oncall-db
key: password
maxUserConnections: 20
---
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Grant
metadata:
name: oncall
spec:
mariaDbRef:
name: grafana-db
privileges:
- "ALL"
database: grafana-oncall-db
table: "*"
username: oncall
grantOption: true

View File

@@ -1,53 +0,0 @@
---
apiVersion: v1
kind: Secret
metadata:
name: grafana-oncall-keydb
stringData:
password: ooBaecaimeer9ufeewei
apiVersion: databases.spotahome.com/v1
kind: RedisFailover
metadata:
name: {{ .Release.Name }}
labels:
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
sentinel:
replicas: 3
resources:
requests:
cpu: 100m
limits:
memory: 100Mi
redis:
replicas: 3
resources:
requests:
cpu: 150m
memory: 400Mi
limits:
cpu: 2
memory: 1000Mi
storage:
persistentVolumeClaim:
metadata:
name: redisfailover-persistent-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
exporter:
enabled: true
image: oliver006/redis_exporter:v1.55.0-alpine
args:
- --web.telemetry-path
- /metrics
env:
- name: REDIS_EXPORTER_LOG_FORMAT
value: txt
customConfig:
- tcp-keepalive 0
- loglevel notice

View File

@@ -5,7 +5,7 @@ apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: {{ $parts._0 }}-{{ $parts._1 }}
namespace: {{ .Release.Namespace }}
namespace: {{ $.Release.Namespace }}
spec:
folder: {{ $parts._0 }}
instanceSelector:

View File

@@ -1,19 +0,0 @@
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
name: vm-longterm
spec:
instanceSelector:
matchLabels:
dashboards: "grafana"
datasource:
name: vm-longterm
type: prometheus
access: proxy
url: http://vmselect-vmcluster-longterm.{{ .Release.Namespace }}.svc:8481/longterm/select/0/prometheus/
isDefault: false
jsonData:
'tlsSkipVerify': true
'timeInterval': "6m"
editable: true

View File

@@ -1,19 +0,0 @@
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
name: vm
spec:
instanceSelector:
matchLabels:
dashboards: "grafana"
datasource:
name: vm
type: prometheus
access: proxy
url: http://vmselect-vmcluster.{{ .Release.Namespace }}.svc:8481/select/0/prometheus/
isDefault: true
jsonData:
'tlsSkipVerify': true
'timeInterval': "30s"
editable: true

View File

@@ -1,7 +1,7 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: grafana-db
name: {{ .Release.Name }}-grafana-db
spec:
instances: 2
storage:

View File

@@ -2,32 +2,15 @@
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
name: grafana
name: {{ .Release.Name }}-grafana
labels:
dashboards: "grafana"
dashboards: {{ .Release.Name }}-grafana
spec:
config:
log:
mode: "console"
auth:
disable_login_form: "false"
auth.gitlab:
name: Gitlab
enabled: "true"
allow_sign_up: "true"
auto_login: "false"
client_id: e03e8bbe-1a4f-4555-906e-710f1b148d7b
client_secret: d57d2398-ce98-4309-a799-ac6d7cf54367
scopes: api
auth_url: "https://git.example.org/oauth/authorize"
token_url: "https://git.example.org/oauth/token"
api_url: "https://git.example.org/api/v4"
#allowed_groups: '["cluster-admins"]'
role_attribute_path: "contains(info.groups_direct[*], 'grafana-admin') && 'Admin' || contains(info.groups_direct[*], 'grafana-editor') && 'Editor' || 'Viewer'"
#role_attribute_path: "is_admin && 'Admin' || 'Viewer'"
#tls_skip_verify_insecure: "false"
#use_pkce: "true"
#use_refresh_token: "true"
database:
type: postgres
name: ${GF_DATABASE_NAME}
@@ -38,8 +21,8 @@ spec:
server:
root_url: https://grafana.example.org
security:
admin_user: root
admin_password: {{ .Values.adminPassword }}
admin_user: user
admin_password: ${GF_PASSWORD}
deployment:
spec:
replicas: 2
@@ -57,15 +40,27 @@ spec:
- name: GF_INSTALL_PLUGINS
value: grafana-worldmap-panel,flant-statusmap-panel,grafana-oncall-app,natel-discrete-panel
- name: ONCALL_API_URL
value: http://grafana-oncall-engine:8080
value: http://{{ .Release.Name }}-grafana-oncall-engine:8080
- name: GF_DATABASE_HOST
value: "grafana-db-rw:5432"
value: "{{ .Release.Name }}-grafana-db-rw:5432"
- name: GF_DATABASE_PASSWORD
valueFrom: { secretKeyRef: { name: grafana-db-app, key: password } }
valueFrom: { secretKeyRef: { name: {{ .Release.Name }}-grafana-db-app, key: password } }
- name: GF_DATABASE_NAME
value: "app"
- name: GF_DATABASE_USER
value: "app"
- name: GF_PASSWORD
valueFrom: { secretKeyRef: { name: {{ .Release.Name }}-grafana-admin-password, key: password } }
- name: GF_SECURITY_ADMIN_USER
valueFrom:
secretKeyRef:
key: user
name: {{ .Release.Name }}-grafana-admin-password
- name: GF_SECURITY_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: {{ .Release.Name }}-grafana-admin-password
ingress:
metadata:
annotations:
@@ -87,4 +82,4 @@ spec:
tls:
- hosts:
- grafana.example.org
secretName: grafana-ingressmyingress-tls
secretName: {{ .Release.Name }}-grafana-ingress-tls

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-grafana-admin-password
namespace:
stringData:
user: admin
password: asdasdASD

View File

@@ -1,7 +1,7 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: grafana-oncall-db
name: {{ .Release.Name }}-grafana-oncall-db
spec:
instances: 2
storage:

View File

@@ -1,7 +1,7 @@
apiVersion: databases.spotahome.com/v1
kind: RedisFailover
metadata:
name: grafana-oncall
name: {{ .Release.Name }}-grafana-oncall
labels:
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}

View File

@@ -0,0 +1,22 @@
{{- $first := true }}
{{- range .Values.storages }}
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
name: {{ $.Release.Name }}-{{ .name }}
spec:
instanceSelector:
matchLabels:
dashboards: {{ $.Release.Name }}-grafana
datasource:
name: {{ .name }}
type: prometheus
access: proxy
url: http://vmselect-vmcluster.{{ $.Release.Namespace }}.svc:8481/select/0/prometheus/
isDefault: {{ if $first }}true{{ $first = false }}{{ else }}false{{ end }}
jsonData:
'tlsSkipVerify': true
'timeInterval': "30s"
editable: true
{{- end }}

View File

@@ -2,8 +2,7 @@
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMServiceScrape
metadata:
name: vmalert-vmalert
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
spec:
endpoints:
- path: /metrics

View File

@@ -1,8 +1,7 @@
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMAlert
metadata:
name: vmalert
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
spec:
datasource:
url: http://vmselect-vmcluster.{{ .Release.Namespace }}.svc:8481/select/0/prometheus

View File

@@ -1,7 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
name: alertmanager
name: {{ .Release.Name }}-alertmanager
type: Opaque
stringData:
alertmanager.yaml: |
@@ -23,7 +23,7 @@ stringData:
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMAlertmanager
metadata:
name: alertmanager
name: {{ .Release.Name }}
spec:
replicaCount: 2
configSecret: alertmanager
configSecret: {{ .Release.Name }}-alertmanager

View File

@@ -1,9 +1,9 @@
{{- range .Values.storages }}
---
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMServiceScrape
metadata:
name: vminsert-vmcluster
namespace: {{ .Release.Namespace }}
name: vminsert-{{ $.Release.Name }}-{{ .name }}
spec:
endpoints:
- path: /metrics
@@ -20,8 +20,7 @@ spec:
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMServiceScrape
metadata:
name: vmselect-vmcluster
namespace: cozy-monitoring
name: vmselect-{{ $.Release.Name }}-{{ .name }}
spec:
endpoints:
- path: /metrics
@@ -38,8 +37,7 @@ spec:
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMServiceScrape
metadata:
name: vmstorage-vmcluster
namespace: cozy-monitoring
name: vmstorage-{{ $.Release.Name }}-{{ .name }}
spec:
endpoints:
- path: /metrics
@@ -52,3 +50,4 @@ spec:
app.kubernetes.io/component: monitoring
app.kubernetes.io/instance: vmcluster
app.kubernetes.io/name: vmstorage
{{- end }}

Some files were not shown because too many files have changed in this diff Show More