Databrew: Allow spaces in names (#6923)
This commit is contained in:
		
							parent
							
								
									069218e1f3
								
							
						
					
					
						commit
						a0434335d2
					
				| @ -1,5 +1,6 @@ | |||||||
| import json | import json | ||||||
| from typing import Any, Dict, Union | from typing import Any, Dict, Union | ||||||
|  | from urllib.parse import unquote | ||||||
| 
 | 
 | ||||||
| from moto.core.common_types import TYPE_RESPONSE | from moto.core.common_types import TYPE_RESPONSE | ||||||
| from moto.core.responses import BaseResponse | from moto.core.responses import BaseResponse | ||||||
| @ -39,7 +40,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
|         # https://docs.aws.amazon.com/databrew/latest/dg/API_DeleteRecipeVersion.html |         # https://docs.aws.amazon.com/databrew/latest/dg/API_DeleteRecipeVersion.html | ||||||
|         if request.method == "DELETE": |         if request.method == "DELETE": | ||||||
|             split_path = self.parsed_url.path.strip("/").split("/") |             split_path = self._get_path().strip("/").split("/") | ||||||
|             recipe_name = split_path[1] |             recipe_name = split_path[1] | ||||||
|             recipe_version = split_path[3] |             recipe_version = split_path[3] | ||||||
|             self.databrew_backend.delete_recipe_version(recipe_name, recipe_version) |             self.databrew_backend.delete_recipe_version(recipe_name, recipe_version) | ||||||
| @ -49,6 +50,9 @@ class DataBrewResponse(BaseResponse): | |||||||
|                 json.dumps({"Name": recipe_name, "RecipeVersion": recipe_version}), |                 json.dumps({"Name": recipe_name, "RecipeVersion": recipe_version}), | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|  |     def _get_path(self) -> str: | ||||||
|  |         return unquote(self.parsed_url.path) | ||||||
|  | 
 | ||||||
|     @amzn_request_id |     @amzn_request_id | ||||||
|     def list_recipes(self) -> str: |     def list_recipes(self) -> str: | ||||||
|         # https://docs.aws.amazon.com/databrew/latest/dg/API_ListRecipes.html |         # https://docs.aws.amazon.com/databrew/latest/dg/API_ListRecipes.html | ||||||
| @ -98,7 +102,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def publish_recipe(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] |     def publish_recipe(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
|         if request.method == "POST": |         if request.method == "POST": | ||||||
|             recipe_name = self.parsed_url.path.strip("/").split("/", 2)[1] |             recipe_name = self._get_path().strip("/").split("/", 2)[1] | ||||||
|             recipe_description = self.parameters.get("Description") |             recipe_description = self.parameters.get("Description") | ||||||
|             self.databrew_backend.publish_recipe(recipe_name, recipe_description) |             self.databrew_backend.publish_recipe(recipe_name, recipe_description) | ||||||
|             return 200, {}, json.dumps({"Name": recipe_name}) |             return 200, {}, json.dumps({"Name": recipe_name}) | ||||||
| @ -126,7 +130,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def recipe_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] |     def recipe_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
| 
 | 
 | ||||||
|         recipe_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] |         recipe_name = self._get_path().rstrip("/").rsplit("/", 1)[1] | ||||||
| 
 | 
 | ||||||
|         if request.method == "PUT": |         if request.method == "PUT": | ||||||
|             return self.put_recipe_response(recipe_name) |             return self.put_recipe_response(recipe_name) | ||||||
| @ -177,7 +181,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def ruleset_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] |     def ruleset_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
| 
 | 
 | ||||||
|         ruleset_name = self.parsed_url.path.split("/")[-1] |         ruleset_name = self._get_path().split("/")[-1] | ||||||
| 
 | 
 | ||||||
|         if request.method == "PUT": |         if request.method == "PUT": | ||||||
|             response = self.put_ruleset_response(ruleset_name) |             response = self.put_ruleset_response(ruleset_name) | ||||||
| @ -281,7 +285,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def dataset_response(self, request: Any, full_url: str, headers: Any) -> Union[str, TYPE_RESPONSE]:  # type: ignore[return] |     def dataset_response(self, request: Any, full_url: str, headers: Any) -> Union[str, TYPE_RESPONSE]:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
| 
 | 
 | ||||||
|         dataset_name = self.parsed_url.path.split("/")[-1] |         dataset_name = self._get_path().split("/")[-1] | ||||||
| 
 | 
 | ||||||
|         if request.method == "POST": |         if request.method == "POST": | ||||||
|             return self.create_dataset() |             return self.create_dataset() | ||||||
| @ -334,7 +338,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def job_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] |     def job_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
| 
 | 
 | ||||||
