如何使用 SAM 创建 AWS 资源以在本地运行 CDK 应用程序?

pup*_*eno 5 amazon-web-services aws-sam aws-cdk

我有一个名为 Example4Be 的应用程序,我有一个创建 AWS 非 Lambda 资源的堆栈(在本例中只是 DynamoDB,但也可以是 SQS、SNS 等):

import * as cdk from "aws-cdk-lib"
import {Construct} from "constructs"
import * as dynamodb from "aws-cdk-lib/aws-dynamodb"

export class Example4BeResourcesStack extends cdk.Stack {
    public readonly table: dynamodb.Table

    constructor(scope: Construct, id: string, props?: cdk.StageProps) {
        super(scope, id, props)

        this.table = new dynamodb.Table(this, "Hits", {
            partitionKey: {
                name: "path",
                type: dynamodb.AttributeType.STRING
            }
        })
    }
}

Run Code Online (Sandbox Code Playgroud)

然后有一个使用它的堆栈:

import * as cdk from "aws-cdk-lib"
import * as lambda from "aws-cdk-lib/aws-lambda"
import * as apigw from "aws-cdk-lib/aws-apigateway"
import {Construct} from "constructs"
import {Example4BeResourcesStack} from "./example4-be-resources-stack";

export class Example4BeStack extends cdk.Stack {
    public readonly hcEndpoint: cdk.CfnOutput

    constructor(scope: Construct, id: string, props?: cdk.StageProps) {
        super(scope, id, props)

        const resources = new Example4BeResourcesStack(scope, `${id}Resources`)

        const hello = new lambda.Function(this, "HelloHandler", {
            runtime: lambda.Runtime.NODEJS_14_X,
            code: lambda.Code.fromAsset("lambda"),
            handler: "hello.handler",
            environment: {
                HITS_TABLE_NAME: resources.table.tableName
            }
        })

        resources.table.grantReadWriteData(hello)

        // defines an API Gateway REST API resource backed by our "hello" function.
        const gateway = new apigw.LambdaRestApi(this, "Endpoint", {
            handler: hello
        })

        this.hcEndpoint = new cdk.CfnOutput(this, "GatewayUrl", {
            value: gateway.url
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个文件,app.ts实例化堆栈:

#!/usr/bin/env node
import * as cdk from "aws-cdk-lib"
import {Example4BeStack} from "../lib/example4-be-stack";

const app = new cdk.App()
new Example4BeStack(app, "Example4BePipeline")
Run Code Online (Sandbox Code Playgroud)

我运行它的方式是运行:

cdk synth --no-staging > template.yaml
sam local start-api
Run Code Online (Sandbox Code Playgroud)

但这似乎并没有创建 DynamoDB 表。我想cdk deploy我失踪了?这应该怎么做呢?

如果您愿意,我很乐意添加更多应用程序,实际部署中涉及 CodePipeline。

fed*_*nev 5

SAM-CDK 集成在本地运行模拟 lambda,根据需要调用云部署的资源。

(1) 使用以下方式部署堆栈cdk deploy

我们的本地 lambda 将与已部署资源1依赖项(表、队列等)交互。使用单独的帐户进行测试是 AWS 最佳实践。2

(2) 告诉 SAM lambda 的云端环境变量

// locals.json is used by SAM to resolve lambda env vars
{
  // the lambda resource id from sam-template.yaml 
  "HandlerFunctionEDBA20C2": { 
    // our lambda has an environment variable named TABLE_NAME
    // this is deployed-resource in cloud - tip: define a CfnOutput in your stack.  cdk deploy will emit the values to the terminal
    "TABLE_NAME": "CdkTsPlayLocalTestingStack-SuperTable2CB94566-1VPR5PAXO0GM5" 
  },
  "AnotherLambdaCD21C99": {
    "QUEUE_ARN": "<queue-arn>"
  }
}
Run Code Online (Sandbox Code Playgroud)

或者您可以将一组变量应用于所有函数:

{
  "Parameters": {
    "TABLE_NAME": "CdkTsPlayLocalTestingStack-SuperTable2CB94566-1VPR5PAXO0GM5" 
  }
}
Run Code Online (Sandbox Code Playgroud)

(3) 现在可以进行本地迭代了

在本地对 lambda 进行更改,然后让 SAM cli 执行其操作3

# synth the app template, output a sam format template
npx cdk synth '*' -a 'ts-node ./bin/app.ts' --profile <testing-profile> --no-staging > cdk.out/sam-template.yaml

# call a local function
sam local invoke HandlerFunctionEDBA20C2 \
--template cdk.out/sam-template.yaml \
--profile <testing-profile> \
--event lib/stacks/testing/LocalTestingStack/test-events/create.json \
--env-vars lib/stacks/testing/LocalTestingStack/locals.json
Run Code Online (Sandbox Code Playgroud)

(4) 或者与自动化测试集成

start-lambda启动模拟器,针对本地端点运行自动化测试。 文档在这里

哪里发生了什么?

SAM目前有3个本地测试命令:

萨姆命令 拉姆达 APIGW 其他(发电机等) 做什么的
sam 本地调用 当地的 测试本地 lambda
sam 本地启动-lambda 当地的 监视模式 - 使用 SDK 或 CLI 调用 lambda
sam 本地启动-api 当地的 当地的 监视模式 - 通过本地端点测试本地 lambda

请注意,lambda 是所有这些优点的核心。我们可以将事件输入模拟到本地 lambda 中。我们可以模拟 api/sdk 端点。我们可以与 lambda SDK 调用引用的已部署资源进行交互。但目前尚未涵盖其他设置。例如,我们无法测试 lambda DynamoDB 流处理程序。我们希望本地功能能够随着时间的推移而增长。


(1) 我使用术语“local-lambda”来表示 lambda 的本地版本,它将sam local在容器中运行。“部署资源”指的是我们的 lambda 的云部署集成(例如 DynamoDB 表、队列等)。

(2) 此时,测试不会触及您的管道堆栈。完成本地测试后,将更改推送到 github,这将启动管道部署到(staging和)prod帐户。您可以将其他测试步骤作为管道阶段的一部分运行

(3) 预览版sam-beta-cdkCLI比普通 CLI更容易将 CDK 与 SAM 集成sam。例如,它似乎.yaml为我们创造了同样的东西。但这两个工具似乎具有相同的基础功能。