Core - Use json module for error_json exception type rendering instead of jinja2 (#4587)
This commit is contained in:
parent
f4abd5528f
commit
f717e494d3
@ -695,7 +695,7 @@ class CognitoIdpUser(BaseModel):
|
|||||||
for w in wrong_attrs
|
for w in wrong_attrs
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
+ "\\n"
|
+ "\n"
|
||||||
)
|
)
|
||||||
self.attribute_lookup = flat_attributes
|
self.attribute_lookup = flat_attributes
|
||||||
self.attributes = expand_attrs(flat_attributes)
|
self.attributes = expand_attrs(flat_attributes)
|
||||||
|
@ -794,7 +794,7 @@ class ConfigRule(ConfigEmptyDictable):
|
|||||||
if not set(param_names).issubset(allowed_names):
|
if not set(param_names).issubset(allowed_names):
|
||||||
raise InvalidParameterValueException(
|
raise InvalidParameterValueException(
|
||||||
"Unknown parameters provided in the inputParameters: "
|
"Unknown parameters provided in the inputParameters: "
|
||||||
+ self.input_parameters.replace('"', '\\"')
|
+ self.input_parameters
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify all the required parameters are specified.
|
# Verify all the required parameters are specified.
|
||||||
|
@ -37,12 +37,6 @@ ERROR_RESPONSE = """<?xml version="1.0" encoding="UTF-8"?>
|
|||||||
</ErrorResponse>
|
</ErrorResponse>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ERROR_JSON_RESPONSE = """{
|
|
||||||
"message": "{{message}}",
|
|
||||||
"__type": "{{error_type}}"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class RESTError(HTTPException):
|
class RESTError(HTTPException):
|
||||||
code = 400
|
code = 400
|
||||||
@ -53,22 +47,22 @@ class RESTError(HTTPException):
|
|||||||
"single_error": SINGLE_ERROR_RESPONSE,
|
"single_error": SINGLE_ERROR_RESPONSE,
|
||||||
"wrapped_single_error": WRAPPED_SINGLE_ERROR_RESPONSE,
|
"wrapped_single_error": WRAPPED_SINGLE_ERROR_RESPONSE,
|
||||||
"error": ERROR_RESPONSE,
|
"error": ERROR_RESPONSE,
|
||||||
"error_json": ERROR_JSON_RESPONSE,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, error_type, message, template="error", **kwargs):
|
def __init__(self, error_type, message, template="error", **kwargs):
|
||||||
super(RESTError, self).__init__()
|
super(RESTError, self).__init__()
|
||||||
env = Environment(loader=DictLoader(self.templates))
|
|
||||||
self.error_type = error_type
|
self.error_type = error_type
|
||||||
self.message = message
|
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):
|
def get_headers(self, *args, **kwargs):
|
||||||
return [
|
return [
|
||||||
@ -87,6 +81,9 @@ class DryRunClientError(RESTError):
|
|||||||
class JsonRESTError(RESTError):
|
class JsonRESTError(RESTError):
|
||||||
def __init__(self, error_type, message, template="error_json", **kwargs):
|
def __init__(self, error_type, message, template="error_json", **kwargs):
|
||||||
super(JsonRESTError, self).__init__(error_type, message, template, **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"
|
self.content_type = "application/json"
|
||||||
|
|
||||||
def get_body(self, *args, **kwargs):
|
def get_body(self, *args, **kwargs):
|
||||||
|
@ -31,8 +31,7 @@ def validate_alias(value):
|
|||||||
|
|
||||||
alias_pattern = r"^(?!D-|d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$"
|
alias_pattern = r"^(?!D-|d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$"
|
||||||
if not re.match(alias_pattern, value):
|
if not re.match(alias_pattern, value):
|
||||||
json_pattern = alias_pattern.replace("\\", r"\\")
|
return fr"satisfy regular expression pattern: {alias_pattern}"
|
||||||
return fr"satisfy regular expression pattern: {json_pattern}"
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@ -59,8 +58,7 @@ def validate_dns_ips(value):
|
|||||||
)
|
)
|
||||||
for dnsip in value:
|
for dnsip in value:
|
||||||
if not re.match(dnsip_pattern, dnsip):
|
if not re.match(dnsip_pattern, dnsip):
|
||||||
json_pattern = dnsip_pattern.replace("\\", r"\\")
|
return fr"satisfy regular expression pattern: {dnsip_pattern}"
|
||||||
return fr"satisfy regular expression pattern: {json_pattern}"
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@ -73,7 +71,7 @@ def validate_edition(value):
|
|||||||
|
|
||||||
def validate_name(value):
|
def validate_name(value):
|
||||||
"""Raise exception if name fails to match constraints."""
|
"""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):
|
if not re.match(name_pattern, value):
|
||||||
return fr"satisfy regular expression pattern: {name_pattern}"
|
return fr"satisfy regular expression pattern: {name_pattern}"
|
||||||
return ""
|
return ""
|
||||||
@ -88,9 +86,7 @@ def validate_password(value):
|
|||||||
r"(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s]))^.*$"
|
r"(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s]))^.*$"
|
||||||
)
|
)
|
||||||
if not re.match(passwd_pattern, value):
|
if not re.match(passwd_pattern, value):
|
||||||
# Can't have an odd number of backslashes in a literal.
|
return fr"satisfy regular expression pattern: {passwd_pattern}"
|
||||||
json_pattern = passwd_pattern.replace("\\", r"\\")
|
|
||||||
return fr"satisfy regular expression pattern: {json_pattern}"
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@ -98,8 +94,7 @@ def validate_short_name(value):
|
|||||||
"""Raise exception if short name fails to match constraints."""
|
"""Raise exception if short name fails to match constraints."""
|
||||||
short_name_pattern = r'^[^\/:*?"<>|.]+[^\/:*?"<>|]*$'
|
short_name_pattern = r'^[^\/:*?"<>|.]+[^\/:*?"<>|]*$'
|
||||||
if value and not re.match(short_name_pattern, value):
|
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: {short_name_pattern}"
|
||||||
return fr"satisfy regular expression pattern: {json_pattern}"
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
from moto.core.exceptions import RESTError, JsonRESTError
|
from moto.core.exceptions import JsonRESTError
|
||||||
|
|
||||||
|
|
||||||
class EmrError(RESTError):
|
|
||||||
code = 400
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidRequestException(JsonRESTError):
|
class InvalidRequestException(JsonRESTError):
|
||||||
@ -17,3 +13,10 @@ class ValidationException(JsonRESTError):
|
|||||||
super(ValidationException, self).__init__(
|
super(ValidationException, self).__init__(
|
||||||
"ValidationException", message, **kwargs
|
"ValidationException", message, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceNotFoundException(JsonRESTError):
|
||||||
|
def __init__(self, message, **kwargs):
|
||||||
|
super(ResourceNotFoundException, self).__init__(
|
||||||
|
"ResourceNotFoundException", message, **kwargs
|
||||||
|
)
|
||||||
|
@ -7,7 +7,11 @@ import pytz
|
|||||||
from boto3 import Session
|
from boto3 import Session
|
||||||
from dateutil.parser import parse as dtparse
|
from dateutil.parser import parse as dtparse
|
||||||
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel
|
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 (
|
from .utils import (
|
||||||
random_instance_group_id,
|
random_instance_group_id,
|
||||||
random_cluster_id,
|
random_cluster_id,
|
||||||
@ -482,7 +486,7 @@ class ElasticMapReduceBackend(BaseBackend):
|
|||||||
def describe_cluster(self, cluster_id):
|
def describe_cluster(self, cluster_id):
|
||||||
if cluster_id in self.clusters:
|
if cluster_id in self.clusters:
|
||||||
return self.clusters[cluster_id]
|
return self.clusters[cluster_id]
|
||||||
raise EmrError("ResourceNotFoundException", "", "error_json")
|
raise ResourceNotFoundException("")
|
||||||
|
|
||||||
def get_instance_groups(self, instance_group_ids):
|
def get_instance_groups(self, instance_group_ids):
|
||||||
return [
|
return [
|
||||||
|
@ -10,7 +10,7 @@ from moto.core.responses import AWSServiceSpec
|
|||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from moto.core.responses import xml_to_json_response
|
from moto.core.responses import xml_to_json_response
|
||||||
from moto.core.utils import tags_from_query_string
|
from moto.core.utils import tags_from_query_string
|
||||||
from .exceptions import EmrError
|
from .exceptions import ValidationException
|
||||||
from .models import emr_backends
|
from .models import emr_backends
|
||||||
from .utils import steps_from_query_string, Unflattener, ReleaseLabel
|
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. "
|
"Only one AMI version and release label may be specified. "
|
||||||
"Provided AMI: {0}, release label: {1}."
|
"Provided AMI: {0}, release label: {1}."
|
||||||
).format(ami_version, release_label)
|
).format(ami_version, release_label)
|
||||||
raise EmrError(
|
raise ValidationException(message=message)
|
||||||
error_type="ValidationException",
|
|
||||||
message=message,
|
|
||||||
template="error_json",
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if ami_version:
|
if ami_version:
|
||||||
kwargs["requested_ami_version"] = ami_version
|
kwargs["requested_ami_version"] = ami_version
|
||||||
@ -338,18 +334,10 @@ class ElasticMapReduceResponse(BaseResponse):
|
|||||||
ReleaseLabel(release_label) < ReleaseLabel("emr-5.7.0")
|
ReleaseLabel(release_label) < ReleaseLabel("emr-5.7.0")
|
||||||
):
|
):
|
||||||
message = "Custom AMI is not allowed"
|
message = "Custom AMI is not allowed"
|
||||||
raise EmrError(
|
raise ValidationException(message=message)
|
||||||
error_type="ValidationException",
|
|
||||||
message=message,
|
|
||||||
template="error_json",
|
|
||||||
)
|
|
||||||
elif ami_version:
|
elif ami_version:
|
||||||
message = "Custom AMI is not supported in this version of EMR"
|
message = "Custom AMI is not supported in this version of EMR"
|
||||||
raise EmrError(
|
raise ValidationException(message=message)
|
||||||
error_type="ValidationException",
|
|
||||||
message=message,
|
|
||||||
template="error_json",
|
|
||||||
)
|
|
||||||
|
|
||||||
step_concurrency_level = self._get_param("StepConcurrencyLevel")
|
step_concurrency_level = self._get_param("StepConcurrencyLevel")
|
||||||
if step_concurrency_level:
|
if step_concurrency_level:
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
|
import json
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from werkzeug.exceptions import HTTPException
|
from werkzeug.exceptions import HTTPException
|
||||||
from jinja2 import DictLoader, Environment
|
|
||||||
|
|
||||||
|
|
||||||
ERROR_JSON_RESPONSE = """{
|
|
||||||
"message": "{{message}}"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def exception_handler(f):
|
def exception_handler(f):
|
||||||
@ -23,18 +17,11 @@ def exception_handler(f):
|
|||||||
class ManagedBlockchainClientError(HTTPException):
|
class ManagedBlockchainClientError(HTTPException):
|
||||||
code = 400
|
code = 400
|
||||||
|
|
||||||
templates = {
|
|
||||||
"error": ERROR_JSON_RESPONSE,
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, error_type, message, **kwargs):
|
def __init__(self, error_type, message, **kwargs):
|
||||||
super(HTTPException, self).__init__()
|
super(HTTPException, self).__init__()
|
||||||
env = Environment(loader=DictLoader(self.templates))
|
|
||||||
self.error_type = error_type
|
self.error_type = error_type
|
||||||
self.message = message
|
self.message = message
|
||||||
self.description = env.get_template("error").render(
|
self.description = json.dumps({"message": self.message})
|
||||||
error_type=error_type, message=message, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_headers(self, *args, **kwargs):
|
def get_headers(self, *args, **kwargs):
|
||||||
return [
|
return [
|
||||||
|
@ -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"
|
"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
|
@mock_cognitoidp
|
||||||
def test_admin_delete_user_attributes_non_existing_user():
|
def test_admin_delete_user_attributes_non_existing_user():
|
||||||
|
@ -188,13 +188,10 @@ def test_describe_cluster():
|
|||||||
@mock_emr
|
@mock_emr
|
||||||
def test_describe_cluster_not_found():
|
def test_describe_cluster_not_found():
|
||||||
conn = boto3.client("emr", region_name="us-east-1")
|
conn = boto3.client("emr", region_name="us-east-1")
|
||||||
raised = False
|
with pytest.raises(ClientError) as e:
|
||||||
try:
|
|
||||||
conn.describe_cluster(ClusterId="DummyId")
|
conn.describe_cluster(ClusterId="DummyId")
|
||||||
except ClientError as e:
|
|
||||||
if e.response["Error"]["Code"] == "ResourceNotFoundException":
|
assert e.value.response["Error"]["Code"] == "ResourceNotFoundException"
|
||||||
raised = True
|
|
||||||
raised.should.equal(True)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_emr
|
@mock_emr
|
||||||
|
Loading…
Reference in New Issue
Block a user