简体   繁体   English

AWS CDK:按 CDK 顺序运行外部构建命令?

[英]AWS CDK: run external build command in CDK sequence?

Is it possible to run an external build command as part of a CDK stack sequence?是否可以将外部构建命令作为 CDK 堆栈序列的一部分运行? Intention: 1) create a rest API, 2) write rest URL to config file, 3) build and deploy a React app:意图:1) 创建一个 rest API,2) 将 rest URL 写入配置文件,3) 构建和部署 React 应用程序:

import apigateway = require('@aws-cdk/aws-apigateway');
import cdk = require('@aws-cdk/core');
import fs = require('fs')
import s3deployment = require('@aws-cdk/aws-s3-deployment');

export class MyStack extends cdk.Stack {

  const restApi = new apigateway.RestApi(this, ..);
  fs.writeFile('src/app-config.json', 
    JSON.stringify({ "api": restApi.deploymentStage.urlForPath('/myResource') }))

  // TODO locally run 'npm run build', create 'build' folder incl rest api config

  const websiteBucket = new s3.Bucket(this, ..)
  new s3deployment.BucketDeployment(this, .. {
      sources: [s3deployment.Source.asset('build')],
      destinationBucket: websiteBucket
  }) 
}

Unfortunately, it is not possible, as the necessary references are only available after deploy and therefore after you try to write the file (the file will contain cdk tokens ).不幸的是,这是不可能的,因为必要的引用仅在部署之后可用,因此在您尝试写入文件之后(该文件将包含cdk 令牌)。

I personally have solved this problem by telling cdk to output the apigateway URLs to a file and then parse it after the deploy to upload it so a S3 bucket, to do it you need:我个人通过告诉 cdk 到 output apigateway URL 到一个文件,然后在部署对其进行解析以将其上传为 S3 存储桶,从而解决了这个问题,你需要这样做:

  • deploy with the output file options, for example: cdk deploy -O./cdk.out/deploy-output.json使用 output 文件选项进行部署,例如: cdk deploy -O./cdk.out/deploy-output.json
  • In ./cdk.out/deploy-output.json you will find a JSON object with a key for each stack that produced an output (eg your stack that contains an API gateway) In ./cdk.out/deploy-output.json you will find a JSON object with a key for each stack that produced an output (eg your stack that contains an API gateway)
  • manually parse that JSON to get your apigateway url手动解析 JSON 以获取您的 apigateway url
  • create your configuration file and upload it to S3 (you can do it via aws-sdk)创建您的配置文件并将其上传到 S3(您可以通过 aws-sdk 完成)

Of course, you have the last steps in a custom script, which means that you have to wrap your cdk deploy .当然,您有自定义脚本中的最后一步,这意味着您必须包装您的cdk deploy I suggest to do so with a nodejs script, so that you can leverage aws-sdk to upload your file to S3 easily.我建议使用 nodejs 脚本执行此操作,以便您可以利用 aws-sdk 轻松将文件上传到 S3。

Accepting that cdk doesn't support this, I split logic into two cdk scripts, accessed API gateway URL as cdk output via the cli, then wrapped everything in a bash script. Accepting that cdk doesn't support this, I split logic into two cdk scripts, accessed API gateway URL as cdk output via the cli, then wrapped everything in a bash script.

AWS CDK: AWS CDK:

// API gateway
const api = new apigateway.RestApi(this, 'my-api', ..)

// output url
const myResourceURL = api.deploymentStage.urlForPath('/myResource');
new cdk.CfnOutput(this, 'MyRestURL', { value: myResourceURL });

Bash: Bash:

# deploy api gw
cdk deploy --app (..)  

# read url via cli with --query
export rest_url=`aws cloudformation describe-stacks --stack-name (..) --query "Stacks[0].Outputs[?OutputKey=='MyRestURL'].OutputValue" --output text`

# configure React app
echo "{ \"api\" : { \"invokeUrl\" : \"$rest_url\" } }" > src/app-config.json

# build React app with url
npm run build

# run second cdk app to deploy React built output folder
cdk deploy --app (..)  

Is there a better way?有没有更好的办法?

