-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to call out to a custom Lambda function using AwsCustomResource and use the response to create resources? #7430
Comments
I think the docs on |
Hi @NetaNir. Thanks for responding. I have looked into |
Short answer: use the provider framework for this Longer answer: aws-cdk/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts Line 109 in 71bcd22
|
Thank @jogold. I will give it a shot. |
One issue with that approach is that I again need to know the name of the VPC before I can create the provider Lambda function, due to the fact the Lambda that hits the API needs to reside in the VPC. Is there a way to reference a Lambda function that already exists out of the stack? |
Ok, so I spoke too soon. Found this: #4810 (comment) - will give it a go. |
Unfortunately I'm still having the same issue using @jogold's suggestion of the provider framework. The problem being that the My code: const onEvent = Function.fromFunctionArn(scope, 'MyFunc', 'arn:aws:lambda:ap-southeast-2:123456789:function:my-func-name')
const cr = new CustomResource(scope, 'MyCustomResource', {
provider: CustomResourceProvider.fromLambda(onEvent),
properties: {
FunctionName: 'my-func-name',
Payload: `{"path": "vpcs/all"}`,
},
})
cr.getAtt('Payload') // returns token
cr.getAttString('Payload') // returns token Can someone please share a concrete example on how I can invoke a Lambda and return the concrete response? |
It's a token because it's a deploy-time value. You cannot use it at synth time but you can use the returned value in another construct. Also you can do What are you trying to achieve exactly? What kind of resources do you want to create? Also, if everything is known at synth time then maybe you don't need a custom resource. Looks like something for Stack Overflow. |
I am currently trying to achieve a very basic actions: create a security group using an existing VPC. When trying to fetch an existing VPC using a token with the
Which I assume means this function is executed at synth time(?). This is why I am trying to resolve the concrete data object from the Lambda. Is there anyway I can call out to a HTTP API at synth time only? For example: if (isSynth) {
const resp = callCustomApi('/my/path')
const vpc = Vpc.fromLookup(this, 'MyVpc', {
vpcId: resp.vpc_dev,
})
} |
You cannot use aws-cdk/packages/@aws-cdk/aws-ec2/lib/vpc.ts Line 946 in e818658
This is because it calls the EC2 API at synth time to lookup all the attributes of the VPC to import. You could use the |
The problem with that solution is that I don't know what values I need from the API prior to executing CDK. I could wrap the CDK executable with our own executable and have our executable run CDK as a child process. This I have tried but its not ideal. What we are building is a Typescript library that wraps around CDK to apply our company-specific We currently achieve this scale of deployment through custom in-house built tool. However, it has become dated over the years and is difficult add functionality to or maintain. We are hoping that CDK can replace this tool and provide base framework for which to continue building from. |
Here is the current solution I'm leaning towards. We would have a standalone call-api.js #!/usr/bin/env node
const http = require('http')
http.get('https://my.api.com/vpcs/all', (resp) => {
let data = ''
// Concatenate all chunks
resp.on('data', (chunk) => {
data += chunk
})
// Send response
resp.on('end', () => {
// Returns the following JSON object.
// {
// "vpc_dev": "vpc-1234abcd",
// "vpc_test": "vpc-2345bcde",
// "vpc_prod": "vpc-3456cdef"
// }
console.log(data)
})
}) my-stack.ts import { execSync } from 'child_process'
import { App, Stack } from '@aws-cdk/core'
import { Vpc, SecurityGroup } from '@aws-cdk/aws-ec2'
class MyStack extends Stack {
constructor(scope: App) {
super(scope, 'MyStack')
const resp = execSync('node ./call-api.js').toString()
const vpcId = JSON.parse(resp).vpc_dev
const vpc = Vpc.fromLookup(this, 'MyVpc', { vpcId })
new SecurityGroup(this, 'MySg', { vpc })
}
}
const app = new App()
new MyStack(app)
app.synth() Thoughts, comments or concerns? |
I am closing this since this is mostly guidance discussion. Ideally should be in Stack Overflow. |
@eladb Hi, I see this was dated from 2020. Is this method still usable? |
❓ General Issue
The Question
What I want to do is call out to a custom API endpoint (which is exposed by a Lambda function), return the ID of an existing VPC and use it to create a security group. (This is a contrived example. I have other use cases for retrieving values from our custom API.)
I have the following basic
my-func-name
lambda for calling out to the API:The below stack uses
AwsCustomResource
to invoke the above lambda and attempts to use the the response data to create a security group. But becauseAwsCustomResource.getResponseField
returns aToken
value, I'm unable to parse the JSON response into aObject
, and instead receive an error due to it trying to parse theToken
represented string.Error:
Unexpected token $ in JSON at position 0 Subprocess exited with error 1 Error: Subprocess exited with error 1 at ChildProcess.<anonymous>(/app/node_modules / aws - cdk / lib / api / cxapp / exec.ts: 118: 23) at ChildProcess.emit(events.js: 310: 20) at ChildProcess.EventEmitter.emit(domain.js: 482: 12) at Process.ChildProcess._handle.onexit(internal / child_process.js: 275: 12)
So I understand the issue here. Just want to understand how to get around it. How can I use the concrete response data from an invoked Lambda for creating arbitrary resources?
Environment
Other information
The text was updated successfully, but these errors were encountered: