Yang Liu
Yang Liu

Reputation: 731

How to deploy application stack for a cross accounts pipeline

I'm setting up a CI pipeline for AWS Rds only. The pipeline is going to deploy RDS stack across Alpha/Gamma/Prod AWS account in order.

I have an application stack defined as:

export class ApplicationStack extends CDK.Stack {
    constructor(scope: Construct, id: string, props: ApplicationStackProps) {
        super(scope, id, props);
        const coreVpc: Ec2.IVpc = Ec2.Vpc.fromLookup(this, "CoreVpc", {
            vpcName: "CoreVpc",
        });
        const rdsStack = new RdsStack(scope, `eCommerceDatabaseRdsStack-${props.stageName}`, {
            vpc: coreVpc,
            description: `The stack defines eCommerceDatabase at ${props.stageName}.`,
        });
    }
}

Now I'm trying to deploy above application stack to a pipeline that's across multiple AWS accounts.

Here is how I tried to create the pipeline:

/**
 * This is where we define the whole pipeline.
 */
export class PipelineStack extends Cdk.Stack {
  constructor(scope: Cdk.App, id: string, props: PipelineStackProps) {
    super(scope, id, props);

    // Initialize the pipeline
    const pipeline = new codepipeline.Pipeline(this, "Pipeline", {
      pipelineName: "eCommerceDatabasePipeline",
      restartExecutionOnUpdate: true,
    });

    // Add stages to this pipeline.
    pipelineStageInfoList.forEach((pipelineStage: PipelineStageInfo) => {
      const applicationStack = new ApplicationStack(
        this,
        `eCommerceDatabaseStack-${pipelineStage.stageName}`,
        {
          stageName: pipelineStage.stageName,
        }
      );
      const stage: Cdk.aws_codepipeline.IStage = pipeline.addStage({
        stageName: pipelineStage.stageName,
      });


      // This is where I'm having trouble. 
      //It complains that applicationStack.templateFile is just a string, 
      //not assignable to ArtifactPath type. 
      stage.addAction(
        new codepipeline_actions.CloudFormationCreateUpdateStackAction({
          actionName: `eCommerceDatabase-${pipelineStage.stageName}-Deploy`,
          templatePath: applicationStack.templateFile,
          stackName: `eCommerceDatabase-${pipelineStage.stageName}`,
          region: pipelineStage.awsRegion,
          adminPermissions: true,
        })
      );
    });
  }
}

As commented above, I don't know how to pass the application cloudformation stack to the pipeline stage. I don't know whether I'm using the right approach either.

Upvotes: 0

Views: 153

Answers (1)

Yang Liu
Yang Liu

Reputation: 731

I got this work. So share my pipeline stack here. I referred https://cdkworkshop.com/20-typescript/70-advanced-topics/200-pipelines/1000-setting-up.html to setup the CDK package. My RDS clusters are in the private subnets of VPC(which is controlled by a different CDK package https://github.com/yangliunewyork/AwsStandardVpcTemplate).

import * as Cdk from "aws-cdk-lib";

import * as pipelines from "aws-cdk-lib/pipelines";
import {
  PipelineStageInfo,
  pipelineStageInfoList,
} from "../config/pipeline-config";
import { PipelineStage } from "./pipeline-stage";

export interface PipelineStackProps extends Cdk.StackProps {
  readonly pipelineName: string;
  readonly description: string;
}

export class PipelineStack extends Cdk.Stack {
  constructor(scope: Cdk.App, id: string, props: PipelineStackProps) {
    super(scope, id, props);

    // Initialize the pipeline
    const pipeline = new pipelines.CodePipeline(this, "Pipeline", {
      pipelineName: "rdsDatabasePipeline",

      // Create KMS keys for the artifact buckets, 
      // allowing cross-account deployments
      crossAccountKeys: true,

      // allow the pipeline to reconfigure itself when assets or stages 
      // are being added to it
      selfMutation: true,

      // synth is expected to produce the CDK Cloud Assembly as its output
      synth: new pipelines.ShellStep("Synth", {
        input: pipelines.CodePipelineSource.gitHub(
          "yang/RdsDatabaseCdk",
          "main",
          {
            authentication: Cdk.SecretValue.secretsManager('github-token')
          }
        ),
        // Install dependencies, build and run cdk synth
        commands: [
          'npm ci',
          'npm run build',
          'npx cdk synth'
        ],
      }),
    });

    // Add stages to this pipeline.
    pipelineStageInfoList.forEach((pipelineStage: PipelineStageInfo) => {
      pipeline.addStage(
        new PipelineStage(this, pipelineStage.stageName, {
          stageName: pipelineStage.stageName,
          pipelineName: props.pipelineName,
          env: {
            account: pipelineStage.awsAccount,
            region: pipelineStage.awsRegion,
          },
        })
      );

    });
  }
}

Upvotes: 1

Related Questions