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
我有一个带阶段的管道堆栈。此阶段包含多个堆栈。其中一个堆栈创建了一个 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