|         job_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] |         job_name = self._get_path().rstrip("/").rsplit("/", 1)[1] | ||||||
| 
 | 
 | ||||||
|         if request.method == "GET": |         if request.method == "GET": | ||||||
|             return self.get_job_response(job_name) |             return self.get_job_response(job_name) | ||||||
| @ -424,7 +428,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def profile_job_response(self, request: Any, full_url: str, headers: Any) -> str:  # type: ignore[return] |     def profile_job_response(self, request: Any, full_url: str, headers: Any) -> str:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
| 
 | 
 | ||||||
|         job_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] |         job_name = self._get_path().rstrip("/").rsplit("/", 1)[1] | ||||||
| 
 | 
 | ||||||
|         if request.method == "PUT": |         if request.method == "PUT": | ||||||
|             return self.update_profile_job_response(job_name) |             return self.update_profile_job_response(job_name) | ||||||
| @ -433,7 +437,7 @@ class DataBrewResponse(BaseResponse): | |||||||
|     def recipe_job_response(self, request: Any, full_url: str, headers: Any) -> str:  # type: ignore[return] |     def recipe_job_response(self, request: Any, full_url: str, headers: Any) -> str:  # type: ignore[return] | ||||||
|         self.setup_class(request, full_url, headers) |         self.setup_class(request, full_url, headers) | ||||||
| 
 | 
 | ||||||
|         job_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] |         job_name = self._get_path().rstrip("/").rsplit("/", 1)[1] | ||||||
| 
 | 
 | ||||||
