AwsCustomResource: Return response field from lambda backed custom resource #19833
-
Describe the bugI'am trying to create a lambda backed custom resource and get a field from its response but I get an error that the Vendor response doesn't contain such key I thought that the keys in the response of the lambda function must match the string parameter of custom_resource::.get_response_field which in that case would be "info.current". What am I doing wrong? You can find the a simple version of the code below Expected BehaviorGet "info.current" as an output after deployment finishes Current Behavior
Reproduction Stepsfrom aws_cdk.aws_logs import RetentionDays
from constructs import Construct
from aws_cdk import (Stack,
aws_iam as iam,
aws_lambda as l,
CfnOutput,
Duration,
custom_resources as cr
)
class DemoConstruct(Construct):
def __init__(self, construct: Construct, construct_id: str):
super().__init__(construct, construct_id)
with open(f"./resources/lambdas/pathsLambda.py") as lambda_path:
code = lambda_path.read()
demo_lambda_function = l.Function(
scope=self,
id=f"DemoLambda-{construct_id}",
code=l.Code.from_inline(code),
environment={
"SOME_ARG": "argVal"
},
handler="index.lambda_handler",
runtime=l.Runtime.PYTHON_3_7,
timeout=Duration.seconds(60),
memory_size=2048
)
c_resource = cr.AwsCustomResource(
self,
f"CustomResource-{construct_id}",
log_retention=RetentionDays.ONE_WEEK,
on_update=cr.AwsSdkCall(
service="Lambda",
action="invoke",
physical_resource_id=cr.PhysicalResourceId.of("Trigger"),
parameters={
"FunctionName": demo_lambda_function.function_name,
"InvocationType": "RequestResponse",
"Payload": "{\"Request\":{\"Method\": \"method1\"}}"
},
# output_paths=["info.current"]
),
policy=cr.AwsCustomResourcePolicy.from_statements([
iam.PolicyStatement(
actions=["lambda:InvokeFunction"],
resources=[demo_lambda_function.function_arn]
)
])
)
CfnOutput(self, id="InfoCurrent", value=c_resource.get_response_field("info.current"), export_name="InfoCurrent")
class Demo(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
DemoConstruct(self, "Demo")
And the lambda code: def lambda_handler(event, context):
print(event)
print(context)
myStr = "q"
#for i in range(4096):
# myStr += 'q'
my_dict = {
"info": {
"current": {
"version": 3
},
"applied": {
"count": 23
}
},
"other": myStr
}
print(my_dict)
return my_dict Possible SolutionNo response Additional Information/ContextNo response CDK CLI Version2.10 Framework VersionNo response Node.js Versionv16.3.0 OSMac LanguagePython Language Version3.7 Other informationNo response |
Beta Was this translation helpful? Give feedback.
Replies: 9 comments 12 replies
-
Hey @manosntoulias, I have converted this to a discussion since there probably isn't a bug here (since I have been able to successfully create custom resources with responses), but rather a complication/error in the process. If this does turn out to be a bug, I will convert back to an issue. In the interim, I have verified this behavior and am investigating the probably cause and will update with an answer ASAP (best guess atm is that it has to do with a different structure for custom resource responses vs basic lambda responses)! |
Beta Was this translation helpful? Give feedback.
-
I'm copying my answer from the last thread since this seems to be a duplicate The output_paths parameter and getResponseField method both work with the Api response. So for your case, you're using Lambda Invoke. I'm not too sure what info.current is, but it's not in any of the response elements seen here 🙂 Hope this helps guide you in the right direction! |
Beta Was this translation helpful? Give feedback.
-
Hello again @peterwoodworth, I looked carefully at your answer and you are right when specifying "Payload" I get the response in the output: However it seems that the value of 'Payload' is stringified and cannot access paths like "Payload.info" as I get the same error. Tried changing my lambda response to this without success:
Im also trying to use CustomResource instead of AwsCustomResource, but since it does not use lambda invoke even just specifying "Payload" fails. Maybe the response structure for this as well will help. Thanks again. |
Beta Was this translation helpful? Give feedback.
-
I have more success with CustomResource. Changed the lambda response to this: ` {
and now I am able to do c_resource.get_att_string("other"). However still fail to get "info" as its value is not a string. I have a hard time using c_resource.get_att instead. I cannot find a way to turn this to a string and have it in the output |
Beta Was this translation helpful? Give feedback.
-
I'm also trying to do something like this and faced with a similar error let me know if you have found a solution. |
Beta Was this translation helpful? Give feedback.
-
@muhammadali2022skipq and everyone else who might be interested, I have:
Note: All these were done because with the accessor methods (e.g. get_att_string) I can only access the first level of the response in integer or string format. Nested json objects are returned as string and I can not access their fields. If someone knows how to access nested fields, feel free to comment |
Beta Was this translation helpful? Give feedback.
-
Another option is to use self._create_thumbprint_custom_resource = CustomResource(
self,
f"{id}CustomResource",
service_token=self._thumbprint_lambda_function_arn,
properties=payload,
)
# Get the thumbprint from the response
self._thumbprint = self._create_thumbprint_custom_resource.get_att(
attribute_name="thumbprint"
).to_string() |
Beta Was this translation helpful? Give feedback.
-
Hello! Reopening this discussion to make it searchable. |
Beta Was this translation helpful? Give feedback.
-
Hello, I'm trying to provide custom data as input to the event so that the Lambda can function differently based on that input. metricsRule.addTarget(new LambdaTarget(sendNotificationsLambda), { In tried to use input and event, but the custom data generated by the event was not passed to the lambda function. For example When the lambda runs, it’s not receiving the instances to show the message: "The following instances were launched: [i-123, i-456]" Is there a way to substantiate the custom resource to pass to the Lambda Function? When we use an Event Bridge Rule and capture the event to go to the Lambda, we can have the Lambda process the event and manipulate it however we want. |
Beta Was this translation helpful? Give feedback.
@muhammadali2022skipq and everyone else who might be interested,
I have:
Note: All these were done because with …