chore: remove deprecated slack_channel and heartbeat integration types (#5270)

# What this PR does

See [Slack
discussion](https://raintank-corp.slack.com/archives/C06K1MQ07GS/p1732110700877869)
for more context

## 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] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
This commit is contained in:
Joey Orlando 2024-11-20 11:17:04 -05:00 committed by GitHub
parent 336b924a08
commit fda05a6cc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 33 additions and 133 deletions

View file

@ -39,7 +39,7 @@ engine:
replicaCount: 1 replicaCount: 1
celery: celery:
replicaCount: 1 replicaCount: 1
worker_beat_enabled: false worker_beat_enabled: true
externalGrafana: externalGrafana:
url: http://grafana:3000 url: http://grafana:3000

View file

@ -525,29 +525,21 @@ class AlertReceiveChannel(IntegrationOptionsMixin, MaintainableObject):
) )
@property @property
def short_name_with_maintenance_status(self): def created_name(self) -> str:
if self.maintenance_mode is not None:
return (
self.short_name + f" *[ on "
f"{AlertReceiveChannel.MAINTENANCE_MODE_CHOICES[self.maintenance_mode][1]}"
f" :construction: ]*"
)
else:
return self.short_name
@property
def created_name(self):
return f"{self.get_integration_display()} {self.smile_code}" return f"{self.get_integration_display()} {self.smile_code}"
@property @property
def web_link(self) -> str: def web_link(self) -> str:
return UIURLBuilder(self.organization).integration_detail(self.public_primary_key) return UIURLBuilder(self.organization).integration_detail(self.public_primary_key)
@property
def is_maintenace_integration(self) -> bool:
return self.integration == AlertReceiveChannel.INTEGRATION_MAINTENANCE
@property @property
def integration_url(self) -> str | None: def integration_url(self) -> str | None:
if self.integration in [ if self.integration in [
AlertReceiveChannel.INTEGRATION_MANUAL, AlertReceiveChannel.INTEGRATION_MANUAL,
AlertReceiveChannel.INTEGRATION_SLACK_CHANNEL,
AlertReceiveChannel.INTEGRATION_INBOUND_EMAIL, AlertReceiveChannel.INTEGRATION_INBOUND_EMAIL,
AlertReceiveChannel.INTEGRATION_MAINTENANCE, AlertReceiveChannel.INTEGRATION_MAINTENANCE,
]: ]:

View file

@ -0,0 +1,23 @@
# Generated by Django 4.2.16 on 2024-11-20 15:39
from django.db import migrations
import django_migration_linter as linter
class Migration(migrations.Migration):
dependencies = [
('heartbeat', '0002_delete_heartbeat'),
]
operations = [
linter.IgnoreMigration(),
migrations.RemoveField(
model_name='integrationheartbeat',
name='actual_check_up_task_id',
),
migrations.RemoveField(
model_name='integrationheartbeat',
name='last_checkup_task_time',
),
]

View file

@ -48,16 +48,6 @@ class IntegrationHeartBeat(models.Model):
Stores the latest received heartbeat signal time Stores the latest received heartbeat signal time
""" """
last_checkup_task_time = models.DateTimeField(default=None, null=True)
"""
Deprecated. This field is not used. TODO: remove it
"""
actual_check_up_task_id = models.CharField(max_length=100)
"""
Deprecated. Stored the latest scheduled `integration_heartbeat_checkup` task id. TODO: remove it
"""
previous_alerted_state_was_life = models.BooleanField(default=True) previous_alerted_state_was_life = models.BooleanField(default=True)
""" """
Last status of the heartbeat. Determines if integration was alive on latest checkup Last status of the heartbeat. Determines if integration was alive on latest checkup

View file

