Background
Amplify apps are easily extensible with Lambda functions, using amplify add function
. Great!
Problem
How can I access the Amplify app ID from the Lambda function code? There are a lot of scenarios where I need that string in order to locate resources or access secrets in SSM.
More generally
How can my function do introspection on the app? How can I get the app ID from the Lambda function? Is there a service? Am I supposed to pass the information (somehow) through the CloudFormation template for the function?
Due diligence
I've spent days trying to figure this out, and I have at least learned the secret, undocumented way to get anything in a nested CloudFormation stack's outputs into the parameters for my CloudFormation stack, so that I can create environment variables that my Lambda function can see.
That does not solve my original problem of finding the top-level app ID. Or any information about the top-level app. If I could find the stack name for the top-level CloudFormation for the stack then I could learn a lot of things. I can't.
How to pass stack outputs from app resources into function stack parameters
I've spent days trying to figure this out, and I have at least learned the secret, undocumented way to use dependsOn
in the backend-config.json to get the outputs from the CloudFormation stacks for other resources in the Amplify app and feed those into the parameters for my stack for my function:
"function": {
"MyFunctionName": {
"build": true,
"providerPlugin": "awscloudformation",
"service": "Lambda",
"dependsOn": [
{
"category": "api",
"resourceName": "Data",
"attributes": [
"GraphQLAPIIdOutput"
]
}
],
}
}
}
That creates a new parameter for your function that's named using a pattern that's not documented anywhere, from what I can tell: [category][resource name][CloudFormation stack output name]
. You can reference that in your CloudFormation stack for your function to create an environment variable that your function code can access:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
...
"secretsPathAmplifyAppId": {
"Type": "String"
}
...
"Resources": {
...
"Environment": {
"Variables": {
"AMPLIFY_APP_ID": {
"Ref": "secretsPathAmplifyAppId"
},
Using the AmplifyAppId
in amplify-meta.json
doesn't work
If I could access the provider
/ cloudformation
data from a dependsOn
then I could get the app ID into my function's stack. But that doesn't work. I spent some time eliminating that possibility.
Using secretsPathAmplifyAppId
There is a side effect of using amplify update function to add secrets. If you add any secret to the function then you will get a new parameter as an input to your function's CloudFormation stack: secretsPathAmplifyAppId
I did that and added a dummy secret that I don't really need, in order to get that CloudFormation stack parameter containing the Amplify App ID that I do need. And then I referenced that in my CloudFormation template for my function:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
...
"env": {
"Type": "String"
},
"s3Key": {
"Type": "String"
},
...
"secretsPathAmplifyAppId": {
"Type": "String"
}
That works, right? No!
If I create a new app in Amplify, perhaps deploying it to a staging or production account for the first time, then I'll get the error Parameters: [secretsPathAmplifyAppId] must have values
from the initial build when I press "Save and Deploy" on the "Host your web app" form. This is because using secretsPathAmplifyAppId
relies on the Amplify CLI adding the value to the team-provider-info.json
file. For a new app's first deployment, "the team-provider-info.json
file is not available in the Admin UI deployment job", as described in https://github.com/aws-amplify/amplify-cli/issues/8513 . And there is apparently no solution.
WHY IS THIS SO HARD?!?
The Amplify documentation implies that it's not difficult to add a Lambda function and do whatever. I'm a Lambda pro and a code pro, and I can do whatever. But only if I can pass context information to my code.
How can an Amplify app's Lambda functions do introspection on the app?