Telegram long polling (#2250)

# What this PR does

Runs Telegram long polling to get updates. 
It's enabled by setting `FEATURE_TELEGRAM_LONG_POLLING_ENABLED=True`.
That will disable webhook and run separate deployment for telegram long
polling.

Telegram long polling is not very HA mode, but it does not need to
expose webhook url to internet and simplifies telegram integration.

## Which issue(s) this PR fixes

closes #561 

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
This commit is contained in:
Alexander Cherepanov 2023-08-24 13:12:24 +06:00 committed by GitHub
parent 5a5fb6ea8e
commit ec028eb9d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 586 additions and 7 deletions

View file

@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Public API for webhooks @mderynck ([#2790](https://github.com/grafana/oncall/pull/2790))
- Use Telegram polling protocol instead of a webhook if `FEATURE_TELEGRAM_LONG_POLLING_ENABLED` set to `True` by @alexintech
([#2250](https://github.com/grafana/oncall/pull/2250))
### Changed

View file

@ -18,6 +18,7 @@ REDIS_PROFILE = redis
RABBITMQ_PROFILE = rabbitmq
PROMETHEUS_PROFILE = prometheus
GRAFANA_PROFILE = grafana
TELEGRAM_POLLING_PROFILE = telegram_polling
DEV_ENV_DIR = ./dev
DEV_ENV_FILE = $(DEV_ENV_DIR)/.env.dev

View file

@ -27,7 +27,7 @@ SOCIAL_AUTH_REDIRECT_IS_HTTPS=False
GRAFANA_INCIDENT_STATIC_API_KEY=
GRAFANA_API_URL=http://localhost:3000
CELERY_WORKER_QUEUE="default,critical,long,slack,telegram,webhook,retry,celery"
CELERY_WORKER_QUEUE=default,critical,long,slack,telegram,webhook,retry,celery
CELERY_WORKER_CONCURRENCY=3
CELERY_WORKER_MAX_TASKS_PER_CHILD=100
CELERY_WORKER_SHUTDOWN_INTERVAL=65m

View file

@ -75,6 +75,7 @@ The possible profiles values are:
- `rabbitmq`
- `postgres`
- `mysql`
- `telegram_polling`
The default is `engine,oncall_ui,redis,grafana`. This runs:

View file

@ -81,6 +81,23 @@ services:
profiles:
- engine
oncall_telegram_polling:
container_name: oncall_telegram_polling
labels: *oncall-labels
build: *oncall-build-args
restart: always
user: *oncall-user
command: sh -c "python manage.py start_telegram_polling"
env_file: *oncall-env-files
environment: *oncall-env-vars
volumes: *oncall-volumes
extra_hosts: *oncall-extra-hosts
depends_on:
oncall_db_migration:
condition: service_completed_successfully
profiles:
- telegram_polling
# used to invoke one-off commands, primarily from the Makefile
# oncall_engine couldn't (easily) be used due to it's depends_on property
# we could alternatively just use `docker run` however that would require

View file

@ -178,18 +178,20 @@ frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media
web-share" allowfullscreen></iframe>
The Telegram integration for Grafana OnCall is designed for collaborative team work and improved incident response.
It's available in two options: using Webhooks or Long Polling.
Refer to the following steps to configure the Telegram integration:
1. Ensure your Grafana OnCall environment is up and running.
2. Set `FEATURE_TELEGRAM_INTEGRATION_ENABLED` as "True"
3. Create a Telegram bot using [BotFather](https://t.me/BotFather) and save the token provided by BotFather. Please make
3. (Long Polling only) Set `FEATURE_TELEGRAM_LONG_POLLING_ENABLED` as "True"
4. Create a Telegram bot using [BotFather](https://t.me/BotFather) and save the token provided by BotFather. Please make
sure to disable **Group Privacy** for the bot (Bot Settings -> Group Privacy -> Turn off).
4. Paste the token provided by BotFather to the `TELEGRAM_TOKEN` variable on the **Env Variables** page of your
5. Paste the token provided by BotFather to the `TELEGRAM_TOKEN` variable on the **Env Variables** page of your
Grafana OnCall instance.
5. Set the `TELEGRAM_WEBHOOK_HOST` variable to the external address of your Grafana OnCall instance. Please note
6. (Webhook only) Set the `TELEGRAM_WEBHOOK_HOST` variable to the external address of your Grafana OnCall instance. Please note
that `TELEGRAM_WEBHOOK_HOST` must start with `https://` and be publicly available (meaning that it can be reached by
Telegram servers). If your host is private or local, consider using a reverse proxy (e.g. [ngrok](https://ngrok.com)).
6. Now you can connect Telegram accounts on the **Users** page and receive alert groups to Telegram direct messages.
7. Now you can connect Telegram accounts on the **Users** page and receive alert groups to Telegram direct messages.
Alternatively, in case you want to connect Telegram channels to your Grafana OnCall environment, navigate
to the **ChatOps** tab.

View file

@ -160,3 +160,33 @@ def test_live_settings_telegram_calls_set_webhook_once(
mock_set_webhook.assert_called_once_with(
"TEST_UPDATED_VALUE/telegram/", allowed_updates=("message", "callback_query")
)
@pytest.mark.django_db
def test_live_settings_telegram_set_webhook_not_called_if_long_polling_enabled(
make_organization_and_user_with_plugin_token,
make_user_auth_headers,
make_live_setting,
settings,
):
"""
Check that when FEATURE_TELEGRAM_LONG_POLLING_ENABLED is true setting webhook with updating
TELEGRAM_WEBHOOK_HOST live setting does not evaluate.
"""
settings.FEATURE_LIVE_SETTINGS_ENABLED = True
settings.FEATURE_TELEGRAM_LONG_POLLING_ENABLED = True
organization, user, token = make_organization_and_user_with_plugin_token()
LiveSetting.populate_settings_if_needed()
live_setting = LiveSetting.objects.get(name="TELEGRAM_WEBHOOK_HOST")
client = APIClient()
url = reverse("api-internal:live_settings-detail", kwargs={"pk": live_setting.public_primary_key})
data = {"id": live_setting.public_primary_key, "value": "TEST_UPDATED_VALUE", "name": "TELEGRAM_WEBHOOK_HOST"}
with mock.patch("telegram.Bot.set_webhook") as mock_set_webhook:
response = client.put(url, data=data, format="json", **make_user_auth_headers(user, token))
assert response.status_code == HTTP_200_OK
mock_set_webhook.assert_not_called()

View file

@ -3,6 +3,7 @@ import re
from urllib.parse import urlparse
import phonenumbers
from django.conf import settings
from phonenumbers import NumberParseException
from telegram import Bot
from twilio.base.exceptions import TwilioException
@ -137,6 +138,9 @@ class LiveSettingValidator:
@classmethod
def _check_telegram_webhook_host(cls, telegram_webhook_host):
if settings.FEATURE_TELEGRAM_LONG_POLLING_ENABLED:
return
try:
# avoid circular import
from apps.telegram.client import TelegramClient

View file

@ -46,6 +46,13 @@ class TelegramClient:
self.api_client.set_webhook(webhook_url, allowed_updates=self.ALLOWED_UPDATES)
def delete_webhook(self):
webhook_info = self.api_client.get_webhook_info()
if webhook_info.url == "":
return
self.api_client.delete_webhook()
def send_message(
self,
chat_id: Union[int, str],

View file

@ -28,6 +28,9 @@ logger.setLevel(logging.DEBUG)
)
@handle_missing_token
def register_telegram_webhook(token=None):
if settings.FEATURE_TELEGRAM_LONG_POLLING_ENABLED:
return
telegram_client = TelegramClient(token=token)
try:

View file

@ -57,7 +57,8 @@ def on_after_setup_logger(logger, **kwargs):
def on_worker_ready(*args, **kwargs):
from apps.telegram.tasks import register_telegram_webhook
register_telegram_webhook.delay()
if not settings.FEATURE_TELEGRAM_LONG_POLLING_ENABLED:
register_telegram_webhook.delay()
if settings.OTEL_TRACING_ENABLED and settings.OTEL_EXPORTER_OTLP_ENDPOINT:

View file

@ -0,0 +1,50 @@
import logging
import telegram.error
from django.core.management.base import BaseCommand
from telegram.ext import CallbackQueryHandler, Filters, MessageHandler, Updater
from apps.telegram.client import TelegramClient
from apps.telegram.updates.update_manager import UpdateManager
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def start_telegram_polling():
telegram_client = TelegramClient()
telegram_client.delete_webhook()
updater = Updater(token=telegram_client.token, use_context=True)
# Register the error handler function with the dispatcher
updater.dispatcher.add_error_handler(error_handler)
callback_handler = CallbackQueryHandler(handle_message)
# register the message handler function with the dispatcher
updater.dispatcher.add_handler(MessageHandler(Filters.text, handle_message))
updater.dispatcher.add_handler(callback_handler)
# start the long polling loop
updater.start_polling()
def error_handler(update, context):
try:
raise context.error
except telegram.error.Conflict as e:
logger.warning(f"Tried to getUpdates() using telegram long polling, but conflict exists, got error: {e}")
def handle_message(update, context):
logger.debug(f"Update from Telegram: {update}")
UpdateManager.process_update(update)
class Command(BaseCommand):
def handle(self, *args, **options):
logger.info("Starting telegram polling...")
start_telegram_polling()

View file

@ -59,6 +59,7 @@ BASE_URL = os.environ.get("BASE_URL") # Root URL of OnCall backend
# Feature toggles
FEATURE_LIVE_SETTINGS_ENABLED = getenv_boolean("FEATURE_LIVE_SETTINGS_ENABLED", default=True)
FEATURE_TELEGRAM_INTEGRATION_ENABLED = getenv_boolean("FEATURE_TELEGRAM_INTEGRATION_ENABLED", default=True)
FEATURE_TELEGRAM_LONG_POLLING_ENABLED = getenv_boolean("FEATURE_TELEGRAM_LONG_POLLING_ENABLED", default=False)
FEATURE_EMAIL_INTEGRATION_ENABLED = getenv_boolean("FEATURE_EMAIL_INTEGRATION_ENABLED", default=True)
FEATURE_SLACK_INTEGRATION_ENABLED = getenv_boolean("FEATURE_SLACK_INTEGRATION_ENABLED", default=True)
FEATURE_MULTIREGION_ENABLED = getenv_boolean("FEATURE_MULTIREGION_ENABLED", default=False)

View file

@ -214,7 +214,7 @@ oncall:
`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 tokem and webhook url use:
To set up Telegram token and webhook url use:
```yaml
oncall:
@ -224,6 +224,13 @@ oncall:
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.

View file

@ -95,9 +95,16 @@
{{- 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 }}

View file

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

@ -0,0 +1,44 @@
{{- 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 }}
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: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
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 }}
{{- end -}}

View file

@ -0,0 +1,73 @@
telegramPolling.enabled=true -> should create telegram polling deployment:
1: |
- command:
- sh
- -c
- python manage.py start_telegram_polling
env:
- name: BASE_URL
value: https://example.com
- name: SECRET_KEY
valueFrom:
secretKeyRef:
key: SECRET_KEY
name: oncall
- name: MIRAGE_SECRET_KEY
valueFrom:
secretKeyRef:
key: MIRAGE_SECRET_KEY
name: oncall
- name: MIRAGE_CIPHER_IV
value: 1234567890abcdef
- name: DJANGO_SETTINGS_MODULE
value: settings.helm
- name: AMIXR_DJANGO_ADMIN_PATH
value: admin
- name: OSS
value: "True"
- name: UWSGI_LISTEN
value: "1024"
- name: BROKER_TYPE
value: rabbitmq
- name: GRAFANA_API_URL
value: http://oncall-grafana
- name: FEATURE_TELEGRAM_INTEGRATION_ENABLED
value: "True"
- name: FEATURE_TELEGRAM_LONG_POLLING_ENABLED
value: "True"
- name: TELEGRAM_WEBHOOK_HOST
value: https://example.com
- name: TELEGRAM_TOKEN
value: ""
- name: MYSQL_HOST
value: oncall-mariadb
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_DB_NAME
value: oncall
- name: MYSQL_USER
value: root
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
key: mariadb-root-password
name: oncall-mariadb
- name: RABBITMQ_USERNAME
value: user
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
key: rabbitmq-password
name: oncall-rabbitmq
- name: RABBITMQ_HOST
value: oncall-rabbitmq
- name: RABBITMQ_PORT
value: "5672"
- name: RABBITMQ_PROTOCOL
value: amqp
- name: RABBITMQ_VHOST
value: ""
image: grafana/oncall:v1.3.20
imagePullPolicy: Always
name: telegram-polling
securityContext: {}

View file

@ -141,6 +141,77 @@ database.type=mysql -> should create initContainer for MySQL database (default):
cpu: 100m
memory: 128Mi
securityContext: {}
3: |
- command:
- sh
- -c
- until (python manage.py migrate --check); do echo Waiting for database migrations; sleep 2; done
env:
- name: BASE_URL
value: https://example.com
- name: SECRET_KEY
valueFrom:
secretKeyRef:
key: SECRET_KEY
name: oncall
- name: MIRAGE_SECRET_KEY
valueFrom:
secretKeyRef:
key: MIRAGE_SECRET_KEY
name: oncall
- name: MIRAGE_CIPHER_IV
value: 1234567890abcdef
- name: DJANGO_SETTINGS_MODULE
value: settings.helm
- name: AMIXR_DJANGO_ADMIN_PATH
value: admin
- name: OSS
value: "True"
- name: UWSGI_LISTEN
value: "1024"
- name: BROKER_TYPE
value: rabbitmq
- name: GRAFANA_API_URL
value: http://oncall-grafana
- name: MYSQL_HOST
value: oncall-mariadb
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_DB_NAME
value: oncall
- name: MYSQL_USER
value: root
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
key: mariadb-root-password
name: oncall-mariadb
- name: RABBITMQ_USERNAME
value: user
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
key: rabbitmq-password
name: oncall-rabbitmq
- name: RABBITMQ_HOST
value: oncall-rabbitmq
- name: RABBITMQ_PORT
value: "5672"
- name: RABBITMQ_PROTOCOL
value: amqp
- name: RABBITMQ_VHOST
value: ""
image: grafana/oncall:v1.2.36
imagePullPolicy: Always
name: wait-for-db
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
securityContext: {}
database.type=postgresql -> should create initContainer for PostgreSQL database:
1: |
- command:
@ -288,3 +359,76 @@ database.type=postgresql -> should create initContainer for PostgreSQL database:
cpu: 100m
memory: 128Mi
securityContext: {}
3: |
- command:
- sh
- -c
- until (python manage.py migrate --check); do echo Waiting for database migrations; sleep 2; done
env:
- name: BASE_URL
value: https://example.com
- name: SECRET_KEY
valueFrom:
secretKeyRef:
key: SECRET_KEY
name: oncall
- name: MIRAGE_SECRET_KEY
valueFrom:
secretKeyRef:
key: MIRAGE_SECRET_KEY
name: oncall
- name: MIRAGE_CIPHER_IV
value: 1234567890abcdef
- name: DJANGO_SETTINGS_MODULE
value: settings.helm
- name: AMIXR_DJANGO_ADMIN_PATH
value: admin
- name: OSS
value: "True"
- name: UWSGI_LISTEN
value: "1024"
- name: BROKER_TYPE
value: rabbitmq
- name: GRAFANA_API_URL
value: http://oncall-grafana
- name: DATABASE_TYPE
value: postgresql
- name: DATABASE_HOST
value: some-postgresql-host
- name: DATABASE_PORT
value: "5432"
- name: DATABASE_NAME
value: oncall
- name: DATABASE_USER
value: postgres
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
key: postgres-password
name: oncall-postgresql-external
- name: RABBITMQ_USERNAME
value: user
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
key: rabbitmq-password
name: oncall-rabbitmq
- name: RABBITMQ_HOST
value: oncall-rabbitmq
- name: RABBITMQ_PORT
value: "5672"
- name: RABBITMQ_PROTOCOL
value: amqp
- name: RABBITMQ_VHOST
value: ""
image: grafana/oncall:v1.2.36
imagePullPolicy: Always
name: wait-for-db
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
securityContext: {}

View file

@ -3,11 +3,13 @@ templates:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: env=[] -> should support old syntax
set:
telegramPolling.enabled: true
env:
- name: SOME_VAR
value: some_value
@ -20,6 +22,7 @@ tests:
- it: env=map[] -> should set multiple envs
set:
telegramPolling.enabled: true
env:
SOME_VAR: some_value
another_var: "another_value"
@ -39,7 +42,9 @@ tests:
templates:
- engine/deployment.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
env:
- name: SOME_VAR
value: some_value
@ -54,7 +59,9 @@ tests:
templates:
- engine/deployment.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
env:
SOME_VAR: some_value
another_var: "another_value"
@ -74,7 +81,9 @@ tests:
templates:
- engine/deployment.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: true
env:
@ -96,7 +105,9 @@ tests:
templates:
- engine/deployment.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: true
env:

View file

@ -3,12 +3,15 @@ templates:
- celery/deployment.yaml
- engine/deployment.yaml
- engine/job-migrate.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
chart:
appVersion: 1.2.36
tests:
- it: image={} -> should use default image tag
set:
telegramPolling.enabled: true
asserts:
- equal:
path: spec.template.spec.containers[0].image
@ -19,6 +22,7 @@ tests:
- it: image.repository and image.tag -> should use custom image
set:
telegramPolling.enabled: true
image:
repository: custom-oncall
tag: 1.2.36-custom

View file

@ -3,12 +3,14 @@ templates:
- celery/deployment.yaml
- engine/deployment.yaml
- engine/job-migrate.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: imagePullSecrets=[] -> should not create spec.template.spec.imagePullSecrets
set:
imagePullSecrets: []
telegramPolling.enabled: true
asserts:
- notExists:
path: spec.template.spec.imagePullSecrets
@ -17,6 +19,7 @@ tests:
set:
imagePullSecrets:
- name: regcred
telegramPolling.enabled: true
asserts:
- contains:
path: spec.template.spec.imagePullSecrets

View file

@ -3,11 +3,13 @@ templates:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: mariadb.enabled=false -> external MySQL default settings
set:
telegramPolling.enabled: true
mariadb.enabled: false
asserts:
- contains:
@ -38,6 +40,7 @@ tests:
- it: externalMysql -> use external MySQL custom settings
set:
telegramPolling.enabled: true
mariadb.enabled: false
externalMysql:
host: test-host
@ -67,6 +70,8 @@ tests:
value: test-host
- it: mariadb.enabled=true -> internal MySQL default settings
set:
telegramPolling.enabled: true
asserts:
- contains:
path: spec.template.spec.containers[0].env
@ -91,6 +96,7 @@ tests:
- it: mariadb.auth -> internal MySQL custom settings
set:
telegramPolling.enabled: true
mariadb:
auth:
database: grafana_oncall

View file

@ -5,6 +5,7 @@ templates:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
- secrets.yaml
tests:
- it: secrets -> should fail if externalMysql.password not set
@ -20,7 +21,9 @@ tests:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
mariadb.enabled: false
externalMysql:
user: user123

View file

@ -3,11 +3,13 @@ templates:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: postgresql.enabled=false -> external PostgreSQL default settings
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: false
externalPostgresql.host: custom-postgres-host
@ -40,6 +42,7 @@ tests:
- it: externalPostgresql -> should use external PostgreSQL custom settings
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: false
externalPostgresql:
@ -76,6 +79,7 @@ tests:
- it: postgresql.enabled=true -> internal PostgreSQL default settings
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: true
asserts:
@ -107,6 +111,7 @@ tests:
- it: postgresql.auth -> should use internal PostgreSQL custom settings
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql:
enabled: true

View file

@ -5,6 +5,7 @@ templates:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
- secrets.yaml
tests:
- it: secrets -> should fail if externalPostgresql.password not set
@ -23,7 +24,9 @@ tests:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: false
externalPostgresql:
@ -55,7 +58,9 @@ tests:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: false
externalPostgresql:
@ -77,7 +82,9 @@ tests:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql.enabled: false
externalPostgresql:
@ -99,7 +106,9 @@ tests:
- engine/deployment.yaml
- engine/job-migrate.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
set:
telegramPolling.enabled: true
database.type: postgresql
postgresql:
enabled: true

View file

@ -3,11 +3,13 @@ templates:
- celery/deployment.yaml
- engine/deployment.yaml
- engine/job-migrate.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: podSecurityContext={} -> spec.template.spec.securityContext is empty (default)
set:
telegramPolling.enabled: true
asserts:
- isNullOrEmpty:
path: spec.template.spec.securityContext
@ -16,6 +18,7 @@ tests:
- it: podSecurityContext.runAsNonRoot=true -> should fill securityContext
set:
telegramPolling.enabled: true
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
@ -28,6 +31,7 @@ tests:
- it: securityContext.runAsNonRoot=true -> should fill securityContext for container
set:
telegramPolling.enabled: true
securityContext:
runAsNonRoot: true
runAsUser: 1000

View file

@ -3,10 +3,13 @@ templates:
- celery/deployment.yaml
- engine/deployment.yaml
- engine/job-migrate.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: serviceAccount.create=true -> should use created serviceAccount for deployments (default)
set:
telegramPolling.enabled: true
asserts:
- equal:
path: spec.template.spec.serviceAccountName
@ -14,6 +17,7 @@ tests:
- it: serviceAccount.create=false -> should use default serviceAccount for deployments
set:
telegramPolling.enabled: true
serviceAccount.create: false
asserts:
- equal:
@ -22,6 +26,7 @@ tests:
- it: serviceAccount.name=custom -> should use created custom serviceAccount for deployments
set:
telegramPolling.enabled: true
serviceAccount.name: custom
asserts:
- equal:

View file

@ -2,10 +2,14 @@ suite: test telegram envs for deployments
templates:
- engine/deployment.yaml
- celery/deployment.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: oncall.telegram.enabled=false -> Telegram integration disabled (default)
templates:
- engine/deployment.yaml
- celery/deployment.yaml
asserts:
- contains:
path: spec.template.spec.containers[0].env
@ -14,6 +18,9 @@ tests:
value: "False"
- it: oncall.telegram.enabled=true -> should enable Telegram integration
templates:
- engine/deployment.yaml
- celery/deployment.yaml
set:
oncall.telegram:
enabled: true
@ -37,6 +44,9 @@ tests:
value: "abcd:123"
- it: oncall.telegram.existingSecret=some-secret -> should prefer existing secret over oncall.telegram.token
templates:
- engine/deployment.yaml
- celery/deployment.yaml
set:
oncall.telegram:
enabled: true
@ -52,3 +62,18 @@ tests:
secretKeyRef:
name: some-secret
key: token
- it: telegramPolling.enabled=true -> should enable oncall.telegram.enabled too
set:
telegramPolling.enabled: true
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: FEATURE_TELEGRAM_INTEGRATION_ENABLED
value: "True"
- contains:
path: spec.template.spec.containers[0].env
content:
name: FEATURE_TELEGRAM_LONG_POLLING_ENABLED
value: "True"

View file

@ -0,0 +1,73 @@
suite: test telegram polling deployment
templates:
- telegram-polling/deployment.yaml
release:
name: oncall
tests:
- it: telegramPolling.enabled=false -> should not create deployment (default)
asserts:
- hasDocuments:
count: 0
- it: telegramPolling.enabled=true -> should create telegram polling deployment
set:
telegramPolling.enabled: true
asserts:
- containsDocument:
kind: Deployment
apiVersion: apps/v1
name: oncall-telegram-polling
- isSubset:
path: metadata.labels
content:
app.kubernetes.io/component: telegram-polling
app.kubernetes.io/instance: oncall
app.kubernetes.io/name: oncall
- isSubset:
path: spec.selector.matchLabels
content:
app.kubernetes.io/component: telegram-polling
app.kubernetes.io/instance: oncall
app.kubernetes.io/name: oncall
- isSubset:
path: spec.template.metadata.labels
content:
app.kubernetes.io/component: telegram-polling
app.kubernetes.io/instance: oncall
app.kubernetes.io/name: oncall
# Should contain only one replica to avoid Conflict while polling Telegram updates
- equal:
path: spec.replicas
value: 1
- equal:
path: spec.template.spec.serviceAccountName
value: oncall
- contains:
path: spec.template.spec.initContainers
content:
name: wait-for-db
any: true
- matchSnapshot:
path: spec.template.spec.containers
- it: telegramPolling.resources -> should specify resources
set:
telegramPolling:
enabled: true
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
asserts:
- equal:
path: spec.template.spec.containers[0].resources
value:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi

View file

@ -2,6 +2,7 @@ suite: test init container wait-for-db in deployments
templates:
- celery/deployment.yaml
- engine/deployment.yaml
- telegram-polling/deployment.yaml
release:
name: oncall
chart:
@ -16,6 +17,8 @@ tests:
requests:
cpu: 100m
memory: 128Mi
telegramPolling.enabled: true
database.type: mysql
asserts:
- contains:
path: spec.template.spec.initContainers
@ -32,6 +35,7 @@ tests:
- it: database.type=postgresql -> should create initContainer for PostgreSQL database
set:
telegramPolling.enabled: true
database.type: postgresql
externalPostgresql.host: some-postgresql-host
init.resources:

View file

@ -134,6 +134,17 @@ celery:
# - --port=5432
# - example:europe-west3:grafana-oncall-db
# Telegram polling pod configuration
telegramPolling:
enabled: false
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
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