mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-03 01:41:05 -05:00
Merge pull request #1924 from alphagov/replay-letters-in-error
Added a method to reply letters that are in the error folder on S3.
This commit is contained in:
@@ -26,7 +26,9 @@ from app.letters.utils import (
|
|||||||
get_reference_from_filename,
|
get_reference_from_filename,
|
||||||
move_scanned_pdf_to_test_or_live_pdf_bucket,
|
move_scanned_pdf_to_test_or_live_pdf_bucket,
|
||||||
upload_letter_pdf,
|
upload_letter_pdf,
|
||||||
move_failed_pdf, ScanErrorType)
|
move_failed_pdf, ScanErrorType, move_error_pdf_to_scan_bucket,
|
||||||
|
get_file_names_from_error_bucket
|
||||||
|
)
|
||||||
from app.models import (
|
from app.models import (
|
||||||
KEY_TYPE_TEST,
|
KEY_TYPE_TEST,
|
||||||
NOTIFICATION_CREATED,
|
NOTIFICATION_CREATED,
|
||||||
@@ -192,7 +194,9 @@ def process_virus_scan_failed(filename):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
raise VirusScanError('notification id {} Virus scan failed: {}'.format(notification.id, filename))
|
error = VirusScanError('notification id {} Virus scan failed: {}'.format(notification.id, filename))
|
||||||
|
current_app.logger.exception(error)
|
||||||
|
raise error
|
||||||
|
|
||||||
|
|
||||||
@notify_celery.task(name='process-virus-scan-error')
|
@notify_celery.task(name='process-virus-scan-error')
|
||||||
@@ -208,8 +212,9 @@ def process_virus_scan_error(filename):
|
|||||||
updated_count
|
updated_count
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
error = VirusScanError('notification id {} Virus scan error: {}'.format(notification.id, filename))
|
||||||
raise VirusScanError('notification id {} Virus scan error: {}'.format(notification.id, filename))
|
current_app.logger.exception(error)
|
||||||
|
raise error
|
||||||
|
|
||||||
|
|
||||||
def update_letter_pdf_status(reference, status):
|
def update_letter_pdf_status(reference, status):
|
||||||
@@ -219,3 +224,29 @@ def update_letter_pdf_status(reference, status):
|
|||||||
'status': status,
|
'status': status,
|
||||||
'updated_at': datetime.utcnow()
|
'updated_at': datetime.utcnow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def replay_letters_in_error(filename=None):
|
||||||
|
# This method can be used to replay letters that end up in the ERROR directory.
|
||||||
|
# We had an incident where clamAV was not processing the virus scan.
|
||||||
|
if filename:
|
||||||
|
move_error_pdf_to_scan_bucket(filename)
|
||||||
|
# call task to add the filename to anti virus queue
|
||||||
|
current_app.logger.info("Calling scan_file for: {}".format(filename))
|
||||||
|
notify_celery.send_task(
|
||||||
|
name=TaskNames.SCAN_FILE,
|
||||||
|
kwargs={'filename': filename},
|
||||||
|
queue=QueueNames.ANTIVIRUS,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
error_files = get_file_names_from_error_bucket()
|
||||||
|
for item in error_files:
|
||||||
|
moved_file_name = item.key.split('/')[1]
|
||||||
|
current_app.logger.info("Calling scan_file for: {}".format(moved_file_name))
|
||||||
|
move_error_pdf_to_scan_bucket(moved_file_name)
|
||||||
|
# call task to add the filename to anti virus queue
|
||||||
|
notify_celery.send_task(
|
||||||
|
name=TaskNames.SCAN_FILE,
|
||||||
|
kwargs={'filename': moved_file_name},
|
||||||
|
queue=QueueNames.ANTIVIRUS,
|
||||||
|
)
|
||||||
|
|||||||
@@ -110,6 +110,21 @@ def move_failed_pdf(source_filename, scan_error_type):
|
|||||||
_move_s3_object(scan_bucket, source_filename, scan_bucket, target_filename)
|
_move_s3_object(scan_bucket, source_filename, scan_bucket, target_filename)
|
||||||
|
|
||||||
|
|
||||||
|
def move_error_pdf_to_scan_bucket(source_filename):
|
||||||
|
scan_bucket = current_app.config['LETTERS_SCAN_BUCKET_NAME']
|
||||||
|
error_file = 'ERROR/' + source_filename
|
||||||
|
|
||||||
|
_move_s3_object(scan_bucket, error_file, scan_bucket, source_filename)
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_names_from_error_bucket():
|
||||||
|
s3 = boto3.resource('s3')
|
||||||
|
scan_bucket = current_app.config['LETTERS_SCAN_BUCKET_NAME']
|
||||||
|
bucket = s3.Bucket(scan_bucket)
|
||||||
|
|
||||||
|
return bucket.objects.filter(Prefix="ERROR")
|
||||||
|
|
||||||
|
|
||||||
def get_letter_pdf(notification):
|
def get_letter_pdf(notification):
|
||||||
is_test_letter = notification.key_type == KEY_TYPE_TEST and notification.template.is_precompiled_letter
|
is_test_letter = notification.key_type == KEY_TYPE_TEST and notification.template.is_precompiled_letter
|
||||||
if is_test_letter:
|
if is_test_letter:
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ from app.celery.letters_pdf_tasks import (
|
|||||||
letter_in_created_state,
|
letter_in_created_state,
|
||||||
process_virus_scan_passed,
|
process_virus_scan_passed,
|
||||||
process_virus_scan_failed,
|
process_virus_scan_failed,
|
||||||
process_virus_scan_error)
|
process_virus_scan_error, replay_letters_in_error
|
||||||
|
)
|
||||||
from app.letters.utils import get_letter_pdf_filename, ScanErrorType
|
from app.letters.utils import get_letter_pdf_filename, ScanErrorType
|
||||||
from app.models import (
|
from app.models import (
|
||||||
KEY_TYPE_NORMAL,
|
KEY_TYPE_NORMAL,
|
||||||
@@ -363,3 +364,25 @@ def test_process_letter_task_check_virus_scan_error(sample_letter_notification,
|
|||||||
assert "Virus scan error:" in str(e)
|
assert "Virus scan error:" in str(e)
|
||||||
mock_move_failed_pdf.assert_called_once_with(filename, ScanErrorType.ERROR)
|
mock_move_failed_pdf.assert_called_once_with(filename, ScanErrorType.ERROR)
|
||||||
assert sample_letter_notification.status == NOTIFICATION_TECHNICAL_FAILURE
|
assert sample_letter_notification.status == NOTIFICATION_TECHNICAL_FAILURE
|
||||||
|
|
||||||
|
|
||||||
|
def test_replay_letters_in_error_for_all_letters_in_error_bucket(notify_api, mocker):
|
||||||
|
import boto3
|
||||||
|
mockObject = boto3.resource('s3').Object('ERROR', 'ERROR/file_name')
|
||||||
|
mocker.patch("app.celery.letters_pdf_tasks.get_file_names_from_error_bucket", return_value=[mockObject])
|
||||||
|
mock_move = mocker.patch("app.celery.letters_pdf_tasks.move_error_pdf_to_scan_bucket")
|
||||||
|
mock_celery = mocker.patch("app.celery.letters_pdf_tasks.notify_celery.send_task")
|
||||||
|
replay_letters_in_error()
|
||||||
|
mock_move.assert_called_once_with('file_name')
|
||||||
|
mock_celery.assert_called_once_with(name='scan-file', kwargs={'filename': 'file_name'}, queue='antivirus-tasks')
|
||||||
|
|
||||||
|
|
||||||
|
def test_replay_letters_in_error_for_one_file(notify_api, mocker):
|
||||||
|
import boto3
|
||||||
|
mockObject = boto3.resource('s3').Object('ERROR', 'ERROR/file_name')
|
||||||
|
mocker.patch("app.celery.letters_pdf_tasks.get_file_names_from_error_bucket", return_value=[mockObject])
|
||||||
|
mock_move = mocker.patch("app.celery.letters_pdf_tasks.move_error_pdf_to_scan_bucket")
|
||||||
|
mock_celery = mocker.patch("app.celery.letters_pdf_tasks.notify_celery.send_task")
|
||||||
|
replay_letters_in_error("file_name")
|
||||||
|
mock_move.assert_called_once_with('file_name')
|
||||||
|
mock_celery.assert_called_once_with(name='scan-file', kwargs={'filename': 'file_name'}, queue='antivirus-tasks')
|
||||||
|
|||||||
Reference in New Issue
Block a user