I solved a similar issue:我解决了一个类似的问题:

  • Needed to build and upload react-app as well还需要构建和上传 react-app
  • Supported dynamic configuration reading from react-app - look here支持从 react-app 读取动态配置 - 看这里
  • Released my react-app with specific version (in a separate flow)发布了我的特定版本的 react-app(在单独的流程中)
  • Then, during CDK deployment of my app, it took a specific version of my react-app (version retrieved from local configuration) and uploaded its zip file to S3 bucket using CDK BucketDeployment然后,在我的应用程序的 CDK 部署期间,它采用了我的 react-app 的特定版本(从本地配置中检索的版本)并使用 CDK BucketDeployment 将其 zip 文件上传到 S3 存储桶
  • Then, using AwsCustomResource I generated a configuration file with references to Cognito and API-GW and uploaded this file to S3 as well:然后,我使用 AwsCustomResource 生成了一个配置文件,其中包含对 Cognito 和 API-GW 的引用,并将该文件也上传到 S3:

 // create s3 bucket for react-app const uiBucket = new Bucket(this, "ui", { bucketName: this.stackName + "-s3-react-app", blockPublicAccess: BlockPublicAccess.BLOCK_ALL }); let confObj = { "myjsonobj": { "region": `${this.region}`, "identity_pool_id": `${props.CognitoIdentityPool.ref}`, "myBackend": `${apiGw.deploymentStage.urlForPath("/")}` } }; const dataString = JSON.stringify(confObj, null, 4); const bucketDeployment = new BucketDeployment(this, this.stackName + "-app", { destinationBucket: uiBucket, sources: [Source.asset(`reactapp-v1.zip`)] }); bucketDeployment.node.addDependency(uiBucket) const s3Upload = new custom.AwsCustomResource(this, 'config-json', { policy: custom.AwsCustomResourcePolicy.fromSdkCalls({resources: custom.AwsCustomResourcePolicy.ANY_RESOURCE}), onCreate: { service: "S3", action: "putObject", parameters: { Body: dataString, Bucket: `${uiBucket.bucketName}`, Key: "app-config.json", }, physicalResourceId: PhysicalResourceId.of(`${uiBucket.bucketName}`) } }); s3Upload.node.addDependency(bucketDeployment);

As others have mentioned, this isn't supported within CDK.正如其他人所提到的,这在 CDK 中不受支持。 So this how we solved it in SST: https://github.com/serverless-stack/serverless-stack所以这就是我们在 SST 中解决它的方法: https://github.com/serverless-stack/serverless-stack

  1. On the CDK side, allow defining React environment variables using the outputs of other constructs.在 CDK 方面,允许使用其他构造的输出定义 React 环境变量。

     // Create a React.js app const site = new sst.ReactStaticSite(this, "Site", { path: "frontend", environment: { // Pass in the API endpoint to our app REACT_APP_API_URL: api.url, }, });
  2. Spit out a config file while starting the local environment for the backend.在启动后端的本地环境时吐出一个配置文件。

  3. Then start React using sst-env -- react-scripts start , where we havea simple CLI that reads from the config file and loads them as build-time environment variables in React.然后使用sst-env -- react-scripts start启动 React,我们有一个简单的 CLI ,它从配置文件中读取并将它们作为构建时环境变量加载到 React 中。

  4. While deploying, replace these environment variables inside a custom resource based on the outputs.部署时,根据输出替换自定义资源中的这些环境变量。

We wrote about it here: https://serverless-stack.com/chapters/setting-serverless-environments-variables-in-a-react-app.html我们在这里写过: https://serverless-stack.com/chapters/setting-serverless-environments-variables-in-a-react-app.html

And here's the source for the ReactStaticSite and StaticSite constructs for reference.这里是ReactStaticSiteStaticSite结构的来源供参考。

In my case, I'm using the Python language for CDK.就我而言,我使用 CDK 的 Python 语言。 I have a Makefile which I invoke directly from my app.py like this: os.system("make") .我有一个 Makefile,我可以像这样直接从我的 app.py 调用它: os.system("make") I use the make to build up a layer zip file per AWS Docs .我使用 make 根据AWS Docs构建一个层 zip 文件。 Technically you can invoke whatever you'd like.从技术上讲,您可以调用任何您想要的。 You must import the os package of course.当然,您必须导入 os 包。 Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM