Merge branch 'dev' into web-schedules-fixes-bunch-3

This commit is contained in:
Maxim Mordasov 2022-11-03 16:09:43 +00:00 committed by GitHub
commit 29b49ea1a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 151 additions and 14 deletions

View file

@ -76,9 +76,13 @@ def notify_user_async(user_pk, alert_group_pk, notification_policy_pk):
subject, html_message = build_subject_and_message(alert_group, emails_left)
message = strip_tags(html_message)
email_from = settings.EMAIL_HOST_USER
recipient_list = [user.email]
if settings.LICENSE == settings.CLOUD_LICENSE_NAME:
email_from = "oncall@{}.grafana.net".format(user.organization.stack_slug)
else:
email_from = live_settings.EMAIL_HOST_USER
connection = get_connection(
host=live_settings.EMAIL_HOST,
port=live_settings.EMAIL_PORT,

View file

@ -155,3 +155,72 @@ def test_notify_user_no_emails_left(
log_record = notification_policy.personal_log_records.last()
assert log_record.type == UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED
assert log_record.notification_error_code == UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_MAIL_LIMIT_EXCEEDED
@pytest.mark.django_db
def test_notify_user_from_email_oss(
settings,
make_organization,
make_user_for_organization,
make_token_for_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
make_user_notification_policy,
):
settings.LICENSE = settings.OPEN_SOURCE_LICENSE_NAME
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = "test"
settings.EMAIL_HOST_USER = "test@test.com"
organization = make_organization(stack_slug="example")
user = make_user_for_organization(organization)
alert_receive_channel = make_alert_receive_channel(organization)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group=alert_group, raw_request_data=alert_receive_channel.config.example_payload)
notification_policy = make_user_notification_policy(
user,
UserNotificationPolicy.Step.NOTIFY,
notify_by=8,
important=False,
)
notify_user_async(user.pk, alert_group.pk, notification_policy.pk)
assert mail.outbox[0].from_email == "test@test.com"
@pytest.mark.django_db
def test_notify_user_from_email_cloud(
settings,
make_organization,
make_user_for_organization,
make_token_for_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
make_user_notification_policy,
):
settings.LICENSE = settings.CLOUD_LICENSE_NAME
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = "test"
organization = make_organization(stack_slug="slug")
user = make_user_for_organization(organization)
alert_receive_channel = make_alert_receive_channel(organization)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group=alert_group, raw_request_data=alert_receive_channel.config.example_payload)
notification_policy = make_user_notification_policy(
user,
UserNotificationPolicy.Step.NOTIFY,
notify_by=8,
important=False,
)
notify_user_async(user.pk, alert_group.pk, notification_policy.pk)
assert mail.outbox[0].from_email == "oncall@slug.grafana.net"

View file

@ -0,0 +1,33 @@
# Generated by Django 3.2.15 on 2022-10-25 03:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('user_management', '0003_user_hide_phone_number'),
]
operations = [
migrations.CreateModel(
name='Region',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300)),
('slug', models.CharField(max_length=50, unique=True)),
('oncall_backend_url', models.URLField(null=True)),
],
),
migrations.AddField(
model_name='organization',
name='region_slug',
field=models.CharField(default=None, max_length=300, null=True),
),
migrations.AddField(
model_name='organization',
name='migration_destination',
field=models.ForeignKey(db_column='migration_destination_slug', default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='regions', to='user_management.region', to_field='slug'),
),
]

View file

