CloudFormation: Error when referencing unknown resource in FN:GetAtt (#6019)
This commit is contained in:
parent
4ac344bda6
commit
26904fdb36
@ -137,13 +137,16 @@ def clean_json(resource_json: Any, resources_map: "ResourceMap") -> Any:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
if "Fn::GetAtt" in resource_json:
|
if "Fn::GetAtt" in resource_json:
|
||||||
resource = resources_map.get(resource_json["Fn::GetAtt"][0])
|
resource_name = resource_json["Fn::GetAtt"][0]
|
||||||
|
resource = resources_map.get(resource_name)
|
||||||
if resource is None:
|
if resource is None:
|
||||||
return resource_json
|
raise ValidationError(
|
||||||
|
message=f"Template error: instance of Fn::GetAtt references undefined resource {resource_name}"
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
return resource.get_cfn_attribute(resource_json["Fn::GetAtt"][1])
|
return resource.get_cfn_attribute(resource_json["Fn::GetAtt"][1])
|
||||||
except NotImplementedError as n:
|
except NotImplementedError as n:
|
||||||
logger.warning(str(n).format(resource_json["Fn::GetAtt"][0]))
|
logger.warning(str(n).format(resource_name))
|
||||||
except UnformattedGetAttTemplateException:
|
except UnformattedGetAttTemplateException:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
"Bad Request",
|
"Bad Request",
|
||||||
|
@ -69,3 +69,16 @@ def get_template(lambda_code):
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_template_for_unknown_lambda():
|
||||||
|
return {
|
||||||
|
"AWSTemplateFormatVersion": "2010-09-09",
|
||||||
|
"Description": "Sample template using Custom Resource pointing to unknown Function",
|
||||||
|
"Resources": {
|
||||||
|
"CustomInfo": {
|
||||||
|
"Type": "Custom::Info",
|
||||||
|
"Properties": {"ServiceToken": {"Fn::GetAtt": ["InfoFunction", "Arn"]}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -3,12 +3,14 @@ import json
|
|||||||
import requests
|
import requests
|
||||||
import sure # noqa # pylint: disable=unused-import
|
import sure # noqa # pylint: disable=unused-import
|
||||||
import time
|
import time
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
from moto import mock_lambda, mock_cloudformation, mock_logs, mock_s3, settings
|
from moto import mock_lambda, mock_cloudformation, mock_logs, mock_s3, settings
|
||||||
from unittest import SkipTest
|
from unittest import SkipTest
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from tests.test_awslambda.utilities import wait_for_log_msg
|
from tests.test_awslambda.utilities import wait_for_log_msg
|
||||||
from .fixtures.custom_lambda import get_template
|
from .fixtures.custom_lambda import get_template, get_template_for_unknown_lambda
|
||||||
|
|
||||||
|
|
||||||
def get_lambda_code():
|
def get_lambda_code():
|
||||||
@ -170,6 +172,24 @@ def test_create_custom_lambda_resource__verify_manual_request():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_cloudformation
|
||||||
|
def test_create_custom_lambda_resource__unknown_arn():
|
||||||
|
# Try to create a Lambda with an unknown ARN
|
||||||
|
# Verify that this fails in a predictable manner
|
||||||
|
cf = boto3.client("cloudformation", region_name="eu-north-1")
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
cf.create_stack(
|
||||||
|
StackName=f"stack{str(uuid4())[0:6]}",
|
||||||
|
TemplateBody=json.dumps(get_template_for_unknown_lambda()),
|
||||||
|
Capabilities=["CAPABILITY_IAM"],
|
||||||
|
)
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("ValidationError")
|
||||||
|
err["Message"].should.equal(
|
||||||
|
"Template error: instance of Fn::GetAtt references undefined resource InfoFunction"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_log_group_name(cf, stack_name):
|
def get_log_group_name(cf, stack_name):
|
||||||
resources = cf.describe_stack_resources(StackName=stack_name)["StackResources"]
|
resources = cf.describe_stack_resources(StackName=stack_name)["StackResources"]
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
Loading…
Reference in New Issue
Block a user