def test_submit_request_error_status(self): """ Tests that an error job is written to the db """ utc_now_exp = UTC_NOW_EXP_4 requests_db.get_utc_now_iso = Mock(return_value=utc_now_exp) requests_db.request_id_generator = Mock(side_effect=[REQUEST_ID4]) data = {} data["request_id"] = REQUEST_ID4 data["err_msg"] = "Error message goes here" data["request_group_id"] = REQUEST_GROUP_ID_EXP_2 data["granule_id"] = "granule_4" data["object_key"] = "objectkey_4" data["job_type"] = "restore" data["job_status"] = "error" data["request_time"] = utc_now_exp qresult, exp_result = create_insert_request( REQUEST_ID4, data["request_group_id"], data["granule_id"], data["object_key"], data["job_type"], None, None, data["job_status"], data["request_time"], None, data["err_msg"]) database.single_query = Mock(side_effect=[qresult, exp_result, None, None]) mock_ssm_get_parameter(4) try: requests_db.submit_request(data) database.single_query.assert_called_once() except requests_db.DatabaseError as err: self.fail(f"submit_request. {str(err)}") try: result = requests_db.get_job_by_request_id(REQUEST_ID4) expected = result_to_json(exp_result) self.assertEqual(expected, result) except requests_db.DatabaseError as err: self.fail(f"get_job_by_request_id. {str(err)}")
def test_submit_request_error_status(self): """ Tests that a job is written to the db """ self.create_test_requests() boto3.client = Mock() mock_ssm_get_parameter(2) utc_now_exp = "2019-07-31 18:05:19.161362+00:00" requests_db.get_utc_now_iso = Mock(return_value=utc_now_exp) requests_db.request_id_generator = Mock(side_effect=[REQUEST_ID12]) data = {} data["request_id"] = REQUEST_ID12 data["request_group_id"] = REQUEST_GROUP_ID_EXP_1 data["granule_id"] = "granule_1" data["object_key"] = "thisisanobjectkey" data["job_type"] = "restore" data["restore_bucket_dest"] = "my_s3_bucket" data["archive_bucket_dest"] = PROTECTED_BUCKET data["job_status"] = "error" data["request_time"] = utc_now_exp data["err_msg"] = "restore request error message here" try: requests_db.submit_request(data) except requests_db.DatabaseError as err: self.fail(f"submit_request. {str(err)}") try: result = requests_db.get_job_by_request_id(REQUEST_ID12) data["last_update_time"] = utc_now_exp self.assertEqual(data, result[0]) except requests_db.DatabaseError as err: self.fail(f"get_job_by_request_id. {str(err)}")
def test_submit_request_bad_status(self): """ Tests adding a job with an invalid status """ utc_now_exp = "2019-07-31 18:05:19.161362+00:00" requests_db.get_utc_now_iso = Mock(return_value=utc_now_exp) requests_db.request_id_generator = Mock(side_effect=[REQUEST_ID1]) data = {} data["request_id"] = REQUEST_ID1 data["request_group_id"] = REQUEST_GROUP_ID_EXP_1 data["granule_id"] = "granule_1" data["object_key"] = "thisisanobjectkey" data["job_type"] = "restore" data["restore_bucket_dest"] = "my_s3_bucket" data["job_status"] = "invalid" data["last_update_time"] = utc_now_exp mock_err = ('Database Error. new row for relation "request_status" violates ' 'check constraint "request_status_job_status_check" ' f'DETAIL: Failing row contains (1306, {REQUEST_GROUP_ID_EXP_1}, ' 'granule_1, thisisanobjectkey, restore, my_s3_bucket, invalid, ' '2019-07-31 18:05:19.161362+00, 2019-07-31 18:05:19.161362+00, null).') exp_err = ('new row for relation "request_status" violates check constraint ' '"request_status_job_status_check"') mock_ssm_get_parameter(1) database.single_query = Mock(side_effect=[requests_db.DatabaseError( mock_err)]) try: requests_db.submit_request(data) self.fail("expected DatabaseError") except requests_db.DatabaseError as err: self.assertIn(exp_err, str(err)) database.single_query.assert_called_once()
def restore_object(s3_cli, obj, attempt, retries, retrieval_type='Standard'): """Restore an archived S3 Glacier object in an Amazon S3 bucket. Args: s3_cli (object): An instance of boto3 s3 client obj (dict): A dictionary containing: request_group_id (string): A uuid identifying all objects in a granule restore request granule_id (string): The granule_id to which the object_name being restored belongs glacier_bucket (string): The S3 bucket name key (string): The key of the Glacier object being restored dest_bucket (string): The bucket the restored file will be moved to after the restore completes days (number): How many days the restored file will be accessible in the S3 bucket before it expires attempt (number): The attempt number for retry purposes retries (number): The number of retries that will be attempted retrieval_type (string, optional, default=Standard): Glacier Tier. Valid values are 'Standard'|'Bulk'|'Expedited'. Returns: uuid: request_Id. """ data = requests_db.create_data(obj, "restore", "inprogress", None, None) request_id = data["request_id"] request = {'Days': obj["days"], 'GlacierJobParameters': {'Tier': retrieval_type}} # Submit the request try: s3_cli.restore_object(Bucket=obj["glacier_bucket"], Key=obj["key"], RestoreRequest=request) try: requests_db.submit_request(data) LOGGER.info(f"Job {request_id} created.") except requests_db.DatabaseError as err: LOGGER.error("Failed to log request in database. Error {}. Request: {}", str(err), data) except ClientError as c_err: # NoSuchBucket, NoSuchKey, or InvalidObjectState error == the object's # storage class was not GLACIER LOGGER.error("{}. bucket: {} file: {}", c_err, obj["glacier_bucket"], obj["key"]) if attempt == retries: try: data["err_msg"] = str(c_err) data["job_status"] = "error" requests_db.submit_request(data) LOGGER.info(f"Job {request_id} created.") except requests_db.DatabaseError as err: LOGGER.error("Failed to log request in database. Error {}. Request: {}", str(err), data) raise c_err return request_id
def add_request(event): """ Adds a request to the database """ try: granule_id = event['granule_id'] except KeyError: raise BadRequestError("Missing 'granule_id' in input data") try: request_group_id = event['request_group_id'] except KeyError: raise BadRequestError("Missing 'request_group_id' in input data") try: status = event['status'] except KeyError: status = "error" data = {} data["request_id"] = requests_db.request_id_generator() data["request_group_id"] = request_group_id data["granule_id"] = granule_id data["object_key"] = "my_test_filename" data["job_type"] = "restore" data["restore_bucket_dest"] = "my_test_bucket" data["job_status"] = status if status == "error": data["err_msg"] = "error message goes here" request_id = requests_db.submit_request(data) result = requests_db.get_job_by_request_id(request_id) return result
def test_submit_request_missing_granuleid(self): """ Tests adding a job with no granule_id """ utc_now_exp = UTC_NOW_EXP_1 requests_db.get_utc_now_iso = Mock(return_value=utc_now_exp) requests_db.request_id_generator = Mock(side_effect=[REQUEST_ID1]) data = {} data["request_id"] = REQUEST_ID1 data["request_group_id"] = REQUEST_GROUP_ID_EXP_1 data["object_key"] = "thisisanobjectkey" data["job_type"] = "restore" data["restore_bucket_dest"] = "my_s3_bucket" data["job_status"] = "invalid" data["request_time"] = utc_now_exp try: requests_db.submit_request(data) self.fail("expected BadRequestError") except requests_db.BadRequestError as err: exp_msg = "Missing 'granule_id' in input data" self.assertEqual(exp_msg, str(err))
def test_submit_request_inprogress_status(self): """ Tests that an inprogress job is written to the db """ utc_now_exp = UTC_NOW_EXP_1 requests_db.get_utc_now_iso = Mock(return_value=utc_now_exp) requests_db.request_id_generator = Mock(side_effect=[REQUEST_ID1]) data = {} data["request_id"] = REQUEST_ID1 data["request_group_id"] = REQUEST_GROUP_ID_EXP_1 data["granule_id"] = "granule_1" data["object_key"] = "thisisanobjectkey" data["job_type"] = "restore" data["restore_bucket_dest"] = "my_s3_bucket" data["archive_bucket_dest"] = "your_s3_bucket" data["job_status"] = "inprogress" data["request_time"] = utc_now_exp qresult, exp_result = create_insert_request( REQUEST_ID1, data["request_group_id"], data["granule_id"], data["object_key"], data["job_type"], data["restore_bucket_dest"], data["job_status"], data["archive_bucket_dest"], data["request_time"], None, None) database.single_query = Mock(side_effect=[qresult, exp_result, None, None]) mock_ssm_get_parameter(4) try: requests_db.submit_request(data) database.single_query.assert_called_once() except requests_db.DatabaseError as err: self.fail(f"submit_request. {str(err)}") try: result = requests_db.get_job_by_request_id(REQUEST_ID1) expected = result_to_json(exp_result) self.assertEqual(expected, result) except requests_db.DatabaseError as err: self.fail(f"get_job_by_request_id. {str(err)}")
def test_no_db_connect(self): """ Tests a database connection failure """ uuid.uuid4 = Mock(side_effect=[REQUEST_ID1]) os.environ["DATABASE_NAME"] = "noexist" data = {} data["request_id"] = REQUEST_ID1 data["request_group_id"] = requests_db.request_id_generator() data["granule_id"] = "granule_1" data["object_key"] = "thisisanobjectkey" data["job_type"] = "restore" data["restore_bucket_dest"] = "my_s3_bucket" data["job_status"] = "inprogress" mock_ssm_get_parameter(1) exp_err = 'Database Error. FATAL: database "noexist" does not exist\n' database.single_query = Mock(side_effect=[requests_db.DbError( exp_err)]) try: requests_db.submit_request(data) self.fail("expected DatabaseError") except requests_db.DatabaseError as err: self.assertEqual(exp_err, str(err)) database.single_query.assert_called_once()
def create_test_requests(self): """ creates jobs in the db """ boto3.client = Mock() mock_ssm_get_parameter(7) requests_db.get_utc_now_iso = Mock(side_effect=[ UTC_NOW_EXP_1, UTC_NOW_EXP_4, UTC_NOW_EXP_4, UTC_NOW_EXP_4, UTC_NOW_EXP_5, UTC_NOW_EXP_5, UTC_NOW_EXP_6, UTC_NOW_EXP_6, UTC_NOW_EXP_7, UTC_NOW_EXP_7, UTC_NOW_EXP_8, UTC_NOW_EXP_8, ]) requests_db.request_id_generator = Mock(side_effect=[ REQUEST_ID1, REQUEST_ID2, REQUEST_ID3, REQUEST_ID4, REQUEST_ID5, REQUEST_ID6 ]) obj = {} try: obj["request_group_id"] = REQUEST_GROUP_ID_EXP_1 obj["granule_id"] = "granule_1" obj["key"] = "objectkey_1" obj["glacier_bucket"] = "my_s3_bucket" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "complete", UTC_NOW_EXP_1, UTC_NOW_EXP_4) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_2 obj["granule_id"] = "granule_4" obj["key"] = "objectkey_4" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "error", UTC_NOW_EXP_4, None, "oh oh, an error happened") requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_3 obj["granule_id"] = "granule_5" obj["key"] = "dr-glacier/MOD09GQ.A0219114.N5aUCG.006.0656338553321.txt" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_5, UTC_NOW_EXP_5) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_3 obj["granule_id"] = "granule_6" obj["key"] = "dr-glacier/MOD09GQ.A0219114.N5aUCG.006.0656338553321.hdf" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_6, UTC_NOW_EXP_6) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_4 obj["granule_id"] = "granule_4" obj["key"] = "objectkey_4" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_7, UTC_NOW_EXP_7) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_5 obj["granule_id"] = "granule_1" obj["key"] = "objectkey_1" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_8, UTC_NOW_EXP_8) requests_db.submit_request(data) results = requests_db.get_all_requests() return results except requests_db.DatabaseError as err: self.fail(f"submit_request. {str(err)}")
def create_test_requests(self): #pylint: disable-msg=too-many-statements """ creates jobs in the db """ boto3.client = Mock() mock_ssm_get_parameter(12) requests_db.get_utc_now_iso = Mock(side_effect=[ UTC_NOW_EXP_1, UTC_NOW_EXP_4, UTC_NOW_EXP_2, UTC_NOW_EXP_5, UTC_NOW_EXP_3, UTC_NOW_EXP_6, UTC_NOW_EXP_4, UTC_NOW_EXP_4, UTC_NOW_EXP_5, UTC_NOW_EXP_5, UTC_NOW_EXP_6, UTC_NOW_EXP_6, UTC_NOW_EXP_7, UTC_NOW_EXP_7, UTC_NOW_EXP_8, UTC_NOW_EXP_8, UTC_NOW_EXP_9, UTC_NOW_EXP_9, UTC_NOW_EXP_10, UTC_NOW_EXP_10, UTC_NOW_EXP_11, UTC_NOW_EXP_11 ]) requests_db.request_id_generator = Mock(side_effect=[ REQUEST_ID1, REQUEST_ID2, REQUEST_ID3, REQUEST_ID4, REQUEST_ID5, REQUEST_ID6, REQUEST_ID7, REQUEST_ID8, REQUEST_ID9, REQUEST_ID10, REQUEST_ID11 ]) obj = {} try: obj["request_group_id"] = REQUEST_GROUP_ID_EXP_1 obj["granule_id"] = "granule_1" obj["key"] = "objectkey_1" obj["glacier_bucket"] = "my_s3_bucket" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "complete", UTC_NOW_EXP_1, UTC_NOW_EXP_4) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_1 obj["granule_id"] = "granule_2" obj["key"] = "objectkey_2" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "complete", UTC_NOW_EXP_2, UTC_NOW_EXP_5) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_1 obj["granule_id"] = "granule_3" obj["key"] = "objectkey_3" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "complete", UTC_NOW_EXP_3, UTC_NOW_EXP_6) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_2 obj["granule_id"] = "granule_4" obj["key"] = "objectkey_4" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "error", UTC_NOW_EXP_4, None, "oh oh, an error happened") requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_3 obj["granule_id"] = "granule_5" obj["key"] = "objectkey_5" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_5, UTC_NOW_EXP_5) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_3 obj["granule_id"] = "granule_6" obj["key"] = "objectkey_6" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_6, UTC_NOW_EXP_6) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_4 obj["granule_id"] = "granule_4" obj["key"] = "objectkey_4" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_7, UTC_NOW_EXP_7) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_5 obj["granule_id"] = "granule_1" obj["key"] = "objectkey_1" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_8, UTC_NOW_EXP_8) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_5 obj["granule_id"] = "granule_2" obj["key"] = "objectkey_2" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_9, UTC_NOW_EXP_9) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_5 obj["granule_id"] = "granule_3" obj["key"] = "objectkey_3" obj["dest_bucket"] = PROTECTED_BUCKET data = create_data(obj, "restore", "inprogress", UTC_NOW_EXP_10, UTC_NOW_EXP_10) requests_db.submit_request(data) obj["request_group_id"] = REQUEST_GROUP_ID_EXP_6 obj["granule_id"] = "granule_7" obj["key"] = "objectkey_7" obj["glacier_bucket"] = None obj["dest_bucket"] = None data = create_data(obj, "regenerate", "inprogress", UTC_NOW_EXP_11, UTC_NOW_EXP_11) requests_db.submit_request(data) results = requests_db.get_all_requests() return results except requests_db.DatabaseError as err: self.fail(f"submit_request. {str(err)}")