Core - Use json module for error_json exception type rendering instead of jinja2 (#4587)

This commit is contained in:
Dominik Schubert 2021-11-17 17:19:03 +01:00 committed by GitHub
parent f4abd5528f
commit f717e494d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 54 additions and 71 deletions

View File

@ -695,7 +695,7 @@ class CognitoIdpUser(BaseModel):
for w in wrong_attrs
]
)
+ "\\n"
+ "\n"
)
self.attribute_lookup = flat_attributes
self.attributes = expand_attrs(flat_attributes)

View File

@ -794,7 +794,7 @@ class ConfigRule(ConfigEmptyDictable):
if not set(param_names).issubset(allowed_names):
raise InvalidParameterValueException(
"Unknown parameters provided in the inputParameters: "
+ self.input_parameters.replace('"', '\\"')
+ self.input_parameters
)
# Verify all the required parameters are specified.

View File

@ -37,12 +37,6 @@ ERROR_RESPONSE = """<?xml version="1.0" encoding="UTF-8"?>
</ErrorResponse>
"""
ERROR_JSON_RESPONSE = """{
"message": "{{message}}",
"__type": "{{error_type}}"
}
"""
class RESTError(HTTPException):
code = 400
@ -53,22 +47,22 @@ class RESTError(HTTPException):
"single_error": SINGLE_ERROR_RESPONSE,
"wrapped_single_error": WRAPPED_SINGLE_ERROR_RESPONSE,
"error": ERROR_RESPONSE,
"error_json": ERROR_JSON_RESPONSE,
}
def __init__(self, error_type, message, template="error", **kwargs):
super(RESTError, self).__init__()
env = Environment(loader=DictLoader(self.templates))
self.error_type = error_type
self.message = message
self.description = env.get_template(template).render(
error_type=error_type,
message=message,
request_id_tag=self.request_id_tag_name,
**kwargs
)
self.content_type = "application/xml"
if template in self.templates.keys():
env = Environment(loader=DictLoader(self.templates))
self.description = env.get_template(template).render(
error_type=error_type,
message=message,
request_id_tag=self.request_id_tag_name,
**kwargs
)
self.content_type = "application/xml"
def get_headers(self, *args, **kwargs):
return [
@ -87,6 +81,9 @@ class DryRunClientError(RESTError):
class JsonRESTError(RESTError):
def __init__(self, error_type, message, template="error_json", **kwargs):
super(JsonRESTError, self).__init__(error_type, message, template, **kwargs)
self.description = json.dumps(
{"__type": self.error_type, "message": self.message}
)
self.content_type = "application/json"
def get_body(self, *args, **kwargs):

View File

@ -31,8 +31,7 @@ def validate_alias(value):
alias_pattern = r"^(?!D-|d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$"
if not re.match(alias_pattern, value):
json_pattern = alias_pattern.replace("\\", r"\\")
return fr"satisfy regular expression pattern: {json_pattern}"
return fr"satisfy regular expression pattern: {alias_pattern}"
return ""
@ -59,8 +58,7 @@ def validate_dns_ips(value):
)
for dnsip in value:
if not re.match(dnsip_pattern, dnsip):
json_pattern = dnsip_pattern.replace("\\", r"\\")
return fr"satisfy regular expression pattern: {json_pattern}"
return fr"satisfy regular expression pattern: {dnsip_pattern}"
return ""
@ -73,7 +71,7 @@ def validate_edition(value):
def validate_name(value):
"""Raise exception if name fails to match constraints."""
name_pattern = r"^([a-zA-Z0-9]+[\\.-])+([a-zA-Z0-9])+$"
name_pattern = r"^([a-zA-Z0-9]+[\.-])+([a-zA-Z0-9])+$"
if not re.match(name_pattern, value):
return fr"satisfy regular expression pattern: {name_pattern}"
return ""
@ -88,9 +86,7 @@ def validate_password(value):
r"(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s]))^.*$"
)
if not re.match(passwd_pattern, value):
# Can't have an odd number of backslashes in a literal.
json_pattern = passwd_pattern.replace("\\", r"\\")
return fr"satisfy regular expression pattern: {json_pattern}"
return fr"satisfy regular expression pattern: {passwd_pattern}"
return ""
@ -98,8 +94,7 @@ def validate_short_name(value):
"""Raise exception if short name fails to match constraints."""
short_name_pattern = r'^[^\/:*?"<>|.]+[^\/:*?"<>|]*$'
if value and not re.match(short_name_pattern, value):
json_pattern = short_name_pattern.replace("\\", r"\\").replace('"', r"\"")
return fr"satisfy regular expression pattern: {json_pattern}"
return fr"satisfy regular expression pattern: {short_name_pattern}"
return ""

View File

