def should_report_validation_as_skipped_if_not_started_due_to_failing_pipeline( get_caller_identity_mock: MagicMock, describe_step_function_mock: MagicMock, get_step_function_validation_results_mock: MagicMock, ) -> None: get_caller_identity_mock.return_value = {"Account": any_account_id()} describe_step_function_mock.return_value = { "status": "FAILED", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), "output": json.dumps({}), } get_step_function_validation_results_mock.return_value = [] expected_response = { "statusCode": HTTPStatus.OK, "body": { "step function": {"status": "Failed"}, "validation": {"status": Outcome.SKIPPED.value, "errors": []}, "metadata upload": {"status": Outcome.SKIPPED.value, "errors": []}, "asset upload": {"status": Outcome.SKIPPED.value, "errors": []}, }, } # When attempting to create the instance response = entrypoint.lambda_handler( {"httpMethod": "GET", "body": {"execution_arn": any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_report_upload_status_as_pending_when_validation_incomplete( describe_execution_mock: MagicMock, ) -> None: # Given describe_execution_mock.return_value = { "status": "RUNNING", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), } expected_response = { "statusCode": HTTPStatus.OK, "body": { "step function": {"status": "Running"}, "validation": {"status": Outcome.PENDING.value, "errors": []}, "metadata upload": {"status": "Pending", "errors": []}, "asset upload": {"status": "Pending", "errors": []}, }, } with patch("backend.import_status.get.get_step_function_validation_results") as validation_mock: validation_mock.return_value = [] # When attempting to create the instance response = entrypoint.lambda_handler( {"httpMethod": "GET", "body": {"execution_arn": any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_fail_validation_if_it_has_errors_but_step_function_does_not_report_status( get_caller_identity_mock: MagicMock, describe_step_function_mock: MagicMock, get_step_function_validation_results_mock: MagicMock, ) -> None: # Given get_caller_identity_mock.return_value = {"Account": any_account_id()} describe_step_function_mock.return_value = { "status": "FAILED", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), "output": json.dumps({}), } validation_error = {"result": ValidationResult.FAILED.value} get_step_function_validation_results_mock.return_value = [validation_error] expected_response = { "statusCode": HTTPStatus.OK, "body": { "step function": {"status": "Failed"}, "validation": {"status": "Failed", "errors": [validation_error]}, "metadata upload": {"status": Outcome.SKIPPED.value, "errors": []}, "asset upload": {"status": Outcome.SKIPPED.value, "errors": []}, }, } # When response = entrypoint.lambda_handler( {"httpMethod": "GET", "body": {"execution_arn": any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_report_upload_status_as_pending_when_validation_incomplete( describe_execution_mock: MagicMock, ) -> None: # Given describe_execution_mock.return_value = { "status": "RUNNING", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), } expected_response = { STATUS_CODE_KEY: HTTPStatus.OK, BODY_KEY: { STEP_FUNCTION_KEY: {STATUS_KEY: "Running"}, VALIDATION_KEY: {STATUS_KEY: Outcome.PENDING.value, ERRORS_KEY: []}, METADATA_UPLOAD_KEY: {STATUS_KEY: Outcome.PENDING.value, ERRORS_KEY: []}, ASSET_UPLOAD_KEY: {STATUS_KEY: Outcome.PENDING.value, ERRORS_KEY: []}, }, } with patch("backend.step_function.get_step_function_validation_results") as validation_mock: validation_mock.return_value = [] # When attempting to create the instance response = entrypoint.lambda_handler( {HTTP_METHOD_KEY: "GET", BODY_KEY: {EXECUTION_ARN_KEY: any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_fail_validation_if_it_has_errors_but_step_function_does_not_report_status( get_caller_identity_mock: MagicMock, describe_step_function_mock: MagicMock, get_step_function_validation_results_mock: MagicMock, ) -> None: # Given get_caller_identity_mock.return_value = {"Account": any_account_id()} describe_step_function_mock.return_value = { "status": "FAILED", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), "output": json.dumps({}), } validation_error = {ERROR_RESULT_KEY: ValidationResult.FAILED.value} get_step_function_validation_results_mock.return_value = [validation_error] expected_response = { STATUS_CODE_KEY: HTTPStatus.OK, BODY_KEY: { STEP_FUNCTION_KEY: {STATUS_KEY: "Failed"}, VALIDATION_KEY: {STATUS_KEY: Outcome.FAILED.value, ERRORS_KEY: [validation_error]}, METADATA_UPLOAD_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, ASSET_UPLOAD_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, }, } # When response = entrypoint.lambda_handler( {HTTP_METHOD_KEY: "GET", BODY_KEY: {EXECUTION_ARN_KEY: any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_report_validation_as_skipped_if_not_started_due_to_failing_pipeline( get_caller_identity_mock: MagicMock, describe_step_function_mock: MagicMock, get_step_function_validation_results_mock: MagicMock, ) -> None: get_caller_identity_mock.return_value = {"Account": any_account_id()} describe_step_function_mock.return_value = { "status": "FAILED", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), "output": json.dumps({}), } get_step_function_validation_results_mock.return_value = [] expected_response = { STATUS_CODE_KEY: HTTPStatus.OK, BODY_KEY: { STEP_FUNCTION_KEY: {STATUS_KEY: "Failed"}, VALIDATION_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, METADATA_UPLOAD_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, ASSET_UPLOAD_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, }, } # When attempting to create the instance response = entrypoint.lambda_handler( {HTTP_METHOD_KEY: "GET", BODY_KEY: {EXECUTION_ARN_KEY: any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_return_required_property_error_when_missing_mandatory_execution_arn() -> None: # Given a missing "execution_arn" attribute in the body response = entrypoint.lambda_handler({"httpMethod": "GET", "body": {}}, any_lambda_context()) # Then the API should return an error message assert response == { "statusCode": HTTPStatus.BAD_REQUEST, "body": {"message": "Bad Request: 'execution_arn' is a required property"}, }
def should_report_s3_batch_upload_failures( describe_s3_job_mock: MagicMock, describe_step_function_mock: MagicMock, ) -> None: # Given describe_step_function_mock.return_value = { "status": "SUCCEEDED", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), "output": json.dumps( { "validation": {"success": True}, "import_dataset": { METADATA_JOB_ID_KEY: any_job_id(), ASSET_JOB_ID_KEY: any_job_id(), }, } ), } describe_s3_job_mock.return_value = { "Job": { "Status": "Completed", "FailureReasons": [{"FailureCode": "TEST_CODE", "FailureReason": "TEST_REASON"}], } } expected_response = { "statusCode": HTTPStatus.OK, "body": { "step function": {"status": "Succeeded"}, "validation": {"status": Outcome.PASSED.value, "errors": []}, "metadata upload": { "status": "Completed", "errors": [{"FailureCode": "TEST_CODE", "FailureReason": "TEST_REASON"}], }, "asset upload": { "status": "Completed", "errors": [{"FailureCode": "TEST_CODE", "FailureReason": "TEST_REASON"}], }, }, } with patch("backend.import_status.get.STS_CLIENT.get_caller_identity") as sts_mock, patch( "backend.import_status.get.get_step_function_validation_results" ) as validation_mock: validation_mock.return_value = [] sts_mock.return_value = {"Account": any_account_id()} # When response = entrypoint.lambda_handler( {"httpMethod": "GET", "body": {"execution_arn": any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_report_s3_batch_upload_failures( describe_s3_job_mock: MagicMock, describe_step_function_mock: MagicMock, ) -> None: # Given describe_step_function_mock.return_value = { "status": "SUCCEEDED", "input": json.dumps( {DATASET_ID_KEY: any_dataset_id(), VERSION_ID_KEY: any_dataset_version_id()} ), "output": json.dumps( { VALIDATION_KEY: {SUCCESS_KEY: True}, IMPORT_DATASET_KEY: { METADATA_JOB_ID_KEY: any_job_id(), ASSET_JOB_ID_KEY: any_job_id(), }, } ), } describe_s3_job_mock.return_value = { "Job": { "Status": "Completed", "FailureReasons": [{"FailureCode": "TEST_CODE", "FailureReason": "TEST_REASON"}], } } expected_response = { STATUS_CODE_KEY: HTTPStatus.OK, BODY_KEY: { STEP_FUNCTION_KEY: {STATUS_KEY: "Succeeded"}, VALIDATION_KEY: {STATUS_KEY: Outcome.PASSED.value, ERRORS_KEY: []}, METADATA_UPLOAD_KEY: { STATUS_KEY: "Completed", ERRORS_KEY: [{"FailureCode": "TEST_CODE", "FailureReason": "TEST_REASON"}], }, ASSET_UPLOAD_KEY: { STATUS_KEY: "Completed", ERRORS_KEY: [{"FailureCode": "TEST_CODE", "FailureReason": "TEST_REASON"}], }, }, } with patch("backend.step_function.STS_CLIENT.get_caller_identity") as sts_mock, patch( "backend.step_function.get_step_function_validation_results" ) as validation_mock: validation_mock.return_value = [] sts_mock.return_value = {"Account": any_account_id()} # When response = entrypoint.lambda_handler( {HTTP_METHOD_KEY: "GET", BODY_KEY: {EXECUTION_ARN_KEY: any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_return_required_property_error_when_missing_mandatory_execution_arn() -> None: # Given an empty body response = entrypoint.lambda_handler( {HTTP_METHOD_KEY: "GET", BODY_KEY: {}}, any_lambda_context() ) # Then the API should return an error message assert response == { STATUS_CODE_KEY: HTTPStatus.BAD_REQUEST, BODY_KEY: {MESSAGE_KEY: f"Bad Request: '{EXECUTION_ARN_KEY}' is a required property"}, }
def should_retrieve_validation_failures(describe_step_function_mock: MagicMock) -> None: # Given dataset_id = any_dataset_id() version_id = any_dataset_version_id() describe_step_function_mock.return_value = { "status": "SUCCEEDED", "input": json.dumps({DATASET_ID_KEY: dataset_id, VERSION_ID_KEY: version_id}), "output": json.dumps({VALIDATION_KEY: {SUCCESS_KEY: False}}), } url = any_s3_url() error_details = {"error_message": "test"} check = "example" expected_response = { STATUS_CODE_KEY: HTTPStatus.OK, BODY_KEY: { STEP_FUNCTION_KEY: {STATUS_KEY: "Succeeded"}, VALIDATION_KEY: { STATUS_KEY: Outcome.FAILED.value, ERRORS_KEY: [ { ERROR_CHECK_KEY: check, ERROR_DETAILS_KEY: error_details, ERROR_RESULT_KEY: ValidationResult.FAILED.value, ERROR_URL_KEY: url, } ], }, METADATA_UPLOAD_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, ASSET_UPLOAD_KEY: {STATUS_KEY: Outcome.SKIPPED.value, ERRORS_KEY: []}, }, } with ValidationItem( asset_id=( f"{DATASET_ID_PREFIX}{dataset_id}{DB_KEY_SEPARATOR}{VERSION_ID_PREFIX}{version_id}" ), result=ValidationResult.FAILED, details=error_details, url=url, check=check, ): # When response = entrypoint.lambda_handler( {HTTP_METHOD_KEY: "GET", BODY_KEY: {EXECUTION_ARN_KEY: any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response
def should_retrieve_validation_failures(describe_step_function_mock: MagicMock) -> None: # Given dataset_id = any_dataset_id() version_id = any_dataset_version_id() describe_step_function_mock.return_value = { "status": "SUCCEEDED", "input": json.dumps({DATASET_ID_KEY: dataset_id, VERSION_ID_KEY: version_id}), "output": json.dumps({"validation": {"success": False}}), } url = any_s3_url() error_details = {"error_message": "test"} check = "example" expected_response = { "statusCode": HTTPStatus.OK, "body": { "step function": {"status": "Succeeded"}, "validation": { "status": Outcome.FAILED.value, "errors": [ { "check": check, "details": error_details, "result": ValidationResult.FAILED.value, "url": url, } ], }, "metadata upload": {"status": Outcome.SKIPPED.value, "errors": []}, "asset upload": {"status": Outcome.SKIPPED.value, "errors": []}, }, } with ValidationItem( asset_id=f"DATASET#{dataset_id}#VERSION#{version_id}", result=ValidationResult.FAILED, details=error_details, url=url, check=check, ): # When response = entrypoint.lambda_handler( {"httpMethod": "GET", "body": {"execution_arn": any_arn_formatted_string()}}, any_lambda_context(), ) # Then assert response == expected_response