From 970a4e7b4e7d485deddb041ce596e1f70aad00c3 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Thu, 6 Apr 2017 12:14:17 +0100 Subject: [PATCH] New endpoint to send a list of job ids to a queue. The task will be picked up by the FTP app. Given the list of job ids the tasks will get all the files from s3, aggregate them then send to dvla --- app/__init__.py | 4 +++ app/letters/__init__.py | 0 app/letters/letter_schemas.py | 15 +++++++++ app/letters/send_letter_jobs.py | 18 ++++++++++ tests/app/letters/__init__.py | 0 tests/app/letters/test_letter_schemas.py | 30 +++++++++++++++++ tests/app/letters/test_send_letter_jobs.py | 39 ++++++++++++++++++++++ 7 files changed, 106 insertions(+) create mode 100644 app/letters/__init__.py create mode 100644 app/letters/letter_schemas.py create mode 100644 app/letters/send_letter_jobs.py create mode 100644 tests/app/letters/__init__.py create mode 100644 tests/app/letters/test_letter_schemas.py create mode 100644 tests/app/letters/test_send_letter_jobs.py diff --git a/app/__init__.py b/app/__init__.py index f860a0c21..2e962f79b 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -93,6 +93,7 @@ def register_blueprint(application): from app.notifications.notifications_ses_callback import ses_callback_blueprint from app.notifications.notifications_sms_callback import sms_callback_blueprint from app.authentication.auth import requires_admin_auth, requires_auth, requires_no_auth + from app.letters.send_letter_jobs import letter_job service_blueprint.before_request(requires_admin_auth) application.register_blueprint(service_blueprint, url_prefix='/service') @@ -145,6 +146,9 @@ def register_blueprint(application): organisation_blueprint.before_request(requires_admin_auth) application.register_blueprint(organisation_blueprint, url_prefix='/organisation') + letter_job.before_request(requires_admin_auth) + application.register_blueprint(letter_job) + def register_v2_blueprints(application): from app.v2.notifications.post_notifications import v2_notification_blueprint as post_notifications diff --git a/app/letters/__init__.py b/app/letters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/letters/letter_schemas.py b/app/letters/letter_schemas.py new file mode 100644 index 000000000..3827e4f4e --- /dev/null +++ b/app/letters/letter_schemas.py @@ -0,0 +1,15 @@ +from app.schema_validation.definitions import uuid + +letter_job_ids = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "list of job ids", + "type": "object", + "title": "job_ids", + "properties": { + "job_ids": {"type": "array", + "items": uuid, + "minItems": 1 + }, + }, + "required": ["job_ids"] +} diff --git a/app/letters/send_letter_jobs.py b/app/letters/send_letter_jobs.py new file mode 100644 index 000000000..b5311c6f7 --- /dev/null +++ b/app/letters/send_letter_jobs.py @@ -0,0 +1,18 @@ +from flask import Blueprint +from flask import request + +from app import notify_celery +from app.v2.errors import register_errors +from app.letters.letter_schemas import letter_job_ids +from app.schema_validation import validate + +letter_job = Blueprint("letter-job", __name__) +register_errors(letter_job) + + +@letter_job.route('/send-letter-jobs', methods=['POST']) +def send_letter_jobs(): + job_ids = validate(request.get_json(), letter_job_ids) + notify_celery.send_task(name="send_files_to_dvla", args=(job_ids['job_ids'],), queue="process-ftp") + + return "Task created to send files to DVLA" diff --git a/tests/app/letters/__init__.py b/tests/app/letters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/app/letters/test_letter_schemas.py b/tests/app/letters/test_letter_schemas.py new file mode 100644 index 000000000..af64106a3 --- /dev/null +++ b/tests/app/letters/test_letter_schemas.py @@ -0,0 +1,30 @@ +import json +import uuid + +import pytest +from jsonschema import ValidationError + +from app.letters.letter_schemas import letter_job_ids +from app.schema_validation import validate + + +def test_letter_job_id_retuns_400_if_array_is_empty(): + with pytest.raises(ValidationError) as e: + validate({"job_ids": []}, letter_job_ids) + error = json.loads(str(e.value)) + assert len(error.keys()) == 2 + assert error.get('errors')[0]['message'] == 'job_ids [] is too short' + + +def test_letter_job_id_retuns_400_if_array_doesnot_contain_uuids(): + with pytest.raises(ValidationError) as e: + validate({"job_ids": ["1", "2"]}, letter_job_ids) + error = json.loads(str(e.value)) + assert len(error.keys()) == 2 + assert error.get('errors')[0]['message'] == 'job_ids is not a valid UUID' + + +def test_letter_job(): + ids_ = {"job_ids": [str(uuid.uuid4()), str(uuid.uuid4())]} + j = validate(ids_, letter_job_ids) + assert j == ids_ diff --git a/tests/app/letters/test_send_letter_jobs.py b/tests/app/letters/test_send_letter_jobs.py new file mode 100644 index 000000000..9bd5d7f75 --- /dev/null +++ b/tests/app/letters/test_send_letter_jobs.py @@ -0,0 +1,39 @@ +import uuid + +from flask import json + +from tests import create_authorization_header + + +def test_send_letter_jobs(client, mocker): + mock_celery = mocker.patch("app.letters.send_letter_jobs.notify_celery.send_task") + job_ids = {"job_ids": [str(uuid.uuid4()), str(uuid.uuid4()), str(uuid.uuid4())]} + + auth_header = create_authorization_header() + + response = client.post( + path='/send-letter-jobs', + data=json.dumps(job_ids), + headers=[('Content-Type', 'application/json'), auth_header]) + + assert response.status_code == 200 + assert response.get_data(as_text=True) == "Task created to send files to DVLA" + + mock_celery.assert_called_once_with(name="send_files_to_dvla", args=(job_ids['job_ids'],), queue="process-ftp") + + +def test_send_letter_jobs_throws_validation_error(client, mocker): + mock_celery = mocker.patch("app.letters.send_letter_jobs.notify_celery.send_task") + + job_ids = {"job_ids": ["1", "2"]} + + auth_header = create_authorization_header() + + response = client.post( + path='/send-letter-jobs', + data=json.dumps(job_ids), + headers=[('Content-Type', 'application/json'), auth_header]) + + assert response.status_code == 400 + + assert not mock_celery.called