这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。
本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
配置 CDK 工具包消息和交互
AWS CDK Toolkit 库提供了自定义在 CDK 操作期间如何处理消息和交互的
IIoHost
界面,使您能够控制部署进度、错误消息和用户提示的显示,从而更好地与应用程序的用户体验集成。
在执行部署或综合等操作之前,您需要了解 CDK Toolkit 是如何与用户通信的。该IIoHost
接口充当 CDK Toolkit 和您的应用程序之间的通信渠道,负责处理传出的消息和传入的用户响应。
当 CDK 工具包运行操作时,它通过两种主要机制进行通信:
-
消息:通知您操作进度的信息输出(例如 “开始部署” 或 “资源已创建”)。
-
请求:需要输入或确认的决策点(例如 “您想部署这些更改吗?”) ,让你有机会提供事先不知道需要的信息。
使用接IIoHost
口
该IIoHost
接口由两个主要方法组成:
-
notify
:处理单向信息性消息。 -
requestResponse
:处理需要响应的交互式请求。
import { IoMessage, IoRequest } from '@aws-cdk/toolkit-lib'; interface IIoHost { // Handle informational messages notify(message: IoMessage): Promise<void>; // Handle requests that need responses requestResponse(request: IoRequest): Promise<any>; }
消息级别和请求类型
CDK 工具包生成多种类型的消息和请求:
消息级别
-
调试:故障排除的详细消息。
-
错误:可能影响操作的错误消息。
-
信息:一般信息性消息。
-
结果-操作的主要消息。
-
跟踪:非常详细的执行流程信息。
-
警告:不会阻止操作的警告消息。
有关完整列表,请参阅 AWS CDK 工具包库 API 参考中的IoMessages 注册表。
请求类型
CDK 工具包在需要用户输入或确认时发送请求。这些是允许回复的特殊消息。如果未提供任何响应,Toolkit 将在可用时使用默认响应。
基本 IIoHost
实施
以下是实现自定义 io 主机的简单示例:
import { Toolkit } from '@aws-cdk/toolkit-lib'; // Create a toolkit with custom message handling const toolkit = new Toolkit({ ioHost: { // Implementing the IIoHost interface // Handle informational messages notify: async function (msg) { // Example: Handle different message levels appropriately switch (msg.level) { case 'error': console.error(`[${msg.time}] ERROR: ${msg.message}`); break; case 'warning': console.warn(`[${msg.time}] WARNING: ${msg.message}`); break; case 'info': console.info(`[${msg.time}] INFO: ${msg.message}`); break; case 'debug': console.debug(`[${msg.time}] DEBUG: ${msg.message}`); break; case 'trace': console.debug(`[${msg.time}] TRACE: ${msg.message}`); break; default: console.log(`[${msg.time}] ${msg.level}: ${msg.message}`); } }, // Handle requests that need responses requestResponse: async function (msg) { // Example: Log the request and use default response console.log(`Request: ${msg.message}, using default: ${msg.defaultResponse}`); return msg.defaultResponse; // Or implement custom logic to provide responses // if (msg.type === 'deploy') { // return promptUserForDeployment(msg); // } } } as IIoHost // Explicitly cast to IIoHost interface });
CDK Toolkit 等待每次调用完成,允许您在处理消息时执行异步操作,例如 HTTP 请求或用户提示。
默认IIoHost
行为
如果您不提供自定义 io 主机,CDK 工具包库将使用默认的非交互式实现:
-
消息的控制台输出(对不同的消息类型使用适当的颜色)。
-
完全非交互式,不提示用户输入。
-
尽可能自动使用默认响应(相当于对提示回答 “是”)。
-
当需要输入但没有默认响应可用时失败。
此默认行为适用于无人值守的操作,但不适用于交互式命令行应用程序。对于需要用户交互的命令行应用程序,您需要实现自定义 io 主机。自定义实现对于与日志系统或其他专业环境集成也很有用。 UIs
高级 io 主机实现
对于更复杂的场景,我们建议将扩展NonInteractiveIoHost
类作为起点。这种方法允许您利用现有的非交互式实现,同时仅自定义需要更改的特定行为。
以下是扩展基本实现的自定义 io 主机的示例:
import { NonInteractiveIoHost } from '@aws-cdk/toolkit-lib'; class MyCustomIoHost extends NonInteractiveIoHost { // Override only the methods you need to customize // Example: Custom implementation for notify public async notify(msg: IoMessage<unknown>): Promise<void> { // Add custom notification handling logic if (msg.level === 'error') { console.error(`ERROR: ${msg.message}`); // Optionally log to a service or notify a monitoring system await this.logToMonitoringService(msg); } else { await super.notify(msg); } } // Example: Custom implementation for requestResponse public async requestResponse<T, U>(request: IoRequest<T, U>): Promise<U> { // Implement custom request handling console.log(`Received request: ${request.message}`); return request.defaultResponse; } private async logToMonitoringService(msg: IoMessage<unknown>): Promise<void> { // Implementation for monitoring service integration console.log(`Logging to monitoring service: ${msg.level} - ${msg.message}`); } }
这种方法比从头开始实现整个IIoHost
接口更易于维护,因为您只需要重写需要自定义行为的特定方法即可。
与不同的环境集成
Web 应用程序集成
import { Toolkit } from '@aws-cdk/toolkit-lib'; // Example for integrating with a web application const toolkit = new Toolkit({ ioHost: { notify: async function (msg) { // Send message to frontend via WebSocket webSocketServer.send(JSON.stringify({ type: 'cdk-notification', messageLevel: msg.level, message: msg.message, time: msg.time })); }, requestResponse: async function (msg) { // Create a promise that will be resolved when the user responds return new Promise((resolve) => { const requestId = generateUniqueId(); // Store the resolver function pendingRequests[requestId] = resolve; // Send request to frontend webSocketServer.send(JSON.stringify({ type: 'cdk-request', requestId: requestId, requestType: msg.type, message: msg.message, defaultResponse: msg.defaultResponse })); // Frontend would call an API endpoint with the response, // which would then call pendingRequests[requestId](response) }); } } as IIoHost // Explicitly cast to IIoHost interface });
CI/CD 环境集成
import { Toolkit } from '@aws-cdk/toolkit-lib'; // Example for CI/CD environments (non-interactive) const toolkit = new Toolkit({ ioHost: { notify: async function (msg) { // Log all messages with appropriate level switch (msg.level) { case 'error': console.error(msg.message); break; case 'warning': console.warn(msg.message); break; default: console.log(msg.message); } }, requestResponse: async function (msg) { // In CI/CD, always use default responses or predefined answers console.log(`Auto-responding to request: ${msg.message} with ${msg.defaultResponse}`); return msg.defaultResponse; } } as IIoHost // Explicitly cast to IIoHost interface });
实现 io 主机的最佳实践
在实现自定义 io 主机时,请考虑以下最佳实践:
-
错误处理:在 io 主机方法中实现强大的错误处理,以防止故障影响 CDK 操作。
-
超时:考虑为用户交互实现超时,以防止无限期等待。
-
日志:在日志中存储重要消息以进行故障排除,尤其是在非交互式环境中。
-
默认响应:为无法进行用户交互的自动化环境提供合理的默认响应。
-
进度指示:对于长期运行的操作,请提供清晰的进度指示器以改善用户体验。
以下示例通过实现具有错误处理、用户交互超时和正确日志记录的自定义 io 主机来演示这些最佳实践。此实现适用于需要在用户响应和可靠操作之间取得平衡的交互式应用程序:
import { Toolkit } from '@aws-cdk/toolkit-lib'; // Example with error handling and timeouts const toolkit = new Toolkit({ ioHost: { notify: async function (msg) { try { console.log(`[${msg.time}] ${msg.level}: ${msg.message}`); // Additional logging or UI updates } catch (error) { // Ensure errors in notification handling don't break the CDK operation console.error("Error handling notification:", error); } }, requestResponse: async function (msg) { try { // Implement timeout for user response const response = await Promise.race([ getUserResponse(msg), new Promise(resolve => setTimeout(() => resolve(msg.defaultResponse), 60000)) ]); return response; } catch (error) { console.error("Error handling request:", error); return msg.defaultResponse; } } } as IIoHost // Explicitly cast to IIoHost interface });
故障排除
实现自定义 io 主机时的注意事项:
-
未处理的承诺拒绝:确保使用 try/catch 块正确处理所有异步操作。
-
无限等待:为所有用户交互设置超时,以防止应用程序挂起。
-
缺少消息级别:请做好准备,以应对未来的 CDK 版本中可能添加的新消息级别。
-
响应不一致:确保您的 requestResponse 实现以预期的格式返回值。
以下示例演示了一种处理消息级别的强大方法,包括优雅地处理可能在 future CDK 版本中引入的未知消息类型。此实现可确保您的 io 主机与 CDK 更新保持兼容,同时保持正确的日志记录:
import { Toolkit } from '@aws-cdk/toolkit-lib'; // Example of handling unknown message levels const toolkit = new Toolkit({ ioHost: { notify: async function (msg) { // Handle known levels const knownLevels = ['info', 'warning', 'error', 'debug', 'trace', 'status']; if (knownLevels.includes(msg.level)) { // Handle known level handleKnownMessageLevel(msg); } else { // Handle unknown level as info console.log(`Unknown message level "${msg.level}": ${msg.message}`); } }, requestResponse: async function (msg) { // Default implementation return msg.defaultResponse; } } as IIoHost // Explicitly cast to IIoHost interface });