@ -105,12 +105,6 @@ def check_heartbeats() -> str:
return f"Found {expired_count} expired and {restored_count} restored heartbeats" return f"Found {expired_count} expired and {restored_count} restored heartbeats"
@shared_dedicated_queue_retry_task()
def integration_heartbeat_checkup(heartbeat_id: int) -> None:
"""Deprecated. TODO: Remove this task after this task cleared from queue"""
pass
@shared_dedicated_queue_retry_task() @shared_dedicated_queue_retry_task()
def process_heartbeat_task(alert_receive_channel_pk): def process_heartbeat_task(alert_receive_channel_pk):
IntegrationHeartBeat.objects.filter( IntegrationHeartBeat.objects.filter(

View file

@ -4,7 +4,5 @@ from apps.heartbeat.models import IntegrationHeartBeat
class IntegrationHeartBeatFactory(factory.DjangoModelFactory): class IntegrationHeartBeatFactory(factory.DjangoModelFactory):
actual_check_up_task_id = "none"
class Meta: class Meta:
model = IntegrationHeartBeat model = IntegrationHeartBeat

View file

@ -31,10 +31,7 @@ def create_alertmanager_alerts(alert_receive_channel_pk, alert, is_demo=False, r
from apps.alerts.models import Alert, AlertReceiveChannel from apps.alerts.models import Alert, AlertReceiveChannel
alert_receive_channel = AlertReceiveChannel.objects_with_deleted.get(pk=alert_receive_channel_pk) alert_receive_channel = AlertReceiveChannel.objects_with_deleted.get(pk=alert_receive_channel_pk)
if ( if alert_receive_channel.deleted_at is not None or alert_receive_channel.is_maintenace_integration:
alert_receive_channel.deleted_at is not None
or alert_receive_channel.integration == AlertReceiveChannel.INTEGRATION_MAINTENANCE
):
logger.info("AlertReceiveChannel alert ignored if deleted/maintenance") logger.info("AlertReceiveChannel alert ignored if deleted/maintenance")
return return

View file

@ -903,7 +903,6 @@ def test_get_list_integrations_link_and_inbound_email(
if integration_type in [ if integration_type in [
AlertReceiveChannel.INTEGRATION_MANUAL, AlertReceiveChannel.INTEGRATION_MANUAL,
AlertReceiveChannel.INTEGRATION_SLACK_CHANNEL,
AlertReceiveChannel.INTEGRATION_MAINTENANCE, AlertReceiveChannel.INTEGRATION_MAINTENANCE,
]: ]:
assert integration_link is None assert integration_link is None

View file

@ -35,9 +35,8 @@ class AlertGroupSlackService:
self._slack_client = SlackClient(slack_team_identity) self._slack_client = SlackClient(slack_team_identity)
def update_alert_group_slack_message(self, alert_group: "AlertGroup") -> None: def update_alert_group_slack_message(self, alert_group: "AlertGroup") -> None:
from apps.alerts.models import AlertReceiveChannel
logger.info(f"Update message for alert_group {alert_group.pk}") logger.info(f"Update message for alert_group {alert_group.pk}")
try: try:
self._slack_client.chat_update( self._slack_client.chat_update(
channel=alert_group.slack_message.channel_id, channel=alert_group.slack_message.channel_id,
@ -47,7 +46,7 @@ class AlertGroupSlackService:
) )
logger.info(f"Message has been updated for alert_group {alert_group.pk}") logger.info(f"Message has been updated for alert_group {alert_group.pk}")
except SlackAPIRatelimitError as e: except SlackAPIRatelimitError as e:
if alert_group.channel.integration != AlertReceiveChannel.INTEGRATION_MAINTENANCE: if not alert_group.channel.is_maintenace_integration:
if not alert_group.channel.is_rate_limited_in_slack: if not alert_group.channel.is_rate_limited_in_slack:
alert_group.channel.start_send_rate_limit_message_task(e.retry_after) alert_group.channel.start_send_rate_limit_message_task(e.retry_after)
logger.info( logger.info(

View file

@ -141,22 +141,6 @@ class AlertShootingStep(scenario_step.ScenarioStep):
channel_id=channel_id, channel_id=channel_id,
) )
# If alert was made out of a message:
if alert_group.channel.integration == AlertReceiveChannel.INTEGRATION_SLACK_CHANNEL:
channel = json.loads(alert.integration_unique_data)["channel"]
result = self._slack_client.chat_postMessage(
channel=channel,
thread_ts=json.loads(alert.integration_unique_data)["ts"],
text=":rocket: <{}|Incident registered!>".format(alert_group.slack_message.permalink),
team=slack_team_identity,
)
alert_group.slack_messages.create(
slack_id=result["ts"],
organization=alert_group.channel.organization,
_slack_team_identity=self.slack_team_identity,
channel_id=channel,
)
alert.delivered = True alert.delivered = True
except SlackAPITokenError: except SlackAPITokenError:
alert_group.reason_to_skip_escalation = AlertGroup.ACCOUNT_INACTIVE alert_group.reason_to_skip_escalation = AlertGroup.ACCOUNT_INACTIVE
@ -172,7 +156,7 @@ class AlertShootingStep(scenario_step.ScenarioStep):
logger.info("Not delivering alert due to channel is archived.") logger.info("Not delivering alert due to channel is archived.")
except SlackAPIRatelimitError as e: except SlackAPIRatelimitError as e:
# don't rate limit maintenance alert # don't rate limit maintenance alert
if alert_group.channel.integration != AlertReceiveChannel.INTEGRATION_MAINTENANCE: if not alert_group.channel.is_maintenace_integration:
alert_group.reason_to_skip_escalation = AlertGroup.RATE_LIMITED alert_group.reason_to_skip_escalation = AlertGroup.RATE_LIMITED
alert_group.save(update_fields=["reason_to_skip_escalation"]) alert_group.save(update_fields=["reason_to_skip_escalation"])
alert_group.channel.start_send_rate_limit_message_task(e.retry_after) alert_group.channel.start_send_rate_limit_message_task(e.retry_after)

View file

@ -1,29 +0,0 @@
# Main
enabled = True
title = "Heartbeat"
slug = "heartbeat"
short_description = None
description = None
is_displayed_on_web = False
is_featured = False
is_able_to_autoresolve = True
is_demo_alert_enabled = False
description = None
# Default templates
slack_title = """\
*<{{ grafana_oncall_link }}|#{{ grafana_oncall_incident_id }} {{ payload.get("title", "Title undefined (check Slack Title Template)") }}>* via {{ integration_name }}
{% if source_link %}
(*<{{ source_link }}|source>*)
{%- endif %}"""
grouping_id = """\
{{ payload.get("id", "") }}{{ payload.get("user_defined_id", "") }}
"""
resolve_condition = '{{ payload.get("is_resolve", False) == True }}'
acknowledge_condition = None
example_payload = None

View file

@ -1,44 +0,0 @@
# Main
enabled = True
title = "Slack Channel"
slug = "slack_channel"
short_description = None
description = None
is_displayed_on_web = False
is_featured = False
is_able_to_autoresolve = False
is_demo_alert_enabled = False
description = None
# Default templates
slack_title = """\
{% if source_link -%}
*<{{ source_link }}|<#{{ payload.get("channel", "") }}>>*
{%- else -%}
<#{{ payload.get("channel", "") }}>
{%- endif %}"""
web_title = """\
{% if source_link -%}
[#{{ grafana_oncall_incident_id }}]{{ source_link }}) <#{{ payload.get("channel", "") }}>>*
{%- else -%}
*#{{ grafana_oncall_incident_id }}* <#{{ payload.get("channel", "") }}>
{%- endif %}"""
telegram_title = """\
{% if source_link -%}
<a href="{{ source_link }}">#{{ grafana_oncall_incident_id }}</a> {{ payload.get("channel", "") }}
{%- else -%}
*#{{ grafana_oncall_incident_id }}* <#{{ payload.get("channel", "") }}>
{%- endif %}"""
grouping_id = '{{ payload.get("ts", "") }}'
resolve_condition = None
acknowledge_condition = None
source_link = '{{ payload.get("amixr_mixin", {}).get("permalink", "")}}'
example_payload = None

View file

@ -878,11 +878,9 @@ INSTALLED_ONCALL_INTEGRATIONS = [
"config_integrations.formatted_webhook", "config_integrations.formatted_webhook",
"config_integrations.kapacitor", "config_integrations.kapacitor",
"config_integrations.elastalert", "config_integrations.elastalert",
"config_integrations.heartbeat",
"config_integrations.inbound_email", "config_integrations.inbound_email",
"config_integrations.maintenance", "config_integrations.maintenance",
"config_integrations.manual", "config_integrations.manual",
"config_integrations.slack_channel",
"config_integrations.zabbix", "config_integrations.zabbix",
"config_integrations.direct_paging", "config_integrations.direct_paging",
# Actually it's Grafana 8 integration. # Actually it's Grafana 8 integration.

View file

@ -12,7 +12,6 @@ CELERY_TASK_ROUTES = {
"common.oncall_gateway.tasks.delete_oncall_connector_async": {"queue": "default"}, "common.oncall_gateway.tasks.delete_oncall_connector_async": {"queue": "default"},
"common.oncall_gateway.tasks.create_slack_connector_async_v2": {"queue": "default"}, "common.oncall_gateway.tasks.create_slack_connector_async_v2": {"queue": "default"},
"common.oncall_gateway.tasks.delete_slack_connector_async_v2": {"queue": "default"}, "common.oncall_gateway.tasks.delete_slack_connector_async_v2": {"queue": "default"},
"apps.heartbeat.tasks.integration_heartbeat_checkup": {"queue": "default"},
"apps.heartbeat.tasks.process_heartbeat_task": {"queue": "default"}, "apps.heartbeat.tasks.process_heartbeat_task": {"queue": "default"},
"apps.labels.tasks.update_labels_cache": {"queue": "default"}, "apps.labels.tasks.update_labels_cache": {"queue": "default"},
"apps.labels.tasks.update_instances_labels_cache": {"queue": "default"}, "apps.labels.tasks.update_instances_labels_cache": {"queue": "default"},