@ -23,19 +23,21 @@ class RequestTimeLoggingMiddleware(MiddlewareMixin):
seconds = (dt - request._logging_start_dt).total_seconds()
status_code = 0 if response is None else response.status_code
content_length = request.headers.get("content-length", default=0)
integration_type = "N/A"
integration_token = "N/A"
message = (
"inbound "
f"latency={str(seconds)} status={status_code} method={request.method} path={request.path} "
f"content-length={content_length} slow={int(seconds > settings.SLOW_THRESHOLD_SECONDS)} "
)
if hasattr(request, "user") and request.user and request.user.id:
user_id = request.user.id
org_id = request.user.organization_id
message += f"user_id={user_id} org_id={org_id} "
if request.path.startswith("/integrations/v1"):
split_path = request.path.split("/")
integration_type = split_path[3]
integration_token = split_path[4]
logging.info(
"inbound "
f"latency={str(seconds)} status={status_code} method={request.method} path={request.path} "
f"content-length={content_length} slow={int(seconds > settings.SLOW_THRESHOLD_SECONDS)} "
f"integration_type={integration_type} "
f"integration_token={integration_token}"
)
message += f"integration_type={integration_type} integration_token={integration_token} "
logging.info(message)
def process_request(self, request):
self.log_message(request, None, "request")

View file

@ -8,7 +8,7 @@ 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: 1.0.7
version: 1.0.8
# 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

View file

@ -224,6 +224,11 @@ externalRabbitmq:
port:
user:
password:
protocol:
vhost:
existingSecret: ""
passwordKey: password
usernameKey: username
```
### Connect external Redis

View file

@ -237,13 +237,21 @@
{{- define "snippet.rabbitmq.env" -}}
{{- if eq .Values.broker.type "rabbitmq" -}}
{{- if and (not .Values.rabbitmq.enabled) (not .Values.externalRabbitmq.existingSecret) (not .Values.externalRabbitmq.usernameKey) .Values.externalRabbitmq.user }}
- name: RABBITMQ_USERNAME
value: {{ include "snippet.rabbitmq.user" . }}
{{- else if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.existingSecret .Values.externalRabbitmq.usernameKey (not .Values.externalRabbitmq.user) }}
- name: RABBITMQ_USERNAME
valueFrom:
secretKeyRef:
name: {{ include "snippet.rabbitmq.password.secret.name" . }}
key: {{ .Values.externalRabbitmq.usernameKey }}
{{- end }}
- name: RABBITMQ_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "snippet.rabbitmq.password.secret.name" . }}
key: rabbitmq-password
key: {{ include "snippet.rabbitmq.password.secret.key" . }}
- name: RABBITMQ_HOST
value: {{ include "snippet.rabbitmq.host" . }}
- name: RABBITMQ_PORT
@ -298,11 +306,21 @@
{{- define "snippet.rabbitmq.password.secret.name" -}}
{{- if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.password -}}
{{ include "oncall.fullname" . }}-rabbitmq-external
{{- else if and (not .Values.rabbitmq.enabled) .Values.externalRabbitmq.existingSecret -}}
{{ .Values.externalRabbitmq.existingSecret }}
{{- else -}}
{{ include "oncall.rabbitmq.fullname" . }}
{{- 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.host" -}}
{{- if and (not .Values.redis.enabled) .Values.externalRedis.host -}}
{{- required "externalRedis.host is required if not redis.enabled" .Values.externalRedis.host | quote }}

View file

@ -21,14 +21,14 @@ data:
mariadb-root-password: {{ required "externalMysql.password is required if not mariadb.enabled" .Values.externalMysql.password | b64enc | quote }}
{{- end }}
---
{{ if and (eq .Values.broker.type "rabbitmq") (not .Values.rabbitmq.enabled) -}}
{{ 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
type: Opaque
data:
rabbitmq-password: {{ required "externalRabbitmq.password is required if not rabbitmq.enabled" .Values.externalRabbitmq.password | b64enc | quote }}
rabbitmq-password: {{ required "externalRabbitmq.password is required if not rabbitmq.enabled and not externalRabbitmq.existingSecret" .Values.externalRabbitmq.password | b64enc | quote }}
{{- end }}
---
{{ if not .Values.redis.enabled -}}

View file

@ -239,6 +239,12 @@ externalRabbitmq:
password:
protocol:
vhost:
# use an existing secret for the rabbitmq password
existingSecret: ""
# the key in the secret containing the rabbitmq password
passwordKey: password
# 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