diff --git a/ocw/lib/db.py b/ocw/lib/db.py index 3358eac4..8931b461 100644 --- a/ocw/lib/db.py +++ b/ocw/lib/db.py @@ -8,7 +8,7 @@ from ocw.apps import getScheduler from webui.PCWConfig import PCWConfig from ..models import Instance, StateChoice, ProviderChoice, CspInfo -from .emailnotify import send_mail, send_leftover_notification +from .emailnotify import send_mail from .azure import Azure from .ec2 import EC2 from .gce import GCE @@ -155,7 +155,6 @@ def update_run() -> None: traceback.format_exc()) auto_delete_instances() - send_leftover_notification() RUNNING = False if not error_occured: LAST_UPDATE = datetime.now(timezone.utc) diff --git a/ocw/lib/ec2.py b/ocw/lib/ec2.py index f1834b73..d4eb33d6 100644 --- a/ocw/lib/ec2.py +++ b/ocw/lib/ec2.py @@ -325,7 +325,12 @@ def vpc_can_be_deleted(self, resource_vpc, vpc_id) -> bool: def report_cleanup_results(self, vpc_errors: list, vpc_notify: list, vpc_locked: list) -> None: if len(vpc_errors) > 0: - send_mail(f'Errors on VPC deletion in [{self._namespace}]', '\n'.join(vpc_errors)) + # this is most common error message which we can not fix. + # So no point to spam us with notifications about it + known_error = "An error occurred (DependencyViolation) when calling the DeleteVpc operation" + filtered = [x for x in vpc_errors if known_error not in x] + if len(filtered) > 0: + send_mail(f'Errors on VPC deletion in [{self._namespace}]', '\n'.join(vpc_errors)) if len(vpc_notify) > 0: send_mail(f'{len(vpc_notify)} VPC\'s should be deleted, skipping due vpc-notify-only=True', ','.join(vpc_notify)) if len(vpc_locked) > 0: diff --git a/ocw/lib/emailnotify.py b/ocw/lib/emailnotify.py index d0141613..f2fe6dd4 100644 --- a/ocw/lib/emailnotify.py +++ b/ocw/lib/emailnotify.py @@ -1,4 +1,3 @@ -from datetime import timedelta import smtplib import logging from email.mime.text import MIMEText @@ -6,7 +5,6 @@ from django.urls import reverse from webui.PCWConfig import PCWConfig from webui.settings import build_absolute_uri -from ..models import Instance logger = logging.getLogger(__name__) @@ -31,22 +29,6 @@ def draw_instance_table(objects): return table.draw() -def send_leftover_notification(): - if PCWConfig.has('notify'): - all_instances = Instance.objects - all_instances = all_instances.filter(active=True, age__gt=timedelta(hours=PCWConfig.get_feature_property( - 'notify', 'age-hours'))).exclude(ignore=True) - body_prefix = f"Message from {build_absolute_uri()}\n\n" - # Handle namespaces - for namespace in PCWConfig.get_namespaces_for('notify'): - receiver_email = PCWConfig.get_feature_property('notify', 'to', namespace) - namespace_objects = all_instances.filter(namespace=namespace) - if namespace_objects.filter(notified=False).count() > 0 and receiver_email: - send_mail(f'CSP left overs - {namespace}', - body_prefix + draw_instance_table(namespace_objects), receiver_email=receiver_email) - all_instances.update(notified=True) - - def send_cluster_notification(namespace, clusters): if len(clusters) and PCWConfig.has('notify'): clusters_str = '' diff --git a/ocw/migrations/0013_remove_instance_notified_alter_instance_provider.py b/ocw/migrations/0013_remove_instance_notified_alter_instance_provider.py new file mode 100644 index 00000000..fe2d4945 --- /dev/null +++ b/ocw/migrations/0013_remove_instance_notified_alter_instance_provider.py @@ -0,0 +1,22 @@ +# Generated by Django 5.0.9 on 2024-09-16 19:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ocw', '0012_rename_vault_namespace_instance_namespace_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='instance', + name='notified', + ), + migrations.AlterField( + model_name='instance', + name='provider', + field=models.CharField(choices=[('GCE', 'Google'), ('EC2', 'EC2'), ('AZURE', 'Azure')], max_length=8), + ), + ] diff --git a/ocw/models.py b/ocw/models.py index 06d1c10f..9fb79bec 100644 --- a/ocw/models.py +++ b/ocw/models.py @@ -32,7 +32,6 @@ class Instance(models.Model): instance_id = models.CharField(max_length=200) region = models.CharField(max_length=64, default='') namespace = models.CharField(max_length=64, default='') - notified = models.BooleanField(default=False) ignore = models.BooleanField(default=False) TAG_IGNORE = 'pcw_ignore' diff --git a/ocw/tables.py b/ocw/tables.py index ab664c42..c60d4851 100644 --- a/ocw/tables.py +++ b/ocw/tables.py @@ -33,19 +33,6 @@ def render(self, record): return "" -class MailColumn(tables.BooleanColumn): - @property - def header(self): - return "" - - def render(self, value, record, bound_column): - value = self._get_bool_value(record, value, bound_column) - if value: - return format_html('Email notification was send', - static('img/notified.png')) - return "" - - class TagsColumn(tables.TemplateColumn): def __init__(self, template_name=None, **extra): @@ -58,7 +45,6 @@ def header(self): class InstanceTable(tables.Table): tags = TagsColumn() - notified = MailColumn() type = tables.Column(accessor=A('get_type')) first_seen = tables.DateTimeColumn(format='M d Y') last_seen = tables.DateTimeColumn(format='M d Y') diff --git a/tests/test_db.py b/tests/test_db.py index 47e06573..b6907468 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -179,16 +179,12 @@ def mocked__update_provider(arg1, arg2, arg3): def mocked_auto_delete_instances(): call_stack.append('auto_delete_instances') - def mocked_send_leftover_notification(): - call_stack.append('send_leftover_notification') - monkeypatch.setattr('ocw.lib.db._update_provider', mocked__update_provider) monkeypatch.setattr('ocw.lib.db.auto_delete_instances', mocked_auto_delete_instances) - monkeypatch.setattr('ocw.lib.db.send_leftover_notification', mocked_send_leftover_notification) update_run() - assert call_stack == ['_update_provider', 'auto_delete_instances', 'send_leftover_notification'] + assert call_stack == ['_update_provider', 'auto_delete_instances'] def test_update_run_update_provider_throw_exception(update_run_patch, monkeypatch): @@ -202,20 +198,16 @@ def mocked__update_provider(arg1, arg2, arg3): def mocked_auto_delete_instances(): call_stack.append('auto_delete_instances') - def mocked_send_leftover_notification(): - call_stack.append('send_leftover_notification') - def mocked_send_mail(arg1, arg2): call_stack.append('send_mail') monkeypatch.setattr('ocw.lib.db._update_provider', mocked__update_provider) monkeypatch.setattr('ocw.lib.db.auto_delete_instances', mocked_auto_delete_instances) - monkeypatch.setattr('ocw.lib.db.send_leftover_notification', mocked_send_leftover_notification) monkeypatch.setattr('ocw.lib.db.send_mail', mocked_send_mail) update_run() - assert call_stack == ['_update_provider', 'send_mail', 'auto_delete_instances', 'send_leftover_notification'] + assert call_stack == ['_update_provider', 'send_mail', 'auto_delete_instances'] def test_delete_instances_azure(monkeypatch):