@ -1,8 +1,4 @@
from moto.core.exceptions import RESTError, JsonRESTError
class EmrError(RESTError):
code = 400
from moto.core.exceptions import JsonRESTError
class InvalidRequestException(JsonRESTError):
@ -17,3 +13,10 @@ class ValidationException(JsonRESTError):
super(ValidationException, self).__init__(
"ValidationException", message, **kwargs
)
class ResourceNotFoundException(JsonRESTError):
def __init__(self, message, **kwargs):
super(ResourceNotFoundException, self).__init__(
"ResourceNotFoundException", message, **kwargs
)

View File

@ -7,7 +7,11 @@ import pytz
from boto3 import Session
from dateutil.parser import parse as dtparse
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel
from moto.emr.exceptions import EmrError, InvalidRequestException, ValidationException
from moto.emr.exceptions import (
InvalidRequestException,
ValidationException,
ResourceNotFoundException,
)
from .utils import (
random_instance_group_id,
random_cluster_id,
@ -482,7 +486,7 @@ class ElasticMapReduceBackend(BaseBackend):
def describe_cluster(self, cluster_id):
if cluster_id in self.clusters:
return self.clusters[cluster_id]
raise EmrError("ResourceNotFoundException", "", "error_json")
raise ResourceNotFoundException("")
def get_instance_groups(self, instance_group_ids):
return [

View File

@ -10,7 +10,7 @@ from moto.core.responses import AWSServiceSpec
from moto.core.responses import BaseResponse
from moto.core.responses import xml_to_json_response
from moto.core.utils import tags_from_query_string
from .exceptions import EmrError
from .exceptions import ValidationException
from .models import emr_backends
from .utils import steps_from_query_string, Unflattener, ReleaseLabel
@ -319,11 +319,7 @@ class ElasticMapReduceResponse(BaseResponse):
"Only one AMI version and release label may be specified. "
"Provided AMI: {0}, release label: {1}."
).format(ami_version, release_label)
raise EmrError(
error_type="ValidationException",
message=message,
template="error_json",
)
raise ValidationException(message=message)
else:
if ami_version:
kwargs["requested_ami_version"] = ami_version
@ -338,18 +334,10 @@ class ElasticMapReduceResponse(BaseResponse):
ReleaseLabel(release_label) < ReleaseLabel("emr-5.7.0")
):
message = "Custom AMI is not allowed"
raise EmrError(
error_type="ValidationException",
message=message,
template="error_json",
)
raise ValidationException(message=message)
elif ami_version:
message = "Custom AMI is not supported in this version of EMR"
raise EmrError(
error_type="ValidationException",
message=message,
template="error_json",
)
raise ValidationException(message=message)
step_concurrency_level = self._get_param("StepConcurrencyLevel")
if step_concurrency_level:

View File

@ -1,12 +1,6 @@
import json
from functools import wraps
from werkzeug.exceptions import HTTPException
from jinja2 import DictLoader, Environment
ERROR_JSON_RESPONSE = """{
"message": "{{message}}"
}
"""
def exception_handler(f):
@ -23,18 +17,11 @@ def exception_handler(f):
class ManagedBlockchainClientError(HTTPException):
code = 400
templates = {
"error": ERROR_JSON_RESPONSE,
}
def __init__(self, error_type, message, **kwargs):
super(HTTPException, self).__init__()
env = Environment(loader=DictLoader(self.templates))
self.error_type = error_type
self.message = message
self.description = env.get_template("error").render(
error_type=error_type, message=message, **kwargs
)
self.description = json.dumps({"message": self.message})
def get_headers(self, *args, **kwargs):
return [

View File

@ -2987,6 +2987,18 @@ def test_admin_delete_user_attributes_non_existing_attribute():
"Invalid user attributes: user.custom:foo: Attribute does not exist in the schema.\n"
)
with pytest.raises(ClientError) as exc:
conn.admin_delete_user_attributes(
UserPoolId=user_pool_id,
Username=username,
UserAttributeNames=["nickname", "custom:foo", "custom:bar"],
)
err = exc.value.response["Error"]
err["Code"].should.equal("InvalidParameterException")
err["Message"].should.equal(
"Invalid user attributes: user.custom:foo: Attribute does not exist in the schema.\nuser.custom:bar: Attribute does not exist in the schema.\n"
)
@mock_cognitoidp
def test_admin_delete_user_attributes_non_existing_user():

View File

@ -188,13 +188,10 @@ def test_describe_cluster():
@mock_emr
def test_describe_cluster_not_found():
conn = boto3.client("emr", region_name="us-east-1")
raised = False
try:
with pytest.raises(ClientError) as e:
conn.describe_cluster(ClusterId="DummyId")
except ClientError as e:
if e.response["Error"]["Code"] == "ResourceNotFoundException":
raised = True
raised.should.equal(True)
assert e.value.response["Error"]["Code"] == "ResourceNotFoundException"
@mock_emr