123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- import mock
- import pytest
- from copy import deepcopy
- from boto3.dynamodb.conditions import Key
- pytestmark = [
- pytest.mark.acceptance_iam,
- pytest.mark.api,
- pytest.mark.data_mappers,
- pytest.mark.usefixtures("empty_data_mappers"),
- ]
- @pytest.mark.auth
- def test_auth(api_client_iam, data_mapper_base_endpoint):
- headers = {"Authorization": None}
- assert (
- 403
- == api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, "a"), headers=headers
- ).status_code
- )
- assert (
- 403
- == api_client_iam.get(data_mapper_base_endpoint, headers=headers).status_code
- )
- assert (
- 403
- == api_client_iam.delete(
- "{}/{}".format(data_mapper_base_endpoint, "a"), headers=headers
- ).status_code
- )
- def test_it_creates_data_mapper(
- api_client_iam,
- data_mapper_base_endpoint,
- data_mapper_table,
- glue_table_factory,
- stack,
- iam_arn,
- ):
- # Arrange
- table = glue_table_factory()
- key = "test"
- data_mapper = {
- "DataMapperId": key,
- "Columns": ["a"],
- "QueryExecutor": "athena",
- "QueryExecutorParameters": {
- "DataCatalogProvider": "glue",
- "Database": table["Database"],
- "Table": table["Table"],
- },
- "Format": "parquet",
- "RoleArn": "arn:aws:iam::123456789012:role/S3F2DataAccessRole",
- "DeleteOldVersions": False,
- "IgnoreObjectNotFoundExceptions": True,
- }
- # Act
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key), json=data_mapper
- )
- response_body = response.json()
- # Assert
- expected = deepcopy(data_mapper)
- expected["CreatedBy"] = {
- "Username": iam_arn,
- "Sub": mock.ANY,
- }
- expected["DeleteOldVersions"] = False
- # Check the response is ok
- assert 201 == response.status_code
- assert expected == response_body
- # Check the item exists in the DDB Table
- query_result = data_mapper_table.query(
- KeyConditionExpression=Key("DataMapperId").eq(key)
- )
- assert 1 == len(query_result["Items"])
- assert expected == query_result["Items"][0]
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_modifies_data_mapper(
- api_client_iam,
- data_mapper_base_endpoint,
- data_mapper_table,
- glue_table_factory,
- stack,
- ):
- # Arrange
- table = glue_table_factory()
- key = "test"
- data_mapper = {
- "DataMapperId": key,
- "Columns": ["a"],
- "QueryExecutor": "athena",
- "QueryExecutorParameters": {
- "DataCatalogProvider": "glue",
- "Database": table["Database"],
- "Table": table["Table"],
- },
- "Format": "parquet",
- "RoleArn": "arn:aws:iam::123456789012:role/S3F2DataAccessRole",
- "DeleteOldVersions": False,
- "IgnoreObjectNotFoundExceptions": False,
- }
- # Act
- create_response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key), json=data_mapper
- )
- data_mapper["Columns"] = ["b"]
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key), json=data_mapper
- )
- response_body = response.json()
- # Assert
- assert 201 == response.status_code
- assert response_body["Columns"] == ["b"]
- # Check the item exists in the DDB Table
- query_result = data_mapper_table.query(
- KeyConditionExpression=Key("DataMapperId").eq(key)
- )
- assert 1 == len(query_result["Items"])
- assert query_result["Items"][0]["Columns"] == ["b"]
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_creates_without_optionals(
- api_client_iam,
- data_mapper_base_endpoint,
- data_mapper_table,
- glue_table_factory,
- stack,
- iam_arn,
- ):
- # Arrange
- table = glue_table_factory()
- key = "test"
- data_mapper = {
- "DataMapperId": key,
- "Columns": ["a"],
- "QueryExecutor": "athena",
- "QueryExecutorParameters": {
- "DataCatalogProvider": "glue",
- "Database": table["Database"],
- "Table": table["Table"],
- },
- "RoleArn": "arn:aws:iam::123456789012:role/S3F2DataAccessRole",
- }
- # Act
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key), json=data_mapper
- )
- response_body = response.json()
- # Assert
- expected = deepcopy(data_mapper)
- expected["Format"] = "parquet"
- expected["CreatedBy"] = {
- "Username": iam_arn,
- "Sub": mock.ANY,
- }
- expected["DeleteOldVersions"] = True
- expected["IgnoreObjectNotFoundExceptions"] = False
- # Check the response is ok
- assert 201 == response.status_code
- assert expected == response_body
- # Check the item exists in the DDB Table
- query_result = data_mapper_table.query(
- KeyConditionExpression=Key("DataMapperId").eq(key)
- )
- assert 1 == len(query_result["Items"])
- assert expected == query_result["Items"][0]
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_rejects_invalid_data_mapper(
- api_client_iam, data_mapper_base_endpoint, glue_table_factory, stack
- ):
- # Arrange
- table = glue_table_factory()
- key = "test"
- data_mapper = {
- "DataMapperId": key,
- "Columns": ["a"],
- "QueryExecutor": "athena",
- "QueryExecutorParameters": {
- "DataCatalogProvider": "glue",
- "Database": table["Database"],
- "Table": table["Table"],
- },
- "RoleArn": "arn:aws:iam::123456789012:role/WrongRoleName",
- }
- # Act
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key), json=data_mapper
- )
- response_body = response.json()
- # Assert
- assert 422 == response.status_code
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_rejects_invalid_role(api_client_iam, data_mapper_base_endpoint, stack):
- key = "test"
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key), json={"INVALID": "PAYLOAD"}
- )
- assert 422 == response.status_code
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_rejects_invalid_data_source(
- api_client_iam, data_mapper_base_endpoint, stack
- ):
- key = "test"
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key),
- json={
- "Columns": ["column"],
- "QueryExecutor": "unsupported",
- "QueryExecutorParameters": {},
- "Format": "parquet",
- },
- )
- assert 422 == response.status_code
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_rejects_invalid_data_catalog_provider(
- api_client_iam, data_mapper_base_endpoint, stack
- ):
- key = "test"
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key),
- json={
- "Columns": ["column"],
- "QueryExecutor": "athena",
- "QueryExecutorParameters": {
- "Database": "database",
- "Table": "table",
- "DataCatalogProvider": "invalid",
- },
- "Format": "parquet",
- "RoleArn": "arn:aws:iam::123456789012:role/S3F2DataAccessRole",
- },
- )
- assert 422 == response.status_code
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_rejects_missing_glue_catalog(
- api_client_iam, data_mapper_base_endpoint, stack
- ):
- key = "test"
- response = api_client_iam.put(
- "{}/{}".format(data_mapper_base_endpoint, key),
- json={
- "Columns": ["column"],
- "QueryExecutor": "athena",
- "QueryExecutorParameters": {
- "Database": "non_existent",
- "Table": "non_existent",
- "DataCatalogProvider": "glue",
- },
- "Format": "parquet",
- "RoleArn": "arn:aws:iam::123456789012:role/S3F2DataAccessRole",
- },
- )
- assert 400 == response.status_code
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_gets_all_data_mappers(
- api_client_iam, data_mapper_base_endpoint, glue_data_mapper_factory, stack
- ):
- # Arrange
- item = glue_data_mapper_factory()
- # Act
- response = api_client_iam.get(data_mapper_base_endpoint)
- response_body = response.json()
- # Assert
- assert response.status_code == 200
- assert isinstance(response_body.get("DataMappers"), list)
- assert item in response_body["DataMappers"]
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_gets_data_mapper(
- api_client_iam, data_mapper_base_endpoint, glue_data_mapper_factory, stack
- ):
- # Arrange
- item = glue_data_mapper_factory()
- key = item["DataMapperId"]
- # Act
- response = api_client_iam.get("{}/{}".format(data_mapper_base_endpoint, key))
- response_body = response.json()
- # Assert
- assert response.status_code == 200
- assert item == response_body
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
- def test_it_deletes_data_mapper(
- api_client_iam,
- glue_data_mapper_factory,
- data_mapper_base_endpoint,
- data_mapper_table,
- stack,
- ):
- # Arrange
- item = glue_data_mapper_factory()
- key = item["DataMapperId"]
- # Act
- response = api_client_iam.delete("{}/{}".format(data_mapper_base_endpoint, key))
- # Assert
- assert 204 == response.status_code
- # Check the item doesn't exist in the DDB Table
- query_result = data_mapper_table.query(
- KeyConditionExpression=Key("DataMapperId").eq(key)
- )
- assert 0 == len(query_result["Items"])
- assert (
- response.headers.get("Access-Control-Allow-Origin")
- == stack["APIAccessControlAllowOriginHeader"]
- )
|