Open fai555 opened 2 years ago
I've just spent a decent amount of time figuring out this bug, as there is no mention of this in the documentation that I could see. At a minimum, add a disclaimer for this in the docs.
This plauged me for a while too. :-) I worked around it, by passing things in as a base64 encrypted string
const coreNetworkCfg = new cdk.CustomResource(this, 'UpdateCoreNetworkConfiguration', { serviceToken: policyTable.serviceToken, properties: { policyTableName: policyTable.policyTable.tableName, coreNetworkConfiguration: cdk.Fn.base64(cdk.Stack.of(this).toJsonString(coreNetworkConfiguration)), coreName: props.coreName, }, });
Then in my python lambda, sucking them back out.
`coreNetworkConfiguration = json.loads(base64.b64decode(props['coreNetworkConfiguration']).decode("utf-8"))`
This plauged me for a while too. :-) I worked around it, by passing things in as a base64 encrypted string
const coreNetworkCfg = new cdk.CustomResource(this, 'UpdateCoreNetworkConfiguration', { serviceToken: policyTable.serviceToken, properties: { policyTableName: policyTable.policyTable.tableName, coreNetworkConfiguration: cdk.Fn.base64(cdk.Stack.of(this).toJsonString(coreNetworkConfiguration)), coreName: props.coreName, }, });
Then in my python lambda, sucking them back out. `coreNetworkConfiguration = json.loads(base64.b64decode(props['coreNetworkConfiguration']).decode("utf-8"))`
This is what I ended up doing as well, works fairly well, but feel a bit odd, and make it harder to see actual changes to the data.
Also came across this while troubleshooting the issue in CDK projects.
Converting the data object to string using JSON.stringify(data)
in the stack works. Then just use JSON.parse(dataStr)
in the custom resource function to decode.
+1. This can be very limiting for custom resources that implement some AWS/Boto APIs that have very strict typing validation. Any workaround do feel a little hacky.
Found this same issue with the Python CDK. For instance, when passing a dictionary into CustomResource(..., properties={"key": 1})
, the integer value will be converted to a string.
This also comes up when using boto3 macro
For example, since CloudFormation STILL doesn't support CustomizedMetricSpecification in AWS::AutoScaling::ScalingPolicy (https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/1495), you may want to use boto3 macro to create the policy - especially since it's a simple put_scaling_policy
call in boto. That will fail, however, because bools and ints get converted to strings by the custom resource call which fails validation.
Possible workaround, when using YAML with CloudFormation is:
Define the Properties as a json string:
TargetScalingPolicy:
Type: Boto3::autoscaling.put_scaling_policy
Mode: [ Create, Update ]
Properties: !Sub |
{
"AutoScalingGroupName": "${AutoScalingGroup}",
"PolicyName": "${AWS::StackName}",
"PolicyType": "TargetTrackingScaling",
"EstimatedInstanceWarmup": 240,
(...)
Modify the boto3 macro resource lambda around line 82, so that this whole if
looks like this:
if request == mode or request in mode:
if isinstance(properties["Properties"], str):
properties["Properties"] = json.loads(properties["Properties"])
status, message = execute(properties["Action"], properties["Properties"])
return sendResponse(event, context, status, message)
(we add the if isinstance(properties["Properties"], str): ...
part) to convert the properties back into an object.
Obvious disadvantage is that now you have a JSON string inside your YAML template, which reduced readability and since it's a string most editors/validators will ignore it, so you don't have any validation of what you put in there - easy to make a mistake.
Also came across this while troubleshooting the issue in CDK projects.
Converting the data object to string using
JSON.stringify(data)
in the stack works. Then just useJSON.parse(dataStr)
in the custom resource function to decode.
@markilott You meant the entire Data
from the CR or just one of the attr in Data
. For me it just errors when trying to parse a attribute from Data
during synth.
my_stringified_data = my_cr.get_att("stringified_json_object").to_string()
# Parsing the above data for using with another construct
json.loads(my_stringified_data)
My understanding is we can't manipulate the response, since it's not available during synth operation.
Name of the resource
AWS::CloudFormation::CustomResource
Resource Name
AWS::CloudFormation::CustomResource
Issue Description
Created a Custom Resource with boolean and int properties. When these properties are accessed in the Lambda function, they are all converted to string.
Expected Behavior
Although the AWS Cloud formation docs although mentions that the
ResourceProperties
is a JSON Object. And JSON object can contain Integers and Booleans. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-requests.htmlObserved Behavior
Conducted a short experiment to verify if the
ResourceProperties
inevent
of the custom resources are passed with the correct data type. Used the following Custom Resource configurationAfter applying it, the following logs appear
The properties are always returning String even though they have been passed as String, Boolean and Integer.
Test Cases
Pass any integer or boolean key value pair in the
Properties
section and you can see that the properties received in theevent['ResourceProperties']
object are all in string format.Other Details
Conducted a short experiment to verify if the
properties
of the custom resources are passed with the correct data type if the Custom Resource is applied from local machine, instead of using AILM. Used the following Custom Resource configuration in a test account to verify that.After applying it from a local setup to the
testaccount-ferdous
, the following logs appearThe properties are always returning String even though they have been passed as String, Boolean and Integer.
Although the AWS Cloud formation docs although mentions that the
ResourceProperties
is a JSON Object. And JSON object can contain Integers and Booleans. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-requests.htmlThe next course of action is to look into the issues of CloudFormation to see if it's already reported. If not, then create an issue and follow up on that. And for the time being, keep using the manual type mapping that we have been doing in the CustomResource Lambda Functions.