AWS CDK:运行 CDK 序列中的外部构建命令?
AWS CDK: run external build command in CDK sequence?
是否可以 运行 将外部构建命令作为 CDK 堆栈序列的一部分?意图: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
})
}
不幸的是,这是不可能的,因为必要的参考仅在部署后可用,因此在您尝试写入文件后(该文件将包含 cdk tokens)。
我个人已经通过告诉 cdk 将 apigateway URL 输出到一个文件然后解析它 在 部署之后将其上传到 S3 存储桶来解决这个问题你需要:
- 使用输出文件选项进行部署,例如:
cdk deploy -O ./cdk.out/deploy-output.json
- 在
./cdk.out/deploy-output.json
中,您会发现一个 JSON 对象,其中每个堆栈都有一个密钥,每个堆栈都会产生一个输出(例如,您的堆栈包含一个 API 网关)
- 手动解析 JSON 以获得您的 apigateway url
- 创建您的配置文件并将其上传到 S3(您可以通过 aws-sdk 完成)
当然,您在自定义脚本中有最后的步骤,这意味着您必须包装 cdk deploy
。我建议使用 nodejs 脚本来执行此操作,以便您可以利用 aws-sdk 轻松将文件上传到 S3。
承认 cdk 不支持这一点,我将逻辑分成两个 cdk 脚本,通过 cli 访问 API 网关 URL 作为 cdk 输出,然后将所有内容包装在 bash 脚本。
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:
# 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 (..)
有没有更好的方法?
我解决了类似的问题:
- 还需要构建和上传 react-app
- 支持从 react-app 读取动态配置 - 查看
- 发布了我的 react-app 特定版本(在单独的流程中)
- 然后,在我的应用程序的 CDK 部署期间,它使用我的 react-app 的特定版本(从本地配置检索的版本)并使用 CDK BucketDeployment
将其 zip 文件上传到 S3 存储桶
- 然后,我使用 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);
正如其他人所提到的,这在 CDK 中不受支持。所以这就是我们在 SST 中解决它的方法:https://github.com/serverless-stack/serverless-stack
在 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,
},
});
在为后端启动本地环境时吐出一个配置文件。
然后使用 sst-env -- react-scripts start
启动 React,其中我们有 a simple CLI 从配置文件中读取并将它们作为构建时环境变量加载到 React 中。
部署时,根据输出在自定义资源中替换这些环境变量。
我们在这里写道:https://serverless-stack.com/chapters/setting-serverless-environments-variables-in-a-react-app.html
这里是 ReactStaticSite
and StaticSite
构造的来源以供参考。
是否可以 运行 将外部构建命令作为 CDK 堆栈序列的一部分?意图: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
})
}
不幸的是,这是不可能的,因为必要的参考仅在部署后可用,因此在您尝试写入文件后(该文件将包含 cdk tokens)。
我个人已经通过告诉 cdk 将 apigateway URL 输出到一个文件然后解析它 在 部署之后将其上传到 S3 存储桶来解决这个问题你需要:
- 使用输出文件选项进行部署,例如:
cdk deploy -O ./cdk.out/deploy-output.json
- 在
./cdk.out/deploy-output.json
中,您会发现一个 JSON 对象,其中每个堆栈都有一个密钥,每个堆栈都会产生一个输出(例如,您的堆栈包含一个 API 网关) - 手动解析 JSON 以获得您的 apigateway url
- 创建您的配置文件并将其上传到 S3(您可以通过 aws-sdk 完成)
当然,您在自定义脚本中有最后的步骤,这意味着您必须包装 cdk deploy
。我建议使用 nodejs 脚本来执行此操作,以便您可以利用 aws-sdk 轻松将文件上传到 S3。
承认 cdk 不支持这一点,我将逻辑分成两个 cdk 脚本,通过 cli 访问 API 网关 URL 作为 cdk 输出,然后将所有内容包装在 bash 脚本。
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:
# 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 (..)
有没有更好的方法?
我解决了类似的问题:
- 还需要构建和上传 react-app
- 支持从 react-app 读取动态配置 - 查看
- 发布了我的 react-app 特定版本(在单独的流程中)
- 然后,在我的应用程序的 CDK 部署期间,它使用我的 react-app 的特定版本(从本地配置检索的版本)并使用 CDK BucketDeployment 将其 zip 文件上传到 S3 存储桶
- 然后,我使用 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);
正如其他人所提到的,这在 CDK 中不受支持。所以这就是我们在 SST 中解决它的方法:https://github.com/serverless-stack/serverless-stack
在 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, }, });
在为后端启动本地环境时吐出一个配置文件。
然后使用
sst-env -- react-scripts start
启动 React,其中我们有 a simple CLI 从配置文件中读取并将它们作为构建时环境变量加载到 React 中。部署时,根据输出在自定义资源中替换这些环境变量。
我们在这里写道:https://serverless-stack.com/chapters/setting-serverless-environments-variables-in-a-react-app.html
这里是 ReactStaticSite
and StaticSite
构造的来源以供参考。