So, I’m considering migrating our serverless.ts de...
# help
r
So, I’m considering migrating our serverless.ts defined projects to use SST. I don’t yet have any experience of using AWS CDK or SST so have a question before I dive in. In our serverless.ts definition we define lots of resources to do with the VPC - e.g. subnets, NAT Gateways, NACLs, security groups, and also Aurora RDS definition. As far as I can tell, these would need to be defined using CDK rather than SST. Is there a recommended way to achieve this using SST and CDK together, I couldn’t see anything in the docs so thought I’d ask the experts here?
f
Hey @Ross Coundon Awesome to hear that!
VPC ... would need to be defined using CDK rather than SST.
Yes, that’s correct. Each SST construct is just a thin wrapper grouping several CDK constructs together. For example, when you create an
sst.Api
construct, behind the scene, you are really creating an
apigatewayv2.HttpApi
. And for each route that’s added, you are creating a
apigatewayv2.HttpRoute
and a
lambda.Function
. And if custom domain is configured for the
sst.Api
construct, an
acm.Certificate
, a
apigatewayv2.DomainName
and a couple of
route53.Record
s are created. For VPC, SST doesn’t have a wrapper around it, you can just define it using CDK constructs. Btw, are you thinking of rewriting
serverless.ts
to SST in one go? You also have the option to leave the VPC stuff in
serverless.ts
, and imports the VPC in to SST. So if you want to create ie. a new Api endpoint in SST and have the Lambda functions launched into the VPC created in
serverless.ts
, the code looks something like:
Copy code
import * as ec2 from "@aws-cdk/aws-ec2";
import * as sst from "@serverless-stack/resources";

// Import VPC
const existingVpc = ec2.Vpc.fromLookup(this, 'VPC', {
  vpcName: `MyExistingVPC`,
});

// Create an API
new sst.Api(this, "Api", {
  defaultFunctionProps: {
    vpc: existingVpc,
  },
  routes: {
    "GET    /notes": "src/list.main",
    "POST   /notes": "src/create.main",
    "GET    /notes/{id}": "src/get.main",
    "PUT    /notes/{id}": "src/update.main",
    "DELETE /notes/{id}": "src/delete.main",
  },
});
Another thing I wanted to mention is that for local functions to be able to connect to your RDS while live developing, either the RDS has to be publicly exposed, or connected through a VPN. Some ppl are fine with the former for their dev servers. But here’s some info on setting up a VPN using AWS Client VPC service https://docs.serverless-stack.com/live-lambda-development#connecting-to-a-vpc lol.. there is a lot of stuff to digest here. Let me know if you prefer to chat over zoom.
r
Thanks Frank - how do you set up SST and CDK to work together in the way you describe, are they simply defined as separate stacks with imports for values that are required to be referenced? Or can I import CDK constructs in an SST app and define both in one place? If it’s either, what’s the recommended approach? Yeah - this is something we already have in place with the RDS and lambdas within a VPC. Just wondering how to make the same thing work in SST/CDK land
f
Yeah I think there might be some confusion, SST has two parts to it, the CLI and the Constructs.
SST constructs are just CDK constructs.. lemme give an example.
r
Yeah, I think what I’m asking is - how/should I define an SST construct (e.g. a lambda) and a CDK construct (e.g. a NAT Gateway) in the same set of TypeScript files. Or, should I have a separate CDK and SST projects?
f
Yeah, in the same TypeScript file.
Copy code
import * as ec2 from "@aws-cdk/aws-ec2";
import * as sst from "@serverless-stack/resources";

// Create VPC using CDK construct
const vpc = new ec2.Vpc(this, 'VPC', { ... });

// Create an Function using SST construct
new sst.Function(this, "Function", { vpc });
Something like this
r
Right, cool. So would I need a cdk.json and an sst.json if using both in same file? On the other subject, I now see the challenge re: local lambda and VPC (opened your link)
f
r
Ok, cool. I did see that but wondered about the situation where i wasn’t migrating from CDK, rather I’d be incorporating both
I guess it’d be a handy (and short) section in the docs to help describe how to have both where SST doesn’t have the construct the reader needs (yet)
f
Yeah good point! Now you mentioned it.. I think migrate is a misleading term.
r
Great, good stuff
Sorry to go back to this, just about to make a start on defining our stack which will need SST and CDK constructs. I need to use a REST API rather than an HTTP API because of the need for usage plans and API keys. This, I think, means I need to use a @aws-cdk/aws-apigateway construct. From our conversation a few days ago, I thought I could do this within an sst.Stack as per above
However, does this mean I then lose the ability to do the smart live debugging stuff? When I run
sst start
I get the message
Copy code
===================
 Starting debugger
===================

Transpiling Lambda code...
Nothing has been transpiled
Debug session started. Listening for requests...
And I just get a internal server error and nothing is routed to my machine
Found the cloudwatch logs and it’s complaining
Copy code
Cannot find module 'lambda'
Which I guess is related to SST saying
Copy code
Nothing has been transpiled
Which I assume is because this lambda is defined by CDK rather than SST, or am I on the wrong track?
f
Hey @Ross Coundon change
Copy code
const handler = new lambda.Function(this, "MyFirstSst", {
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromAsset('src'),
      handler: "lambda.handler",
    });
to
Copy code
const handler = new sst.Function(this, "MyFirstSst", {
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: "src/lambda.handler",
    });
Everywhere you are using
lambda.Function
, just swap it with
sst.Function
r
Ah, so I can plumb an sst.Function into a cdk apigateway.RestApi ?
f
yup yup,
sst.Function
extends
lambda.Funtion
.. so it’s pretty much a drop in and replace.
r
possibly the missing link…
thanks Frank, more tinkering
f
yup ypu.. the handler definition is a bit different for
sst.Function
, you don’t need to set
code
, just
handler
is normally fine.
r
and it works 😄
f
nice.. yeah, the `cannot find module `lambda`` error in CloudWatch is b/c you are using lambda in
lambda.Function
.. which you don’t need now
r
excellent, much simpler
f
just curious.. are you sharing the same APIG project across multiple sls services?
r
no, everything will be inside one project
f
got it.. that’s good