Merge dev to main (#73)

* Log (failed) attempt to notify a user with viewer role

* Remove old publishing workflow

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Add publishing workflows for next (unreleased) and released documentation

Notable features:
- Merges are blocked by strict Hugo reference checking. However, this
only works for references that resolve within the repository. Once you
have Hugo references to website pages beyond this repository, you will
want to remove this test job.
- Pushes to main are automatically published to "next" documentation
consistent with our other OSS projects.
- Pushes of release tags publish to a versioned directory in the
website. The website uses `v<MAJOR>.<MINOR>.x` versioning and the
"Determine technical documentation version" step will make sure that a
tag such as `v0.20.7` is mapped to `v0.20.x`.
- Pushes to release branches will only be published if there is an
existing corresponding release tag. For example, pushing to a new
release branch `release-0.1000` will not trigger a publish of
documentation until there is a `v0.1000.0` release tag.

> **Note:** I have used a release branch naming convention
`release-<MAJOR>-<MINOR>` which is consistent with grafana/mimir but I
see that in the old amixr repository there are long lived release
branches for patch versions. If that is required. I can update this PR
to support that but I would recommend not including patch versions in
release branch naming unless you have a good reason to do so.

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Add helm chaart installation

* s/mimir/oncall/

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Remove https:// prefix from BASE_URL docker env var

* Fix cloud heartbeat name

* Polishing telegram

* Update docker-compose.yml

* Update plugin README  (#48)

* Update README and screenshot, remove plop for build info since version is now displayed prominently

* Sign build

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Build actions (#38)

* Drone, github action changes

* Minor version updates

* Update frontend dependencies

* Re-enable unit test

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Revert stylelint version (#52)

* Revert stylelint version

* Build plugin as well as lint

* Build in previous step

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Update screenshot (#53)

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* oncall images for docs (#55)

* Fix chart

* Finalise helm chart

* Update README.md

* Top menu fix

* Fix db encoding

* Add api key docs

* Reverting utf8 fix

* bug fixes

* fix for link for OSS version

* Fixing utf8 and docker compose

* 8080 -> 8000 port for consistency

* Improve the helm chart

* makeReq

* Fixing images

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Add last moment improvements

* Fixing port

* Replace symlink with file for CHANGELOG.MD (#68)

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Edit Chart.yaml

* Edit version

* Edit README.md

* Fixing port

* Update README.md

* Fix linting

* image: grafana/oncall

* Merge dev to main (#71)

* Merge dev to main (#54)

* Log (failed) attempt to notify a user with viewer role

* Remove https:// prefix from BASE_URL docker env var

* Fix cloud heartbeat name

* Polishing telegram

* Update docker-compose.yml

* Update plugin README  (#48)

* Update README and screenshot, remove plop for build info since version is now displayed prominently

* Sign build

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Build actions (#38)

* Drone, github action changes

* Minor version updates

* Update frontend dependencies

* Re-enable unit test

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Revert stylelint version (#52)

* Revert stylelint version

* Build plugin as well as lint

* Build in previous step

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Update screenshot (#53)

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

Co-authored-by: Matias Bordese <mbordese@gmail.com>
Co-authored-by: Matvey Kukuy <Matvey-Kuk@users.noreply.github.com>
Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
Co-authored-by: Matvey Kukuy <matvey@amixr.io>
Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Merge dev to main (#69)

* Log (failed) attempt to notify a user with viewer role

* Remove https:// prefix from BASE_URL docker env var

* Fix cloud heartbeat name

* Polishing telegram

* Update docker-compose.yml

* Update plugin README  (#48)

* Update README and screenshot, remove plop for build info since version is now displayed prominently

* Sign build

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Build actions (#38)

* Drone, github action changes

* Minor version updates

* Update frontend dependencies

* Re-enable unit test

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Revert stylelint version (#52)

* Revert stylelint version

* Build plugin as well as lint

* Build in previous step

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* Update screenshot (#53)

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

* oncall images for docs (#55)

* Update README.md

* Top menu fix

* Fix db encoding

* Add api key docs

* Reverting utf8 fix

* bug fixes

* fix for link for OSS version

* Fixing utf8 and docker compose

* 8080 -> 8000 port for consistency

* makeReq

* Fixing images

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Fixing port

* Replace symlink with file for CHANGELOG.MD (#68)

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>

Co-authored-by: Matias Bordese <mbordese@gmail.com>
Co-authored-by: Matvey Kukuy <Matvey-Kuk@users.noreply.github.com>
Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
Co-authored-by: Matvey Kukuy <matvey@amixr.io>
Co-authored-by: Michael Derynck <michael.derynck@grafana.com>
Co-authored-by: Alyssa Wada <101596687+alyssawada@users.noreply.github.com>
Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>

Co-authored-by: Ildar Iskhakov <Ildar.iskhakov@grafana.com>
Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
Co-authored-by: Matias Bordese <mbordese@gmail.com>
Co-authored-by: Matvey Kukuy <Matvey-Kuk@users.noreply.github.com>
Co-authored-by: Matvey Kukuy <matvey@amixr.io>
Co-authored-by: Alyssa Wada <101596687+alyssawada@users.noreply.github.com>
Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>

Co-authored-by: Matias Bordese <mbordese@gmail.com>
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: Ildar Iskhakov <ildar.iskhakov@grafana.com>
Co-authored-by: Matvey Kukuy <Matvey-Kuk@users.noreply.github.com>
Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
Co-authored-by: Matvey Kukuy <matvey@amixr.io>
Co-authored-by: Alyssa Wada <101596687+alyssawada@users.noreply.github.com>
Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>
This commit is contained in:
Michael Derynck 2022-06-14 09:54:41 -06:00 committed by GitHub
parent 846b898bb9
commit 4572131951
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 1280 additions and 46 deletions

View file

@ -0,0 +1,42 @@
name: "publish-technical-documentation-next"
on:
push:
branches:
- "main"
paths:
- "docs/sources/**"
workflow_dispatch:
jobs:
test:
runs-on: "ubuntu-latest"
steps:
- name: "Check out code"
uses: "actions/checkout@v3"
- name: "Build website"
# -e HUGO_REFLINKSERRORLEVEL=ERROR prevents merging broken refs with the downside
# that no refs to external content can be used as these refs will not resolve in the
# docs-base image.
run: |
docker run -v ${PWD}/docs/sources:/hugo/content/docs/oncall/latest -e HUGO_REFLINKSERRORLEVEL=ERROR --rm grafana/docs-base:latest /bin/bash -c 'make hugo'
sync:
runs-on: "ubuntu-latest"
needs: "test"
steps:
- name: "Check out code"
uses: "actions/checkout@v3"
- name: "Clone website-sync Action"
run: "git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.GH_BOT_ACCESS_TOKEN }}@github.com/grafana/website-sync ./.github/actions/website-sync"
- name: "Publish to website repository (next)"
uses: "./.github/actions/website-sync"
id: "publish-next"
with:
repository: "grafana/website"
branch: "master"
host: "github.com"
github_pat: "${{ secrets.GH_BOT_ACCESS_TOKEN }}"
source_folder: "docs/sources"
target_folder: "content/docs/oncall/next"

View file

@ -0,0 +1,74 @@
name: "publish-technical-documentation-release"
on:
push:
branches:
- "release-*"
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
paths:
- "docs/sources/**"
workflow_dispatch:
jobs:
test:
runs-on: "ubuntu-latest"
steps:
- name: "Check out code"
uses: "actions/checkout@v3"
- name:
"Build website"
# -e HUGO_REFLINKSERRORLEVEL=ERROR prevents merging broken refs with the downside
# that no refs to external content can be used as these refs will not resolve in the
# docs-base image.
run: |
docker run -v ${PWD}/docs/sources:/hugo/content/docs/oncall/latest -e HUGO_REFLINKSERRORLEVEL=ERROR --rm grafana/docs-base:latest /bin/bash -c 'make hugo'
sync:
runs-on: "ubuntu-latest"
needs: "test"
steps:
- name: "Checkout code and tags"
uses: "actions/checkout@v3"
with:
fetch-depth: 0
- name: "Checkout Actions library"
uses: "actions/checkout@v3"
with:
repository: "grafana/grafana-github-actions"
path: "./actions"
- name: "Install Actions from library"
run: "npm install --production --prefix ./actions"
- name: "Determine if there is a matching release tag"
id: "has-matching-release-tag"
uses: "./actions/has-matching-release-tag"
with:
ref_name: "${{ github.ref_name }}"
release_tag_regexp: "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
release_branch_regexp: "^release-(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
- name: "Determine technical documentation version"
if: "steps.has-matching-release-tag.outputs.bool == 'true'"
uses: "./actions/docs-target"
id: "target"
with:
ref_name: "${{ github.ref_name }}"
- name: "Clone website-sync Action"
if: "steps.has-matching-release-tag.outputs.bool == 'true'"
run: "git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.GH_BOT_ACCESS_TOKEN }}@github.com/grafana/website-sync ./.github/actions/website-sync"
- name: "Publish to website repository (release)"
if: "steps.has-matching-release-tag.outputs.bool == 'true'"
uses: "./.github/actions/website-sync"
id: "publish-release"
with:
repository: "grafana/website"
branch: "master"
host: "github.com"
github_pat: "${{ secrets.GH_BOT_ACCESS_TOKEN }}"
source_folder: "docs/sources"
# Append ".x" to target to produce a v<major>.<minor>.x directory.
target_folder: "content/docs/oncall/${{ steps.target.outputs.target }}.x"

View file

@ -1,40 +0,0 @@
name: publish_docs
on:
pull_request:
push:
branches:
- main
paths:
- 'docs/sources/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v1
- name: Build Website
run: |
docker run -v ${PWD}/sources:/hugo/content/docs/amixr --rm grafana/docs-base:latest /bin/bash -c 'make hugo'
# sync:
# runs-on: ubuntu-latest
# needs: test
# if: github.ref == 'refs/heads/main'
# steps:
# - uses: actions/checkout@v1
# - run: git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.GH_BOT_ACCESS_TOKEN }}@github.com/grafana/website-sync ./.github/actions/website-sync
# - name: publish-to-git
# uses: ./.github/actions/website-sync
# id: publish
# with:
# repository: grafana/website
# branch: master
# host: github.com
# github_pat: '${{ secrets.GH_BOT_ACCESS_TOKEN }}'
# source_folder: docs/sources
# target_folder: content/docs/amixr/v0.0.39
# - shell: bash
# run: |
# test -n "${{ steps.publish.outputs.commit_hash }}"
# test -n "${{ steps.publish.outputs.working_directory }}"

View file

@ -15,7 +15,7 @@ We prepared multiple environments: [production](https://grafana.com/docs/grafana
1. Download docker-compose.yaml:
```bash
curl https://github.com/grafana/oncall/blob/dev/docker-compose.yml -o docker-compose.yaml
curl -fsSL https://raw.githubusercontent.com/grafana/oncall/dev/docker-compose.yml -o docker-compose.yaml
```
2. Set variables:

View file

@ -1,8 +1,6 @@
services:
engine:
# TODO: change to the public image once it's public
# image: ...
build: engine
image: grafana/oncall
ports:
- 8080:8080
command: >
@ -36,7 +34,7 @@ services:
celery:
# TODO: change to the public image once it's public
build: engine
image: grafana/oncall
command: sh -c "./celery_with_exporter.sh"
environment:
BASE_URL: $DOMAIN
@ -70,7 +68,7 @@ services:
condition: service_started
oncall_db_migration:
build: engine
image: grafana/oncall
command: python manage.py migrate --noinput
environment:
BASE_URL: $DOMAIN

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 KiB

85
engine/settings/helm.py Normal file
View file

@ -0,0 +1,85 @@
import os
import sys
# Workaround to use pymysql instead of mysqlclient
import pymysql
from .prod_without_db import * # noqa
pymysql.install_as_MySQLdb()
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": os.environ.get("MYSQL_DB_NAME"),
"USER": os.environ.get("MYSQL_USER"),
"PASSWORD": os.environ["MYSQL_PASSWORD"],
"HOST": os.environ.get("MYSQL_HOST"),
"PORT": os.environ.get("MYSQL_PORT"),
"OPTIONS": {
"charset": "utf8mb4",
"connect_timeout": 1,
},
},
}
RABBITMQ_USERNAME = os.environ.get("RABBITMQ_USERNAME")
RABBITMQ_PASSWORD = os.environ.get("RABBITMQ_PASSWORD")
RABBITMQ_HOST = os.environ.get("RABBITMQ_HOST")
RABBITMQ_PORT = os.environ.get("RABBITMQ_PORT")
CELERY_BROKER_URL = f"amqp://{RABBITMQ_USERNAME}:{RABBITMQ_PASSWORD}@{RABBITMQ_HOST}:{RABBITMQ_PORT}"
REDIS_PASSWORD = os.environ.get("REDIS_PASSWORD")
REDIS_HOST = os.environ.get("REDIS_HOST")
REDIS_PORT = os.environ.get("REDIS_PORT", "6379")
REDIS_URI = f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}"
CACHES = {
"default": {
"BACKEND": "redis_cache.RedisCache",
"LOCATION": [
REDIS_URI,
],
"OPTIONS": {
"DB": 1,
"PARSER_CLASS": "redis.connection.HiredisParser",
"CONNECTION_POOL_CLASS": "redis.BlockingConnectionPool",
"CONNECTION_POOL_CLASS_KWARGS": {
"max_connections": 50,
"timeout": 20,
},
"MAX_CONNECTIONS": 1000,
"PICKLE_VERSION": -1,
},
},
}
APPEND_SLASH = False
SECURE_SSL_REDIRECT = False
TESTING = "pytest" in sys.modules or "unittest" in sys.modules
if TESTING:
TELEGRAM_TOKEN = "0000000000:XXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXX"
TWILIO_AUTH_TOKEN = "twilio_auth_token"
# TODO: OSS: Add these setting to oss settings file. Add Version there too.
OSS_INSTALLATION_FEATURES_ENABLED = True
INSTALLED_APPS += ["apps.oss_installation"] # noqa
CELERY_BEAT_SCHEDULE["send_usage_stats"] = { # noqa
"task": "apps.oss_installation.tasks.send_usage_stats_report",
"schedule": crontab(hour=0, minute=randrange(0, 59)), # Send stats report at a random minute past midnight # noqa
"args": (),
} # noqa
CELERY_BEAT_SCHEDULE["send_cloud_heartbeat"] = { # noqa
"task": "apps.oss_installation.tasks.send_cloud_heartbeat",
"schedule": crontab(minute="*/3"), # noqa
"args": (),
} # noqa
SEND_ANONYMOUS_USAGE_STATS = True

23
helm/oncall/.helmignore Normal file
View file

@ -0,0 +1,23 @@
# 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/

43
helm/oncall/Chart.yaml Normal file
View file

@ -0,0 +1,43 @@
apiVersion: v2
name: oncall
description: Developer-friendly incident response with brilliant Slack integration
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v1.0.0"
dependencies:
- name: cert-manager
version: v1.8.0
repository: https://charts.jetstack.io
condition: cert-manager.enabled
- name: mariadb
version: 11.0.10
repository: https://charts.bitnami.com/bitnami
condition: mariadb.enabled
- name: rabbitmq
version: 10.1.1
repository: https://charts.bitnami.com/bitnami
condition: rabbitmq.enabled
- name: redis
version: 16.10.1
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled
- name: grafana
version: 6.29.6
repository: https://grafana.github.io/helm-charts
condition: grafana.enabled
- name: ingress-nginx
version: 4.1.4
repository: https://kubernetes.github.io/ingress-nginx
condition: ingress-nginx.enabled

120
helm/oncall/README.md Normal file
View file

@ -0,0 +1,120 @@
# 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)
> 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
Cluster requirements:
* ensure you can run x86-64/amd64 workloads. arm64 architecture is currently not supported
## Install
### Installing the helm chart
```bash
helm install \
--wait \
--set base_url=example.com \
--set grafana."grafana\.ini".server.domain=example.com \
oncall \
.
```
Follow the `helm install` output to finish setting up Grafana OnCall backend and Grafana OnCall frontend plugin
## 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 \
oncall \
.
```
### 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
```
nginx-ingress:
enabled: false
cert-manager:
enabled: false
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/issuer: "letsencrypt-prod"
```
### 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
```
CREATE DATABASE oncall CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```
To use an external MySQL instance set mysql.enabled to `false` and configure the `externalMysql` parameters.
```
mariadb:
enabled: true
# 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:
```
### 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.
```
rabbitmq:
enabled: false # Disable the RabbitMQ dependency from the release
externalRabbitmq:
host:
port:
user:
password:
```
## Uninstall
### Uninstalling the helm chart
```bash
helm delete oncall
```
### Clean up PVC's
```bash
kubectl delete pvc data-oncall-mariadb-0 data-oncall-rabbitmq-0 \
redis-data-oncall-redis-master-0 redis-data-oncall-redis-replicas-0 \
redis-data-oncall-redis-replicas-1 redis-data-oncall-redis-replicas-2
```
### Clean up secrets
```bash
kubectl delete secrets certificate-tls oncall-cert-manager-webhook-ca oncall-ingress-nginx-admission
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,54 @@
=================================================================
📞 Grafana OnCall Notes
=================================================================
👋 Your Grafana OnCall instance has been successfully deployed
TODO: Add disclaimer about stateful services, ingress controller, certificates
{{- 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:
Issue the one-time token to connect Grafana OnCall backend and Grafana OnCall plugin by running 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 -- bash -c "python manage.py issue_invite_for_the_frontend --override"
Fill the Grafana OnCall Backend URL:
http://{{ include "oncall.engine.fullname" . }}:8080
Fill the Grafana URL:
{{ if .Values.grafana.enabled }}http://{{ include "oncall.grafana.fullname" . }}{{ else }}https://<external-grafana>{{- end }}
🎉🎉🎉 Done! 🎉🎉🎉

View file

@ -0,0 +1,165 @@
{{- define "snippet.oncall.env" -}}
- name: BASE_URL
value: https://{{ .Values.base_url }}
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ template "oncall.fullname" . }}
key: SECRET_KEY
- name: MIRAGE_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ template "oncall.fullname" . }}
key: MIRAGE_SECRET_KEY
- name: MIRAGE_CIPHER_IV
value: "1234567890abcdef"
- name: DJANGO_SETTINGS_MODULE
value: "settings.helm"
- name: AMIXR_DJANGO_ADMIN_PATH
value: "admin"
- name: OSS
value: "True"
{{- end }}
{{- define "snippet.celery.env" -}}
- name: CELERY_WORKER_QUEUE
value: "default,critical,long,slack,telegram,webhook,celery"
- name: CELERY_WORKER_CONCURRENCY
value: "1"
- name: CELERY_WORKER_MAX_TASKS_PER_CHILD
value: "100"
- name: CELERY_WORKER_SHUTDOWN_INTERVAL
value: "65m"
- name: CELERY_WORKER_BEAT_ENABLED
value: "True"
{{- end }}
{{- define "snippet.mysql.env" -}}
- name: MYSQL_HOST
value: {{ include "snippet.mysql.host" . }}
- name: MYSQL_PORT
value: {{ include "snippet.mysql.port" . }}
- name: MYSQL_DB_NAME
value: {{ include "snippet.mysql.db" . }}
- name: MYSQL_USER
value: {{ include "snippet.mysql.user" . }}
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.mysql.password.secret.name" . }}
key: mariadb-root-password
{{- end }}
{{- define "snippet.mysql.password.secret.name" -}}
{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.password -}}
{{ include "oncall.fullname" . }}-mysql-external
{{- else -}}
{{ include "oncall.mariadb.fullname" . }}
{{- end -}}
{{- end -}}
{{- define "snippet.mysql.host" -}}
{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.host -}}
{{- required "externalMysql.host is required if not mariadb.enabled" .Values.externalMysql.host | quote }}
{{- else -}}
{{ include "oncall.mariadb.fullname" . }}
{{- end -}}
{{- end -}}
{{- define "snippet.mysql.port" -}}
{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.port -}}
{{- required "externalMysql.port is required if not mariadb.enabled" .Values.externalMysql.port | quote }}
{{- else -}}
"3306"
{{- end -}}
{{- end -}}
{{- define "snippet.mysql.db" -}}
{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.db -}}
{{- required "externalMysql.db is required if not mariadb.enabled" .Values.externalMysql.db | quote}}
{{- else -}}
"oncall"
{{- end -}}
{{- end -}}
{{- define "snippet.mysql.user" -}}
{{- if and (not .Values.mariadb.enabled) .Values.externalMysql.user -}}
{{- .Values.externalMysql.user | quote}}
{{- else -}}
"root"
{{- end -}}
{{- end -}}
{{- define "snippet.rabbitmq.env" -}}
- name: RABBITMQ_USERNAME
value: {{ include "snippet.rabbitmq.user" . }}
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.rabbitmq.password.secret.name" . }}
key: rabbitmq-password
- name: RABBITMQ_HOST
value: {{ include "snippet.rabbitmq.host" . }}
- name: RABBITMQ_PORT
value: {{ include "snippet.rabbitmq.port" . }}
{{- end }}
{{- define "snippet.rabbitmq.user" -}}
{{- if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.user -}}
{{- required "externalRabbitmq.user is required if not rabbitmq.enabled" .Values.externalRabbitmq.user | quote }}
{{- else -}}
"user"
{{- end -}}
{{- end -}}
{{- define "snippet.rabbitmq.host" -}}
{{- if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.host -}}
{{- required "externalRabbitmq.host is required if not rabbitmq.enabled" .Values.externalRabbitmq.host | quote }}
{{- 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 | quote }}
{{- else -}}
"5672"
{{- end -}}
{{- end -}}
{{- define "snippet.rabbitmq.password.secret.name" -}}
{{- if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.password -}}
{{ include "oncall.fullname" . }}-rabbitmq-external
{{- else -}}
{{ include "oncall.rabbitmq.fullname" . }}
{{- end -}}
{{- end -}}
{{- define "snippet.redis.host" -}}
{{- if and (not .Values.redis.enabled) .Values.externalRedis.host -}}
{{- required "externalRedis.host is required if not redis.enabled" .Values.externalRedis.host | quote }}
{{- else -}}
{{ include "oncall.redis.fullname" . }}-master
{{- end -}}
{{- end -}}
{{- define "snippet.redis.password.secret.name" -}}
{{- if and (not .Values.redis.enabled) .Values.externalRedis.password -}}
{{ include "oncall.fullname" . }}-redis-external
{{- else -}}
{{ include "oncall.redis.fullname" . }}
{{- end -}}
{{- end -}}
{{- define "snippet.redis.env" -}}
- name: REDIS_HOST
value: {{ include "snippet.redis.host" . }}
- name: REDIS_PORT
value: "6379"
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "snippet.redis.password.secret.name" . }}
key: redis-password
{{- end }}

View file

@ -0,0 +1,96 @@
{{/*
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 }}
{{- 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 }}
{{- define "oncall.mariadb.wait-for-db" }}
- 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"]
env:
{{- include "snippet.oncall.env" . | nindent 12 }}
{{- include "snippet.mysql.env" . | nindent 12 }}
{{- include "snippet.rabbitmq.env" . | nindent 12 }}
{{- include "snippet.redis.env" . | nindent 12 }}
{{- if .Values.env }}
{{- toYaml .Values.env | nindent 12 }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,60 @@
{{- define "template.oncall.celery.deployment" -}}
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 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "oncall.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
{{- include "oncall.mariadb.wait-for-db" . | indent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
command: ["./celery_with_exporter.sh"]
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
{{- include "snippet.celery.env" . | nindent 12 }}
{{- include "snippet.oncall.env" . | nindent 12 }}
{{- include "snippet.mysql.env" . | nindent 12 }}
{{- include "snippet.rabbitmq.env" . | nindent 12 }}
{{- include "snippet.redis.env" . | nindent 12 }}
{{- if .Values.env }}
{{- toYaml .Values.env | nindent 12 }}
{{- end }}
livenessProbe:
exec:
command: [
"bash",
"-c",
"celery inspect ping -A engine -d celery@$HOSTNAME"
]
initialDelaySeconds: 30
periodSeconds: 300
timeoutSeconds: 10
resources:
{{- toYaml .Values.celery.resources | nindent 12 }}
{{- end}}

View file

@ -0,0 +1,26 @@
{{/*
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

@ -0,0 +1 @@
{{ include "template.oncall.celery.deployment" . }}

View file

@ -0,0 +1,22 @@
{{- if (index .Values "cert-manager") }}
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

@ -0,0 +1,26 @@
{{/*
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

@ -0,0 +1,73 @@
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:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
random-annotation: {{ randAlphaNum 10 | lower }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "oncall.engine.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.mariadb.wait-for-db" . | indent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
{{- include "snippet.oncall.env" . | nindent 12 }}
{{- include "snippet.mysql.env" . | nindent 12 }}
{{- include "snippet.rabbitmq.env" . | nindent 12 }}
{{- include "snippet.redis.env" . | nindent 12 }}
{{- if .Values.env }}
{{- toYaml .Values.env | nindent 12 }}
{{- end }}
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: 60
timeoutSeconds: 3
resources:
{{- toYaml .Values.engine.resources | nindent 12 }}

View file

@ -0,0 +1,54 @@
{{- if .Values.migrate.enabled -}}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ printf "%s-migrate-%s" (include "oncall.engine.fullname" .) (now | date "2006-01-02-15-04-05") }}
labels:
{{- include "oncall.engine.labels" . | nindent 4 }}
spec:
ttlSecondsAfterFinished: 20
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 }}
containers:
- name: {{ .Chart.Name }}-migrate
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- /bin/sh
- -c
- |
until (nc -vz $MYSQL_HOST $MYSQL_PORT);
do
echo "waiting for MySQL"; sleep 1;
done
python manage.py migrate
env:
{{- include "snippet.oncall.env" . | nindent 12 }}
{{- include "snippet.mysql.env" . | nindent 12 }}
{{- include "snippet.rabbitmq.env" . | nindent 12 }}
{{- include "snippet.redis.env" . | nindent 12 }}
{{- if .Values.env }}
{{- toYaml .Values.env | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.engine.resources | nindent 12 }}
{{- end }}

View file

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

View file

@ -0,0 +1,15 @@
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

@ -0,0 +1,48 @@
{{- 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:
tls:
- hosts:
- {{ .Values.base_url | quote }}
secretName: certificate-tls
rules:
- host: {{ .Values.base_url | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "oncall.engine.fullname" . }}
port:
number: 8080
- path: /grafana
pathType: Prefix
backend:
service:
name: {{ include "oncall.grafana.fullname" . }}
port:
number: 80
{{- end }}

View file

@ -0,0 +1,43 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}
labels:
{{- include "oncall.labels" . | nindent 4 }}
type: Opaque
data:
SECRET_KEY: {{ randAlphaNum 40 | b64enc | quote }}
MIRAGE_SECRET_KEY: {{ randAlphaNum 40 | b64enc | quote }}
MIRAGE_CIPHER_IV: {{ randAlphaNum 40 | b64enc | quote }}
---
{{ if not .Values.mariadb.enabled -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-mysql-external
type: Opaque
data:
mariadb-root-password: {{ required "externalMysql.password is required if not mariadb.enabled" .Values.externalMysql.password | b64enc | quote }}
{{- end }}
---
{{ if not .Values.rabbitmq.enabled -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-rabbitmq-external
type: Opaque
data:
rabbitmq-password: {{ required "externalRabbitmq.password is required if not rabbitmq.enabled" .Values.externalRabbitmq.password | b64enc | quote }}
{{- end }}
---
{{ if not .Values.redis.enabled -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "oncall.fullname" . }}-redis-external
type: Opaque
data:
rabbitmq-password: {{ required "externalRedis.password is required if not redis.enabled" .Values.externalRedis.password | b64enc | quote }}
{{- end }}

View file

@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "oncall.serviceAccountName" . }}
labels:
{{- include "oncall.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "oncall.fullname" . }}-test-connection"
labels:
{{- include "oncall.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "oncall.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

162
helm/oncall/values.yaml Normal file
View file

@ -0,0 +1,162 @@
# 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
image:
# Grafana OnCall docker image repository
repository: grafana/oncall
tag:
pullPolicy: IfNotPresent
# Whether to create additional service for external connections
# ClusterIP service is always created
service:
enabled: false
type: LoadBalancer
port: 8080
# Engine pods configuration
engine:
replicaCount: 1
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Celery workers pods configuration
celery:
replicaCount: 1
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Whether to run django database migrations automatically
migrate:
enabled: true
# 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"
# Whether to install ingress controller
nginx-ingress:
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
# 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
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:
# 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
externalRabbitmq:
host:
port:
user:
password:
redis:
enabled: true
external_redis:
host:
password:
grafana:
enabled: true
grafana.ini:
server:
domain: example.com
root_url: "%(protocol)s://%(domain)s/grafana"
serve_from_sub_path: true
persistence:
enabled: true
plugins:
- grafana-oncall-app
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
# runAsUser: 1000