AWS CDK 部署到阶段而不删除之前的阶段

时间:2021-02-26 05:59:40

标签: amazon-web-services amazon-cloudformation aws-api-gateway aws-cdk

我使用 AWS CDK 来管理我的 API 网关的部署。我使用阶段在环境中推广我的代码,例如开发、测试、预生产、生产。我的脚本看起来像这样:

export class MyStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const api = new apigateway.SpecRestApi(this, 'my-api', {
      deploy: false,
      apiDefinition: apigateway.ApiDefinition.fromAsset('path/to/swagger.yaml'),
    });

    const stageName = this.node.tryGetContext('stageName');

    const deployment = new apigateway.Deployment(this, `my-api-deployment-${stageName}`, { api });
    new apigateway.Stage(this, `my-api-stage-${stageName}`, {
        stageName,
        deployment,
    });
  }
}

不幸的是,当我将代码从一个阶段提升到下一个阶段时,例如cdk deploy --context stageName=PREPROD,之前的阶段被删除,所以我的 API 网关中只剩下一个阶段。

是否可以在不删除其他阶段的情况下部署到一个阶段?

2 个答案:

答案 0 :(得分:2)

当您部署相同的堆栈时,部署和阶段的 id 因不同的 stageName 参数而变化。 Cloudformation 将删除之前的资源并创建一个新资源。

您需要将代码分成 2 个堆栈以使其正常工作。 堆栈 1 将有代码来创建 api 并将其导出为

export class MyStack1 extends cdk.Stack {
  public readonly api: apigateway.SpecRestApi;
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    this.api = new apigateway.SpecRestApi(this, 'my-api', {
      deploy: false,
      apiDefinition: apigateway.ApiDefinition.fromAsset('path/to/swagger.yaml'),
    });

MyStack2 将有代码来创建阶段和部署。

在您的 bin/App 文件中,您需要将 api 从 MyStack1 传递到 MyStack2 构造函数。

export class MyStack2 extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, api: apigateway.SpecRestApi, props?: cdk.StackProps) {
    super(scope, id, props);

   const stageName = this.node.tryGetContext('stageName');

    const deployment = new apigateway.Deployment(this, `my-api-deployment`, { api });
    new apigateway.Stage(this, `my-api-stage`, {
        stageName,
        deployment,
    });

保持 MyStack2 idmy-api-deployment-stack-${stageName}

这样做的目的是,您将拥有一个带有 api 网关的通用堆栈,以及每个 env 的不同堆栈,例如 dev、test、preprod 和 prod。

答案 1 :(得分:0)

这是我注意到的:

  • 如果您更改 Cloudformation 中资源的逻辑名称的第二个参数,它将始终删除并重新创建。
  • 如果我们需要两个阶段,我们必须有两个不同的物理资源,我们不能只有一个并且不断更改名称,它会删除并重新创建它。
  • 部署到阶段不受阶段控制,而是实际部署。因此,保持 stage 资源名称静态但只有 Deployment 是动态的,真正动态而不是 stageName。

所以,简而言之,我们需要两个阶段,两个部署,并根据动态逻辑名称控制部署哪一个。 代码看起来像这样:

完整代码如下:

const myRestApi = new apigateway.RestApi(this, "rest-api", {
  deploy: false,
});
const methods = myRestApi.root.addMethod(
  "ANY",
  new apigw.MockIntegration()
);

const StageOneDeploy = this.node.tryGetContext("StageOneDeploy");
const stageOneDeployment = new apigateway.Deployment(
  this,
  `api-deployment-${StageOneDeploy}`,
  {
    api: myRestApi,
  }
);

stageOneDeployment._addMethodDependency(methods);

new apigateway.Stage(this, `stageOne`, {
  stageName: "stageOne",
  deployment: stageOneDeployment,
});

const StageTwoDeploy = this.node.tryGetContext("StageTwoDeploy");
const stageTwoDeployment = new apigateway.Deployment(
  this,
  `api-deployment-${StageTwoDeploy}`,
  {
    api: myRestApi,
  }
);
stageTwoDeployment._addMethodDependency(methods);
new apigateway.Stage(this, `stageTwo`, {
  stageName: "stageTwo",
  deployment: stageTwoDeployment,
});

对于 Deploy ,我们可以更改为随机数到要部署到的任何阶段。

cdk deploy HelloCdkStack --context StageOneDeploy=123456 --context StageTwoDeploy=9493812