CDK 管道:在阶段的“post”步骤中使用 Stack 输出

CDK Pipelines: Use Stack output in `post`step of stage

我有一个带阶段的管道堆栈。此阶段包含多个堆栈。其中一个堆栈创建了一个 Step Function。现在我想在舞台的 post 中触发该步骤功能(我为此创建了 InvokeStepFunctionStep 作为自定义 ICodePipelineActionFactory 实现)。

这是来自我的管道堆栈代码:

// TODO make this dynamic
const stepFunctionArn = "arn:aws:states:<FULL_ARN_OMITTED>";
pipeline.addStage(stage, {
          post: [ new InvokeStepFunctionStep('step-function-invoke', {
            stateMachine: sfn.StateMachine.fromStateMachineArn(this, 'StepFunctionfromArn',stepFunctionArn),
            stateMachineInput: StateMachineInput.literal(stepFunctionsInput)
          })]
        });

显然,硬编码 ARN 很糟糕。我尝试从阶段的堆栈中获取步骤函数的 ARN 作为变量。然而,这失败了

dependency cannot cross stage boundaries

我也尝试过为 ARN 使用 CfnOutput,但是当我尝试通过 Fn.ImportValue 使用它时,UpdatePipelineStep 在 CloudFormation 中失败

No export named EdgePackagingStateMachineArn found

动态传递此信息的推荐方法是什么?

选项 1:简单,不是最优的。

为您的 Step Function 指定一个名称,并将其传递给创建它的堆栈和您的调用步骤。从名称构建 ARN。

此选项不是很好,因为为 CloudFormation 资源指定物理名称有其缺点 - 主要是无法引入任何需要资源替换的后续更改,这对于步进函数可能是必需的。

选项 2:更复杂,但从长远来看可能更好。

从创建步骤函数的堆栈中使用步骤函数的 ARN 创建 SSM 参数,然后在调用步骤中读取 SSM 参数。

这还需要为资源指定物理名称 - SSM 参数,但您不太可能需要为其替换资源,因此问题不大。

您可以尝试使用 CfnOutput.importValue property 来引用 CfnOutput 值,这对我有用。见下文:

服务堆栈:

export class XxxStack extends Stack {
  public readonly s3BucketName: CfnOutput;
  constructor(scope: Construct, id: string, props?: StackProps) {
    ...
    this.s3BucketName = new CfnOutput(
      this,
      's3BucketName',
      {
        exportName: `${this.stackName}-s3BucketName`,
        value: s3Bucket.bucketName,
      }
    );
  }
}

阶段class:

import { CfnOutput, Construct, Stage, StageProps } from '@aws-cdk/core';

export class CdkPipelineStage extends Stage {
  public readonly s3BucketName: CfnOutput;

  constructor(scope: Construct, id: string, props?: StageProps) {
    super(scope, id, props);
    const service = new XxxStack(
      this,
      'xxx',
      {
        ...
      }
    );

    this.s3BucketName = service.s3BucketName;
  }
}

管道堆栈:

    import { CdkPipeline, SimpleSynthAction } from '@aws-cdk/pipelines';
    
    const pipeline = new CdkPipeline(this, 'Pipeline', {...})

    const preprod = new CdkPipelineStage(this, 'Staging', {
      env: { account: PREPROD_ACCOUNT, region: PIPELINE_REGION },
    });

    // put validations for the stages
    const preprodStage = pipeline.addApplicationStage(preprod);

    preprodStage.addActions(
      new ShellScriptAction({
        actionName: 'TestService',
        additionalArtifacts: [sourceArtifact],
        rolePolicyStatements: [
          new PolicyStatement({
            effect: Effect.ALLOW,
            actions: ['s3:getObject'],
            resources: [
              `arn:aws:s3:::${preprod.s3BucketName.importValue}/*`,
              `arn:aws:s3:::${preprod.s3BucketName.importValue}`,
            ],
          }),
        ],
        useOutputs: {
          ENV_S3_BUCKET_NAME: pipeline.stackOutput(
            preprod.s3BucketName
          ),
        },
        ...
      }),
    );

注意:我的CDK版本是

$ cdk --version
1.121.0 (build 026cb8f)

而且我可以确认 CfnOutput.importValue 也适用于 CDK 版本 1.139.0 和 CDK 版本 2.8.0