|         if request.method == "PUT": |         if request.method == "PUT": | ||||||
|             return self.update_recipe_job_response(job_name) |             return self.update_recipe_job_response(job_name) | ||||||
|  | |||||||
| @ -177,20 +177,22 @@ def test_create_dataset_that_already_exists(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_delete_dataset(): | @pytest.mark.parametrize("name", ["name", "name with space"]) | ||||||
|  | def test_delete_dataset(name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
|     response = _create_test_dataset(client) |     response = _create_test_dataset(client, dataset_name=name) | ||||||
|  |     assert response["Name"] == name | ||||||
| 
 | 
 | ||||||
|     # Check dataset exists |     # Check dataset exists | ||||||
|     dataset = client.describe_dataset(Name=response["Name"]) |     dataset = client.describe_dataset(Name=name) | ||||||
|     assert dataset["Name"] == response["Name"] |     assert dataset["Name"] == name | ||||||
| 
 | 
 | ||||||
|     # Delete the dataset |     # Delete the dataset | ||||||
|     client.delete_dataset(Name=response["Name"]) |     client.delete_dataset(Name=name) | ||||||
| 
 | 
 | ||||||
|     # Check it does not exist anymore |     # Check it does not exist anymore | ||||||
|     with pytest.raises(ClientError) as exc: |     with pytest.raises(ClientError) as exc: | ||||||
|         client.describe_dataset(Name=response["Name"]) |         client.describe_dataset(Name=name) | ||||||
| 
 | 
 | ||||||
|     err = exc.value.response["Error"] |     err = exc.value.response["Error"] | ||||||
|     assert err["Code"] == "ResourceNotFoundException" |     assert err["Code"] == "ResourceNotFoundException" | ||||||
| @ -198,20 +200,21 @@ def test_delete_dataset(): | |||||||
| 
 | 
 | ||||||
|     # Check that a dataset that does not exist errors |     # Check that a dataset that does not exist errors | ||||||
|     with pytest.raises(ClientError) as exc: |     with pytest.raises(ClientError) as exc: | ||||||
|         client.delete_dataset(Name=response["Name"]) |         client.delete_dataset(Name=name) | ||||||
|     err = exc.value.response["Error"] |     err = exc.value.response["Error"] | ||||||
|     assert err["Code"] == "ResourceNotFoundException" |     assert err["Code"] == "ResourceNotFoundException" | ||||||
|     assert err["Message"] == "One or more resources can't be found." |     assert err["Message"] == "One or more resources can't be found." | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_update_dataset(): | @pytest.mark.parametrize("name", ["name", "name with space"]) | ||||||
|  | def test_update_dataset(name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
|     response = _create_test_dataset(client) |     _create_test_dataset(client, dataset_name=name) | ||||||
| 
 | 
 | ||||||
|     # Update the dataset and check response |     # Update the dataset and check response | ||||||
|     dataset = client.update_dataset( |     dataset = client.update_dataset( | ||||||
|         Name=response["Name"], |         Name=name, | ||||||
|         Format="TEST", |         Format="TEST", | ||||||
|         Input={ |         Input={ | ||||||
|             "S3InputDefinition": { |             "S3InputDefinition": { | ||||||
| @ -232,15 +235,15 @@ def test_update_dataset(): | |||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|     ) |     ) | ||||||
|     assert dataset["Name"] == response["Name"] |     assert dataset["Name"] == name | ||||||
| 
 | 
 | ||||||
|     # Describe the dataset and check the changes |     # Describe the dataset and check the changes | ||||||
|     dataset = client.describe_dataset(Name=response["Name"]) |     dataset = client.describe_dataset(Name=name) | ||||||
|     assert dataset["Name"] == response["Name"] |     assert dataset["Name"] == name | ||||||
|     assert dataset["Format"] == "TEST" |     assert dataset["Format"] == "TEST" | ||||||
|     assert ( |     assert ( | ||||||
|         dataset["ResourceArn"] |         dataset["ResourceArn"] | ||||||
|         == f"arn:aws:databrew:us-west-1:{ACCOUNT_ID}:dataset/{response['Name']}" |         == f"arn:aws:databrew:us-west-1:{ACCOUNT_ID}:dataset/{name}" | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -184,12 +184,12 @@ def test_describe_job_with_long_name(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_update_profile_job(): | @pytest.mark.parametrize("job_name", ["name", "name with space"]) | ||||||
|  | def test_update_profile_job(job_name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
| 
 | 
 | ||||||
|     # Create the job |     # Create the job | ||||||
|     response = _create_test_profile_job(client) |     response = _create_test_profile_job(client, job_name=job_name) | ||||||
|     job_name = response["Name"] |  | ||||||
| 
 | 
 | ||||||
|     # Update the job by changing RoleArn |     # Update the job by changing RoleArn | ||||||
|     update_response = client.update_profile_job( |     update_response = client.update_profile_job( | ||||||
| @ -205,12 +205,12 @@ def test_update_profile_job(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_update_recipe_job(): | @pytest.mark.parametrize("job_name", ["name", "name with space"]) | ||||||
|  | def test_update_recipe_job(job_name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
| 
 | 
 | ||||||
|     # Create the job |     # Create the job | ||||||
|     response = _create_test_recipe_job(client) |     response = _create_test_recipe_job(client, job_name=job_name) | ||||||
|     job_name = response["Name"] |  | ||||||
| 
 | 
 | ||||||
|     # Update the job by changing RoleArn |     # Update the job by changing RoleArn | ||||||
|     update_response = client.update_recipe_job(Name=job_name, RoleArn="a" * 20) |     update_response = client.update_recipe_job(Name=job_name, RoleArn="a" * 20) | ||||||
| @ -250,12 +250,12 @@ def test_update_recipe_job_does_not_exist(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_delete_job(): | @pytest.mark.parametrize("job_name", ["name", "name with space"]) | ||||||
|  | def test_delete_job(job_name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
| 
 | 
 | ||||||
|     # Create the job |     # Create the job | ||||||
|     response = _create_test_recipe_job(client) |     _create_test_recipe_job(client, job_name=job_name) | ||||||
|     job_name = response["Name"] |  | ||||||
| 
 | 
 | ||||||
|     # Delete the job |     # Delete the job | ||||||
|     response = client.delete_job(Name=job_name) |     response = client.delete_job(Name=job_name) | ||||||
|  | |||||||
| @ -162,13 +162,14 @@ def test_describe_recipe_latest_working(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_describe_recipe_with_version(): | @pytest.mark.parametrize("name", ["name", "name with space"]) | ||||||
|  | def test_describe_recipe_with_version(name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
|     response = _create_test_recipe(client) |     _create_test_recipe(client, recipe_name=name) | ||||||
| 
 | 
 | ||||||
|     recipe = client.describe_recipe(Name=response["Name"], RecipeVersion="0.1") |     recipe = client.describe_recipe(Name=name, RecipeVersion="0.1") | ||||||
| 
 | 
 | ||||||
|     assert recipe["Name"] == response["Name"] |     assert recipe["Name"] == name | ||||||
|     assert len(recipe["Steps"]) == 1 |     assert len(recipe["Steps"]) == 1 | ||||||
|     assert recipe["RecipeVersion"] == "0.1" |     assert recipe["RecipeVersion"] == "0.1" | ||||||
| 
 | 
 | ||||||
| @ -260,12 +261,13 @@ def test_describe_recipe_with_invalid_version(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_update_recipe(): | @pytest.mark.parametrize("name", ["name", "name with space"]) | ||||||
|  | def test_update_recipe(name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
|     response = _create_test_recipe(client) |     _create_test_recipe(client, recipe_name=name) | ||||||
| 
 | 
 | ||||||
|     recipe = client.update_recipe( |     recipe = client.update_recipe( | ||||||
|         Name=response["Name"], |         Name=name, | ||||||
|         Steps=[ |         Steps=[ | ||||||
|             { |             { | ||||||
|                 "Action": { |                 "Action": { | ||||||
| @ -290,13 +292,11 @@ def test_update_recipe(): | |||||||
|         ], |         ], | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     assert recipe["Name"] == response["Name"] |     assert recipe["Name"] == name | ||||||
| 
 | 
 | ||||||
|     # Describe the recipe and check the changes |     # Describe the recipe and check the changes | ||||||
|     recipe = client.describe_recipe( |     recipe = client.describe_recipe(Name=name, RecipeVersion="LATEST_WORKING") | ||||||
|         Name=response["Name"], RecipeVersion="LATEST_WORKING" |     assert recipe["Name"] == name | ||||||
|     ) |  | ||||||
|     assert recipe["Name"] == response["Name"] |  | ||||||
|     assert len(recipe["Steps"]) == 1 |     assert len(recipe["Steps"]) == 1 | ||||||
|     assert recipe["Steps"][0]["Action"]["Parameters"]["removeCustomValue"] == "true" |     assert recipe["Steps"][0]["Action"]["Parameters"]["removeCustomValue"] == "true" | ||||||
| 
 | 
 | ||||||
| @ -349,11 +349,11 @@ def test_create_recipe_that_already_exists(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_publish_recipe(): | @pytest.mark.parametrize("recipe_name", ["name", "name with space"]) | ||||||
|  | def test_publish_recipe(recipe_name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
| 
 | 
 | ||||||
|     response = _create_test_recipe(client) |     _create_test_recipe(client, recipe_name=recipe_name) | ||||||
|     recipe_name = response["Name"] |  | ||||||
| 
 | 
 | ||||||
|     # Before a recipe is published, we should not be able to retrieve a published version |     # Before a recipe is published, we should not be able to retrieve a published version | ||||||
|     with pytest.raises(ClientError) as exc: |     with pytest.raises(ClientError) as exc: | ||||||
| @ -412,10 +412,11 @@ def test_publish_long_recipe_name(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_delete_recipe_version(): | @pytest.mark.parametrize("recipe_name", ["name", "name with space"]) | ||||||
|  | def test_delete_recipe_version(recipe_name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
|     response = _create_test_recipe(client) |     _create_test_recipe(client, recipe_name=recipe_name) | ||||||
|     recipe_name = response["Name"] | 
 | ||||||
|     client.delete_recipe_version(Name=recipe_name, RecipeVersion="LATEST_WORKING") |     client.delete_recipe_version(Name=recipe_name, RecipeVersion="LATEST_WORKING") | ||||||
|     with pytest.raises(ClientError) as exc: |     with pytest.raises(ClientError) as exc: | ||||||
|         client.describe_recipe(Name=recipe_name) |         client.describe_recipe(Name=recipe_name) | ||||||
|  | |||||||
| @ -144,13 +144,14 @@ def test_delete_ruleset(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_databrew | @mock_databrew | ||||||
| def test_update_ruleset(): | @pytest.mark.parametrize("name", ["name", "name with space"]) | ||||||
|  | def test_update_ruleset(name): | ||||||
|     client = _create_databrew_client() |     client = _create_databrew_client() | ||||||
|     response = _create_test_ruleset(client) |     _create_test_ruleset(client, ruleset_name=name) | ||||||
| 
 | 
 | ||||||
|     # Update the ruleset and check response |     # Update the ruleset and check response | ||||||
|     ruleset = client.update_ruleset( |     ruleset = client.update_ruleset( | ||||||
|         Name=response["Name"], |         Name=name, | ||||||
|         Rules=[ |         Rules=[ | ||||||
|             { |             { | ||||||
|                 "Name": "Assert values > 0", |                 "Name": "Assert values > 0", | ||||||
| @ -165,10 +166,10 @@ def test_update_ruleset(): | |||||||
|             } |             } | ||||||
|         ], |         ], | ||||||
|     ) |     ) | ||||||
|     assert ruleset["Name"] == response["Name"] |     assert ruleset["Name"] == name | ||||||
| 
 | 
 | ||||||
|     # Describe the ruleset and check the changes |     # Describe the ruleset and check the changes | ||||||
|     ruleset = client.describe_ruleset(Name=response["Name"]) |     ruleset = client.describe_ruleset(Name=name) | ||||||
|     assert ruleset["Name"] == response["Name"] |     assert ruleset["Name"] == name | ||||||
|     assert len(ruleset["Rules"]) == 1 |     assert len(ruleset["Rules"]) == 1 | ||||||
|     assert ruleset["Rules"][0]["SubstitutionMap"][":val1"] == "10" |     assert ruleset["Rules"][0]["SubstitutionMap"][":val1"] == "10" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user