diff --git a/packages/@aws-cdk/aws-chatbot/test/chatbot-logretention.integ.snapshot/asset.22bb41d703c8e7a9a1712308f455fcf58cc012b0a386c9df563a6244a61e6665/index.js b/packages/@aws-cdk/aws-chatbot/test/chatbot-logretention.integ.snapshot/asset.22bb41d703c8e7a9a1712308f455fcf58cc012b0a386c9df563a6244a61e6665/index.js index 5292af72a643d..249a5b580714f 100644 --- a/packages/@aws-cdk/aws-chatbot/test/chatbot-logretention.integ.snapshot/asset.22bb41d703c8e7a9a1712308f455fcf58cc012b0a386c9df563a6244a61e6665/index.js +++ b/packages/@aws-cdk/aws-chatbot/test/chatbot-logretention.integ.snapshot/asset.22bb41d703c8e7a9a1712308f455fcf58cc012b0a386c9df563a6244a61e6665/index.js @@ -12,15 +12,14 @@ const AWS = require("aws-sdk"); * @param options CloudWatch API SDK options. */ async function createLogGroupSafe(logGroupName, region, options) { - var _a; // If we set the log retention for a lambda, then due to the async nature of // Lambda logging there could be a race condition when the same log group is // already being created by the lambda execution. This can sometime result in // an error "OperationAbortedException: A conflicting operation is currently // in progress...Please try again." // To avoid an error, we do as requested and try again. - let retryCount = (options === null || options === void 0 ? void 0 : options.maxRetries) == undefined ? 10 : options.maxRetries; - const delay = ((_a = options === null || options === void 0 ? void 0 : options.retryOptions) === null || _a === void 0 ? void 0 : _a.base) == undefined ? 10 : options.retryOptions.base; + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; do { try { const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); @@ -56,13 +55,12 @@ async function createLogGroupSafe(logGroupName, region, options) { * @param retentionInDays the number of days to retain the log events in the specified log group. */ async function setRetentionPolicy(logGroupName, region, options, retentionInDays) { - var _a; // The same as in createLogGroupSafe(), here we could end up with the race // condition where a log group is either already being created or its retention // policy is being updated. This would result in an OperationAbortedException, // which we will try to catch and retry the command a number of times before failing - let retryCount = (options === null || options === void 0 ? void 0 : options.maxRetries) == undefined ? 10 : options.maxRetries; - const delay = ((_a = options === null || options === void 0 ? void 0 : options.retryOptions) === null || _a === void 0 ? void 0 : _a.base) == undefined ? 10 : options.retryOptions.base; + let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries; + const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base; do { try { const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options }); @@ -173,4 +171,4 @@ async function handler(event, context) { } } exports.handler = handler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0JBQStCOzs7QUFFL0IsNkRBQTZEO0FBQzdELCtCQUErQjtBQVMvQjs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsa0JBQWtCLENBQUMsWUFBb0IsRUFBRSxNQUFlLEVBQUUsT0FBeUI7O0lBQ2hHLDRFQUE0RTtJQUM1RSw0RUFBNEU7SUFDNUUsNkVBQTZFO0lBQzdFLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsdURBQXVEO0lBQ3ZELElBQUksVUFBVSxHQUFHLENBQUEsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLFVBQVUsS0FBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUM1RSxNQUFNLEtBQUssR0FBRyxPQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxZQUFZLDBDQUFFLElBQUksS0FBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7SUFDeEYsR0FBRztRQUNELElBQUk7WUFDRixNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDaEcsTUFBTSxjQUFjLENBQUMsY0FBYyxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoRSxPQUFPO1NBQ1I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxnQ0FBZ0MsRUFBRTtnQkFDbkQsMkRBQTJEO2dCQUMzRCxPQUFPO2FBQ1I7WUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssMkJBQTJCLEVBQUU7Z0JBQzlDLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTtvQkFDbEIsVUFBVSxFQUFFLENBQUM7b0JBQ2IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDekQsU0FBUztpQkFDVjtxQkFBTTtvQkFDTCxzRkFBc0Y7b0JBQ3RGLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztpQkFDekQ7YUFDRjtZQUNELE1BQU0sS0FBSyxDQUFDO1NBQ2I7S0FDRixRQUFRLElBQUksRUFBRSxDQUFDLG9DQUFvQztBQUN0RCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxZQUFvQixFQUFFLE1BQWUsRUFBRSxPQUF5QixFQUFFLGVBQXdCOztJQUMxSCwwRUFBMEU7SUFDMUUsK0VBQStFO0lBQy9FLDhFQUE4RTtJQUM5RSxvRkFBb0Y7SUFDcEYsSUFBSSxVQUFVLEdBQUcsQ0FBQSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsVUFBVSxLQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQzVFLE1BQU0sS0FBSyxHQUFHLE9BQUEsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLFlBQVksMENBQUUsSUFBSSxLQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztJQUN4RixHQUFHO1FBQ0QsSUFBSTtZQUNGLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNoRyxJQUFJLENBQUMsZUFBZSxFQUFFO2dCQUNwQixNQUFNLGNBQWMsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDeEU7aUJBQU07Z0JBQ0wsTUFBTSxjQUFjLENBQUMsa0JBQWtCLENBQUMsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUN0RjtZQUNELE9BQU87U0FFUjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUM5QyxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUU7b0JBQ2xCLFVBQVUsRUFBRSxDQUFDO29CQUNiLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBQ3pELFNBQVM7aUJBQ1Y7cUJBQU07b0JBQ0wsc0ZBQXNGO29CQUN0RixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7aUJBQ3pEO2FBQ0Y7WUFDRCxNQUFNLEtBQUssQ0FBQztTQUNiO0tBQ0YsUUFBUSxJQUFJLEVBQUUsQ0FBQyxvQ0FBb0M7QUFDdEQsQ0FBQztBQUVNLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0QsRUFBRSxPQUEwQjtJQUMxRyxJQUFJO1FBQ0YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFbkMsdUJBQXVCO1FBQ3ZCLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUM7UUFFM0QscUNBQXFDO1FBQ3JDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUM7UUFFL0QsaUNBQWlDO1FBQ2pDLE1BQU0sWUFBWSxHQUFHLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUUxRSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFO1lBQ3BFLDhCQUE4QjtZQUM5QixNQUFNLGtCQUFrQixDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDckUsTUFBTSxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRTdILElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUU7Z0JBQ2xDLHFFQUFxRTtnQkFDckUsMkZBQTJGO2dCQUMzRiw2RUFBNkU7Z0JBQzdFLDRFQUE0RTtnQkFDNUUsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7Z0JBQ3RDLE1BQU0sa0JBQWtCLENBQUMsZUFBZSxPQUFPLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN0RiwwRkFBMEY7Z0JBQzFGLHlGQUF5RjtnQkFDekYsaUJBQWlCO2dCQUNqQixNQUFNLGtCQUFrQixDQUFDLGVBQWUsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDMUY7U0FDRjtRQUVELE1BQU0sT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7S0FDOUM7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFZixNQUFNLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0U7SUFFRCxTQUFTLE9BQU8sQ0FBQyxjQUFzQixFQUFFLE1BQWMsRUFBRSxrQkFBMEI7UUFDakYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNsQyxNQUFNLEVBQUUsY0FBYztZQUN0QixNQUFNLEVBQUUsTUFBTTtZQUNkLGtCQUFrQixFQUFFLGtCQUFrQjtZQUN0QyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1lBQzFCLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxpQkFBaUI7WUFDMUMsSUFBSSxFQUFFO2dCQUNKLG1GQUFtRjtnQkFDbkYsWUFBWSxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZO2FBQ3BEO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFeEMsaUVBQWlFO1FBQ2pFLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzFELE1BQU0sY0FBYyxHQUFHO1lBQ3JCLFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTtZQUM1QixJQUFJLEVBQUUsU0FBUyxDQUFDLElBQUk7WUFDcEIsTUFBTSxFQUFFLEtBQUs7WUFDYixPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsRUFBRSxFQUFFLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxNQUFNLEVBQUU7U0FDdkUsQ0FBQztRQUVGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSTtnQkFDRixpRUFBaUU7Z0JBQ2pFLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNsRSxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO2FBQ2Y7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDWDtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFNBQVMsaUJBQWlCLENBQUMsVUFBZTtRQUN4QyxNQUFNLFlBQVksR0FBb0IsRUFBRSxDQUFDO1FBQ3pDLElBQUksVUFBVSxFQUFFO1lBQ2QsSUFBSSxVQUFVLENBQUMsVUFBVSxFQUFFO2dCQUN6QixZQUFZLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2FBQy9EO1lBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxFQUFFO2dCQUNuQixZQUFZLENBQUMsWUFBWSxHQUFHO29CQUMxQixJQUFJLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO2lCQUNwQyxDQUFDO2FBQ0g7U0FDRjtRQUNELE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDO0FBM0ZELDBCQTJGQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBSZXRyeURlbGF5T3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuaW50ZXJmYWNlIFNka1JldHJ5T3B0aW9ucyB7XG4gIG1heFJldHJpZXM/OiBudW1iZXI7XG4gIHJldHJ5T3B0aW9ucz86IFJldHJ5RGVsYXlPcHRpb25zO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBsb2cgZ3JvdXAgYW5kIGRvZXNuJ3QgdGhyb3cgaWYgaXQgZXhpc3RzLlxuICpcbiAqIEBwYXJhbSBsb2dHcm91cE5hbWUgdGhlIG5hbWUgb2YgdGhlIGxvZyBncm91cCB0byBjcmVhdGUuXG4gKiBAcGFyYW0gcmVnaW9uIHRvIGNyZWF0ZSB0aGUgbG9nIGdyb3VwIGluXG4gKiBAcGFyYW0gb3B0aW9ucyBDbG91ZFdhdGNoIEFQSSBTREsgb3B0aW9ucy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlTG9nR3JvdXBTYWZlKGxvZ0dyb3VwTmFtZTogc3RyaW5nLCByZWdpb24/OiBzdHJpbmcsIG9wdGlvbnM/OiBTZGtSZXRyeU9wdGlvbnMpIHtcbiAgLy8gSWYgd2Ugc2V0IHRoZSBsb2cgcmV0ZW50aW9uIGZvciBhIGxhbWJkYSwgdGhlbiBkdWUgdG8gdGhlIGFzeW5jIG5hdHVyZSBvZlxuICAvLyBMYW1iZGEgbG9nZ2luZyB0aGVyZSBjb3VsZCBiZSBhIHJhY2UgY29uZGl0aW9uIHdoZW4gdGhlIHNhbWUgbG9nIGdyb3VwIGlzXG4gIC8vIGFscmVhZHkgYmVpbmcgY3JlYXRlZCBieSB0aGUgbGFtYmRhIGV4ZWN1dGlvbi4gVGhpcyBjYW4gc29tZXRpbWUgcmVzdWx0IGluXG4gIC8vIGFuIGVycm9yIFwiT3BlcmF0aW9uQWJvcnRlZEV4Y2VwdGlvbjogQSBjb25mbGljdGluZyBvcGVyYXRpb24gaXMgY3VycmVudGx5XG4gIC8vIGluIHByb2dyZXNzLi4uUGxlYXNlIHRyeSBhZ2Fpbi5cIlxuICAvLyBUbyBhdm9pZCBhbiBlcnJvciwgd2UgZG8gYXMgcmVxdWVzdGVkIGFuZCB0cnkgYWdhaW4uXG4gIGxldCByZXRyeUNvdW50ID0gb3B0aW9ucz8ubWF4UmV0cmllcyA9PSB1bmRlZmluZWQgPyAxMCA6IG9wdGlvbnMubWF4UmV0cmllcztcbiAgY29uc3QgZGVsYXkgPSBvcHRpb25zPy5yZXRyeU9wdGlvbnM/LmJhc2UgPT0gdW5kZWZpbmVkID8gMTAgOiBvcHRpb25zLnJldHJ5T3B0aW9ucy5iYXNlO1xuICBkbyB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsb3Vkd2F0Y2hsb2dzID0gbmV3IEFXUy5DbG91ZFdhdGNoTG9ncyh7IGFwaVZlcnNpb246ICcyMDE0LTAzLTI4JywgcmVnaW9uLCAuLi5vcHRpb25zIH0pO1xuICAgICAgYXdhaXQgY2xvdWR3YXRjaGxvZ3MuY3JlYXRlTG9nR3JvdXAoeyBsb2dHcm91cE5hbWUgfSkucHJvbWlzZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ1Jlc291cmNlQWxyZWFkeUV4aXN0c0V4Y2VwdGlvbicpIHtcbiAgICAgICAgLy8gVGhlIGxvZyBncm91cCBpcyBhbHJlYWR5IGNyZWF0ZWQgYnkgdGhlIGxhbWJkYSBleGVjdXRpb25cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdPcGVyYXRpb25BYm9ydGVkRXhjZXB0aW9uJykge1xuICAgICAgICBpZiAocmV0cnlDb3VudCA+IDApIHtcbiAgICAgICAgICByZXRyeUNvdW50LS07XG4gICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRlbGF5KSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVGhlIGxvZyBncm91cCBpcyBzdGlsbCBiZWluZyBjcmVhdGVkIGJ5IGFub3RoZXIgZXhlY3V0aW9uIGJ1dCB3ZSBhcmUgb3V0IG9mIHJldHJpZXNcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ091dCBvZiBhdHRlbXB0cyB0byBjcmVhdGUgYSBsb2dHcm91cCcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH0gd2hpbGUgKHRydWUpOyAvLyBleGl0IGhhcHBlbnMgb24gcmV0cnkgY291bnQgY2hlY2tcbn1cblxuLyoqXG4gKiBQdXRzIG9yIGRlbGV0ZXMgYSByZXRlbnRpb24gcG9saWN5IG9uIGEgbG9nIGdyb3VwLlxuICpcbiAqIEBwYXJhbSBsb2dHcm91cE5hbWUgdGhlIG5hbWUgb2YgdGhlIGxvZyBncm91cCB0byBjcmVhdGVcbiAqIEBwYXJhbSByZWdpb24gdGhlIHJlZ2lvbiBvZiB0aGUgbG9nIGdyb3VwXG4gKiBAcGFyYW0gb3B0aW9ucyBDbG91ZFdhdGNoIEFQSSBTREsgb3B0aW9ucy5cbiAqIEBwYXJhbSByZXRlbnRpb25JbkRheXMgdGhlIG51bWJlciBvZiBkYXlzIHRvIHJldGFpbiB0aGUgbG9nIGV2ZW50cyBpbiB0aGUgc3BlY2lmaWVkIGxvZyBncm91cC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2V0UmV0ZW50aW9uUG9saWN5KGxvZ0dyb3VwTmFtZTogc3RyaW5nLCByZWdpb24/OiBzdHJpbmcsIG9wdGlvbnM/OiBTZGtSZXRyeU9wdGlvbnMsIHJldGVudGlvbkluRGF5cz86IG51bWJlcikge1xuICAvLyBUaGUgc2FtZSBhcyBpbiBjcmVhdGVMb2dHcm91cFNhZmUoKSwgaGVyZSB3ZSBjb3VsZCBlbmQgdXAgd2l0aCB0aGUgcmFjZVxuICAvLyBjb25kaXRpb24gd2hlcmUgYSBsb2cgZ3JvdXAgaXMgZWl0aGVyIGFscmVhZHkgYmVpbmcgY3JlYXRlZCBvciBpdHMgcmV0ZW50aW9uXG4gIC8vIHBvbGljeSBpcyBiZWluZyB1cGRhdGVkLiBUaGlzIHdvdWxkIHJlc3VsdCBpbiBhbiBPcGVyYXRpb25BYm9ydGVkRXhjZXB0aW9uLFxuICAvLyB3aGljaCB3ZSB3aWxsIHRyeSB0byBjYXRjaCBhbmQgcmV0cnkgdGhlIGNvbW1hbmQgYSBudW1iZXIgb2YgdGltZXMgYmVmb3JlIGZhaWxpbmdcbiAgbGV0IHJldHJ5Q291bnQgPSBvcHRpb25zPy5tYXhSZXRyaWVzID09IHVuZGVmaW5lZCA/IDEwIDogb3B0aW9ucy5tYXhSZXRyaWVzO1xuICBjb25zdCBkZWxheSA9IG9wdGlvbnM/LnJldHJ5T3B0aW9ucz8uYmFzZSA9PSB1bmRlZmluZWQgPyAxMCA6IG9wdGlvbnMucmV0cnlPcHRpb25zLmJhc2U7XG4gIGRvIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY2xvdWR3YXRjaGxvZ3MgPSBuZXcgQVdTLkNsb3VkV2F0Y2hMb2dzKHsgYXBpVmVyc2lvbjogJzIwMTQtMDMtMjgnLCByZWdpb24sIC4uLm9wdGlvbnMgfSk7XG4gICAgICBpZiAoIXJldGVudGlvbkluRGF5cykge1xuICAgICAgICBhd2FpdCBjbG91ZHdhdGNobG9ncy5kZWxldGVSZXRlbnRpb25Qb2xpY3koeyBsb2dHcm91cE5hbWUgfSkucHJvbWlzZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgY2xvdWR3YXRjaGxvZ3MucHV0UmV0ZW50aW9uUG9saWN5KHsgbG9nR3JvdXBOYW1lLCByZXRlbnRpb25JbkRheXMgfSkucHJvbWlzZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvci5jb2RlID09PSAnT3BlcmF0aW9uQWJvcnRlZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgaWYgKHJldHJ5Q291bnQgPiAwKSB7XG4gICAgICAgICAgcmV0cnlDb3VudC0tO1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBkZWxheSkpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFRoZSBsb2cgZ3JvdXAgaXMgc3RpbGwgYmVpbmcgY3JlYXRlZCBieSBhbm90aGVyIGV4ZWN1dGlvbiBidXQgd2UgYXJlIG91dCBvZiByZXRyaWVzXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdPdXQgb2YgYXR0ZW1wdHMgdG8gY3JlYXRlIGEgbG9nR3JvdXAnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9IHdoaWxlICh0cnVlKTsgLy8gZXhpdCBoYXBwZW5zIG9uIHJldHJ5IGNvdW50IGNoZWNrXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBjb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dCkge1xuICB0cnkge1xuICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGV2ZW50KSk7XG5cbiAgICAvLyBUaGUgdGFyZ2V0IGxvZyBncm91cFxuICAgIGNvbnN0IGxvZ0dyb3VwTmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Mb2dHcm91cE5hbWU7XG5cbiAgICAvLyBUaGUgcmVnaW9uIG9mIHRoZSB0YXJnZXQgbG9nIGdyb3VwXG4gICAgY29uc3QgbG9nR3JvdXBSZWdpb24gPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuTG9nR3JvdXBSZWdpb247XG5cbiAgICAvLyBQYXJzZSB0byBBV1MgU0RLIHJldHJ5IG9wdGlvbnNcbiAgICBjb25zdCByZXRyeU9wdGlvbnMgPSBwYXJzZVJldHJ5T3B0aW9ucyhldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuU2RrUmV0cnkpO1xuXG4gICAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJyB8fCBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScpIHtcbiAgICAgIC8vIEFjdCBvbiB0aGUgdGFyZ2V0IGxvZyBncm91cFxuICAgICAgYXdhaXQgY3JlYXRlTG9nR3JvdXBTYWZlKGxvZ0dyb3VwTmFtZSwgbG9nR3JvdXBSZWdpb24sIHJldHJ5T3B0aW9ucyk7XG4gICAgICBhd2FpdCBzZXRSZXRlbnRpb25Qb2xpY3kobG9nR3JvdXBOYW1lLCBsb2dHcm91cFJlZ2lvbiwgcmV0cnlPcHRpb25zLCBwYXJzZUludChldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUmV0ZW50aW9uSW5EYXlzLCAxMCkpO1xuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIC8vIFNldCBhIHJldGVudGlvbiBwb2xpY3kgb2YgMSBkYXkgb24gdGhlIGxvZ3Mgb2YgdGhpcyB2ZXJ5IGZ1bmN0aW9uLlxuICAgICAgICAvLyBEdWUgdG8gdGhlIGFzeW5jIG5hdHVyZSBvZiB0aGUgbG9nIGdyb3VwIGNyZWF0aW9uLCB0aGUgbG9nIGdyb3VwIGZvciB0aGlzIGZ1bmN0aW9uIG1pZ2h0XG4gICAgICAgIC8vIHN0aWxsIGJlIG5vdCBjcmVhdGVkIHlldCBhdCB0aGlzIHBvaW50LiBUaGVyZWZvcmUgd2UgYXR0ZW1wdCB0byBjcmVhdGUgaXQuXG4gICAgICAgIC8vIEluIGNhc2UgaXQgaXMgYmVpbmcgY3JlYXRlZCwgY3JlYXRlTG9nR3JvdXBTYWZlIHdpbGwgaGFuZGxlIHRoZSBjb25mbGljdC5cbiAgICAgICAgY29uc3QgcmVnaW9uID0gcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTjtcbiAgICAgICAgYXdhaXQgY3JlYXRlTG9nR3JvdXBTYWZlKGAvYXdzL2xhbWJkYS8ke2NvbnRleHQuZnVuY3Rpb25OYW1lfWAsIHJlZ2lvbiwgcmV0cnlPcHRpb25zKTtcbiAgICAgICAgLy8gSWYgY3JlYXRlTG9nR3JvdXBTYWZlIGZhaWxzLCB0aGUgbG9nIGdyb3VwIGlzIG5vdCBjcmVhdGVkIGV2ZW4gYWZ0ZXIgbXVsdGlwbGUgYXR0ZW1wdHMuXG4gICAgICAgIC8vIEluIHRoaXMgY2FzZSB3ZSBoYXZlIG5vdGhpbmcgdG8gc2V0IHRoZSByZXRlbnRpb24gcG9saWN5IG9uIGJ1dCBhbiBleGNlcHRpb24gd2lsbCBza2lwXG4gICAgICAgIC8vIHRoZSBuZXh0IGxpbmUuXG4gICAgICAgIGF3YWl0IHNldFJldGVudGlvblBvbGljeShgL2F3cy9sYW1iZGEvJHtjb250ZXh0LmZ1bmN0aW9uTmFtZX1gLCByZWdpb24sIHJldHJ5T3B0aW9ucywgMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgcmVzcG9uZCgnU1VDQ0VTUycsICdPSycsIGxvZ0dyb3VwTmFtZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zb2xlLmxvZyhlKTtcblxuICAgIGF3YWl0IHJlc3BvbmQoJ0ZBSUxFRCcsIGUubWVzc2FnZSwgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkxvZ0dyb3VwTmFtZSk7XG4gIH1cblxuICBmdW5jdGlvbiByZXNwb25kKHJlc3BvbnNlU3RhdHVzOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nLCBwaHlzaWNhbFJlc291cmNlSWQ6IHN0cmluZykge1xuICAgIGNvbnN0IHJlc3BvbnNlQm9keSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIFN0YXR1czogcmVzcG9uc2VTdGF0dXMsXG4gICAgICBSZWFzb246IHJlYXNvbixcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgICAgRGF0YToge1xuICAgICAgICAvLyBBZGQgbG9nIGdyb3VwIG5hbWUgYXMgcGFydCBvZiB0aGUgcmVzcG9uc2Ugc28gdGhhdCBpdCdzIGF2YWlsYWJsZSB2aWEgRm46OkdldEF0dFxuICAgICAgICBMb2dHcm91cE5hbWU6IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Mb2dHcm91cE5hbWUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coJ1Jlc3BvbmRpbmcnLCByZXNwb25zZUJvZHkpO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCBwYXJzZWRVcmwgPSByZXF1aXJlKCd1cmwnKS5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgICAgcGF0aDogcGFyc2VkVXJsLnBhdGgsXG4gICAgICBtZXRob2Q6ICdQVVQnLFxuICAgICAgaGVhZGVyczogeyAnY29udGVudC10eXBlJzogJycsICdjb250ZW50LWxlbmd0aCc6IHJlc3BvbnNlQm9keS5sZW5ndGggfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1aXJlKCdodHRwcycpLnJlcXVlc3QocmVxdWVzdE9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VSZXRyeU9wdGlvbnMocmF3T3B0aW9uczogYW55KTogU2RrUmV0cnlPcHRpb25zIHtcbiAgICBjb25zdCByZXRyeU9wdGlvbnM6IFNka1JldHJ5T3B0aW9ucyA9IHt9O1xuICAgIGlmIChyYXdPcHRpb25zKSB7XG4gICAgICBpZiAocmF3T3B0aW9ucy5tYXhSZXRyaWVzKSB7XG4gICAgICAgIHJldHJ5T3B0aW9ucy5tYXhSZXRyaWVzID0gcGFyc2VJbnQocmF3T3B0aW9ucy5tYXhSZXRyaWVzLCAxMCk7XG4gICAgICB9XG4gICAgICBpZiAocmF3T3B0aW9ucy5iYXNlKSB7XG4gICAgICAgIHJldHJ5T3B0aW9ucy5yZXRyeU9wdGlvbnMgPSB7XG4gICAgICAgICAgYmFzZTogcGFyc2VJbnQocmF3T3B0aW9ucy5iYXNlLCAxMCksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXRyeU9wdGlvbnM7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0JBQStCOzs7QUFFL0IsNkRBQTZEO0FBQzdELCtCQUErQjtBQVMvQjs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsa0JBQWtCLENBQUMsWUFBb0IsRUFBRSxNQUFlLEVBQUUsT0FBeUI7SUFDaEcsNEVBQTRFO0lBQzVFLDRFQUE0RTtJQUM1RSw2RUFBNkU7SUFDN0UsNEVBQTRFO0lBQzVFLG1DQUFtQztJQUNuQyx1REFBdUQ7SUFDdkQsSUFBSSxVQUFVLEdBQUcsT0FBTyxFQUFFLFVBQVUsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUM1RSxNQUFNLEtBQUssR0FBRyxPQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7SUFDeEYsR0FBRztRQUNELElBQUk7WUFDRixNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDaEcsTUFBTSxjQUFjLENBQUMsY0FBYyxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoRSxPQUFPO1NBQ1I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxnQ0FBZ0MsRUFBRTtnQkFDbkQsMkRBQTJEO2dCQUMzRCxPQUFPO2FBQ1I7WUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssMkJBQTJCLEVBQUU7Z0JBQzlDLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTtvQkFDbEIsVUFBVSxFQUFFLENBQUM7b0JBQ2IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDekQsU0FBUztpQkFDVjtxQkFBTTtvQkFDTCxzRkFBc0Y7b0JBQ3RGLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztpQkFDekQ7YUFDRjtZQUNELE1BQU0sS0FBSyxDQUFDO1NBQ2I7S0FDRixRQUFRLElBQUksRUFBRSxDQUFDLG9DQUFvQztBQUN0RCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxZQUFvQixFQUFFLE1BQWUsRUFBRSxPQUF5QixFQUFFLGVBQXdCO0lBQzFILDBFQUEwRTtJQUMxRSwrRUFBK0U7SUFDL0UsOEVBQThFO0lBQzlFLG9GQUFvRjtJQUNwRixJQUFJLFVBQVUsR0FBRyxPQUFPLEVBQUUsVUFBVSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQzVFLE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxZQUFZLEVBQUUsSUFBSSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztJQUN4RixHQUFHO1FBQ0QsSUFBSTtZQUNGLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNoRyxJQUFJLENBQUMsZUFBZSxFQUFFO2dCQUNwQixNQUFNLGNBQWMsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDeEU7aUJBQU07Z0JBQ0wsTUFBTSxjQUFjLENBQUMsa0JBQWtCLENBQUMsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUN0RjtZQUNELE9BQU87U0FFUjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUM5QyxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUU7b0JBQ2xCLFVBQVUsRUFBRSxDQUFDO29CQUNiLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7b0JBQ3pELFNBQVM7aUJBQ1Y7cUJBQU07b0JBQ0wsc0ZBQXNGO29CQUN0RixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7aUJBQ3pEO2FBQ0Y7WUFDRCxNQUFNLEtBQUssQ0FBQztTQUNiO0tBQ0YsUUFBUSxJQUFJLEVBQUUsQ0FBQyxvQ0FBb0M7QUFDdEQsQ0FBQztBQUVNLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0QsRUFBRSxPQUEwQjtJQUMxRyxJQUFJO1FBQ0YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFbkMsdUJBQXVCO1FBQ3ZCLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUM7UUFFM0QscUNBQXFDO1FBQ3JDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUM7UUFFL0QsaUNBQWlDO1FBQ2pDLE1BQU0sWUFBWSxHQUFHLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUUxRSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFO1lBQ3BFLDhCQUE4QjtZQUM5QixNQUFNLGtCQUFrQixDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDckUsTUFBTSxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRTdILElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUU7Z0JBQ2xDLHFFQUFxRTtnQkFDckUsMkZBQTJGO2dCQUMzRiw2RUFBNkU7Z0JBQzdFLDRFQUE0RTtnQkFDNUUsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7Z0JBQ3RDLE1BQU0sa0JBQWtCLENBQUMsZUFBZSxPQUFPLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN0RiwwRkFBMEY7Z0JBQzFGLHlGQUF5RjtnQkFDekYsaUJBQWlCO2dCQUNqQixNQUFNLGtCQUFrQixDQUFDLGVBQWUsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDMUY7U0FDRjtRQUVELE1BQU0sT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7S0FDOUM7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFZixNQUFNLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0U7SUFFRCxTQUFTLE9BQU8sQ0FBQyxjQUFzQixFQUFFLE1BQWMsRUFBRSxrQkFBMEI7UUFDakYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNsQyxNQUFNLEVBQUUsY0FBYztZQUN0QixNQUFNLEVBQUUsTUFBTTtZQUNkLGtCQUFrQixFQUFFLGtCQUFrQjtZQUN0QyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1lBQzFCLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxpQkFBaUI7WUFDMUMsSUFBSSxFQUFFO2dCQUNKLG1GQUFtRjtnQkFDbkYsWUFBWSxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZO2FBQ3BEO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFeEMsaUVBQWlFO1FBQ2pFLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzFELE1BQU0sY0FBYyxHQUFHO1lBQ3JCLFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTtZQUM1QixJQUFJLEVBQUUsU0FBUyxDQUFDLElBQUk7WUFDcEIsTUFBTSxFQUFFLEtBQUs7WUFDYixPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsRUFBRSxFQUFFLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxNQUFNLEVBQUU7U0FDdkUsQ0FBQztRQUVGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSTtnQkFDRixpRUFBaUU7Z0JBQ2pFLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNsRSxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO2FBQ2Y7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDWDtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFNBQVMsaUJBQWlCLENBQUMsVUFBZTtRQUN4QyxNQUFNLFlBQVksR0FBb0IsRUFBRSxDQUFDO1FBQ3pDLElBQUksVUFBVSxFQUFFO1lBQ2QsSUFBSSxVQUFVLENBQUMsVUFBVSxFQUFFO2dCQUN6QixZQUFZLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2FBQy9EO1lBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxFQUFFO2dCQUNuQixZQUFZLENBQUMsWUFBWSxHQUFHO29CQUMxQixJQUFJLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO2lCQUNwQyxDQUFDO2FBQ0g7U0FDRjtRQUNELE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDO0FBM0ZELDBCQTJGQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBSZXRyeURlbGF5T3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuaW50ZXJmYWNlIFNka1JldHJ5T3B0aW9ucyB7XG4gIG1heFJldHJpZXM/OiBudW1iZXI7XG4gIHJldHJ5T3B0aW9ucz86IFJldHJ5RGVsYXlPcHRpb25zO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBsb2cgZ3JvdXAgYW5kIGRvZXNuJ3QgdGhyb3cgaWYgaXQgZXhpc3RzLlxuICpcbiAqIEBwYXJhbSBsb2dHcm91cE5hbWUgdGhlIG5hbWUgb2YgdGhlIGxvZyBncm91cCB0byBjcmVhdGUuXG4gKiBAcGFyYW0gcmVnaW9uIHRvIGNyZWF0ZSB0aGUgbG9nIGdyb3VwIGluXG4gKiBAcGFyYW0gb3B0aW9ucyBDbG91ZFdhdGNoIEFQSSBTREsgb3B0aW9ucy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlTG9nR3JvdXBTYWZlKGxvZ0dyb3VwTmFtZTogc3RyaW5nLCByZWdpb24/OiBzdHJpbmcsIG9wdGlvbnM/OiBTZGtSZXRyeU9wdGlvbnMpIHtcbiAgLy8gSWYgd2Ugc2V0IHRoZSBsb2cgcmV0ZW50aW9uIGZvciBhIGxhbWJkYSwgdGhlbiBkdWUgdG8gdGhlIGFzeW5jIG5hdHVyZSBvZlxuICAvLyBMYW1iZGEgbG9nZ2luZyB0aGVyZSBjb3VsZCBiZSBhIHJhY2UgY29uZGl0aW9uIHdoZW4gdGhlIHNhbWUgbG9nIGdyb3VwIGlzXG4gIC8vIGFscmVhZHkgYmVpbmcgY3JlYXRlZCBieSB0aGUgbGFtYmRhIGV4ZWN1dGlvbi4gVGhpcyBjYW4gc29tZXRpbWUgcmVzdWx0IGluXG4gIC8vIGFuIGVycm9yIFwiT3BlcmF0aW9uQWJvcnRlZEV4Y2VwdGlvbjogQSBjb25mbGljdGluZyBvcGVyYXRpb24gaXMgY3VycmVudGx5XG4gIC8vIGluIHByb2dyZXNzLi4uUGxlYXNlIHRyeSBhZ2Fpbi5cIlxuICAvLyBUbyBhdm9pZCBhbiBlcnJvciwgd2UgZG8gYXMgcmVxdWVzdGVkIGFuZCB0cnkgYWdhaW4uXG4gIGxldCByZXRyeUNvdW50ID0gb3B0aW9ucz8ubWF4UmV0cmllcyA9PSB1bmRlZmluZWQgPyAxMCA6IG9wdGlvbnMubWF4UmV0cmllcztcbiAgY29uc3QgZGVsYXkgPSBvcHRpb25zPy5yZXRyeU9wdGlvbnM/LmJhc2UgPT0gdW5kZWZpbmVkID8gMTAgOiBvcHRpb25zLnJldHJ5T3B0aW9ucy5iYXNlO1xuICBkbyB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsb3Vkd2F0Y2hsb2dzID0gbmV3IEFXUy5DbG91ZFdhdGNoTG9ncyh7IGFwaVZlcnNpb246ICcyMDE0LTAzLTI4JywgcmVnaW9uLCAuLi5vcHRpb25zIH0pO1xuICAgICAgYXdhaXQgY2xvdWR3YXRjaGxvZ3MuY3JlYXRlTG9nR3JvdXAoeyBsb2dHcm91cE5hbWUgfSkucHJvbWlzZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ1Jlc291cmNlQWxyZWFkeUV4aXN0c0V4Y2VwdGlvbicpIHtcbiAgICAgICAgLy8gVGhlIGxvZyBncm91cCBpcyBhbHJlYWR5IGNyZWF0ZWQgYnkgdGhlIGxhbWJkYSBleGVjdXRpb25cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdPcGVyYXRpb25BYm9ydGVkRXhjZXB0aW9uJykge1xuICAgICAgICBpZiAocmV0cnlDb3VudCA+IDApIHtcbiAgICAgICAgICByZXRyeUNvdW50LS07XG4gICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRlbGF5KSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVGhlIGxvZyBncm91cCBpcyBzdGlsbCBiZWluZyBjcmVhdGVkIGJ5IGFub3RoZXIgZXhlY3V0aW9uIGJ1dCB3ZSBhcmUgb3V0IG9mIHJldHJpZXNcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ091dCBvZiBhdHRlbXB0cyB0byBjcmVhdGUgYSBsb2dHcm91cCcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH0gd2hpbGUgKHRydWUpOyAvLyBleGl0IGhhcHBlbnMgb24gcmV0cnkgY291bnQgY2hlY2tcbn1cblxuLyoqXG4gKiBQdXRzIG9yIGRlbGV0ZXMgYSByZXRlbnRpb24gcG9saWN5IG9uIGEgbG9nIGdyb3VwLlxuICpcbiAqIEBwYXJhbSBsb2dHcm91cE5hbWUgdGhlIG5hbWUgb2YgdGhlIGxvZyBncm91cCB0byBjcmVhdGVcbiAqIEBwYXJhbSByZWdpb24gdGhlIHJlZ2lvbiBvZiB0aGUgbG9nIGdyb3VwXG4gKiBAcGFyYW0gb3B0aW9ucyBDbG91ZFdhdGNoIEFQSSBTREsgb3B0aW9ucy5cbiAqIEBwYXJhbSByZXRlbnRpb25JbkRheXMgdGhlIG51bWJlciBvZiBkYXlzIHRvIHJldGFpbiB0aGUgbG9nIGV2ZW50cyBpbiB0aGUgc3BlY2lmaWVkIGxvZyBncm91cC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2V0UmV0ZW50aW9uUG9saWN5KGxvZ0dyb3VwTmFtZTogc3RyaW5nLCByZWdpb24/OiBzdHJpbmcsIG9wdGlvbnM/OiBTZGtSZXRyeU9wdGlvbnMsIHJldGVudGlvbkluRGF5cz86IG51bWJlcikge1xuICAvLyBUaGUgc2FtZSBhcyBpbiBjcmVhdGVMb2dHcm91cFNhZmUoKSwgaGVyZSB3ZSBjb3VsZCBlbmQgdXAgd2l0aCB0aGUgcmFjZVxuICAvLyBjb25kaXRpb24gd2hlcmUgYSBsb2cgZ3JvdXAgaXMgZWl0aGVyIGFscmVhZHkgYmVpbmcgY3JlYXRlZCBvciBpdHMgcmV0ZW50aW9uXG4gIC8vIHBvbGljeSBpcyBiZWluZyB1cGRhdGVkLiBUaGlzIHdvdWxkIHJlc3VsdCBpbiBhbiBPcGVyYXRpb25BYm9ydGVkRXhjZXB0aW9uLFxuICAvLyB3aGljaCB3ZSB3aWxsIHRyeSB0byBjYXRjaCBhbmQgcmV0cnkgdGhlIGNvbW1hbmQgYSBudW1iZXIgb2YgdGltZXMgYmVmb3JlIGZhaWxpbmdcbiAgbGV0IHJldHJ5Q291bnQgPSBvcHRpb25zPy5tYXhSZXRyaWVzID09IHVuZGVmaW5lZCA/IDEwIDogb3B0aW9ucy5tYXhSZXRyaWVzO1xuICBjb25zdCBkZWxheSA9IG9wdGlvbnM/LnJldHJ5T3B0aW9ucz8uYmFzZSA9PSB1bmRlZmluZWQgPyAxMCA6IG9wdGlvbnMucmV0cnlPcHRpb25zLmJhc2U7XG4gIGRvIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY2xvdWR3YXRjaGxvZ3MgPSBuZXcgQVdTLkNsb3VkV2F0Y2hMb2dzKHsgYXBpVmVyc2lvbjogJzIwMTQtMDMtMjgnLCByZWdpb24sIC4uLm9wdGlvbnMgfSk7XG4gICAgICBpZiAoIXJldGVudGlvbkluRGF5cykge1xuICAgICAgICBhd2FpdCBjbG91ZHdhdGNobG9ncy5kZWxldGVSZXRlbnRpb25Qb2xpY3koeyBsb2dHcm91cE5hbWUgfSkucHJvbWlzZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgY2xvdWR3YXRjaGxvZ3MucHV0UmV0ZW50aW9uUG9saWN5KHsgbG9nR3JvdXBOYW1lLCByZXRlbnRpb25JbkRheXMgfSkucHJvbWlzZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvci5jb2RlID09PSAnT3BlcmF0aW9uQWJvcnRlZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgaWYgKHJldHJ5Q291bnQgPiAwKSB7XG4gICAgICAgICAgcmV0cnlDb3VudC0tO1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBkZWxheSkpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFRoZSBsb2cgZ3JvdXAgaXMgc3RpbGwgYmVpbmcgY3JlYXRlZCBieSBhbm90aGVyIGV4ZWN1dGlvbiBidXQgd2UgYXJlIG91dCBvZiByZXRyaWVzXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdPdXQgb2YgYXR0ZW1wdHMgdG8gY3JlYXRlIGEgbG9nR3JvdXAnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9IHdoaWxlICh0cnVlKTsgLy8gZXhpdCBoYXBwZW5zIG9uIHJldHJ5IGNvdW50IGNoZWNrXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBjb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dCkge1xuICB0cnkge1xuICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGV2ZW50KSk7XG5cbiAgICAvLyBUaGUgdGFyZ2V0IGxvZyBncm91cFxuICAgIGNvbnN0IGxvZ0dyb3VwTmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Mb2dHcm91cE5hbWU7XG5cbiAgICAvLyBUaGUgcmVnaW9uIG9mIHRoZSB0YXJnZXQgbG9nIGdyb3VwXG4gICAgY29uc3QgbG9nR3JvdXBSZWdpb24gPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuTG9nR3JvdXBSZWdpb247XG5cbiAgICAvLyBQYXJzZSB0byBBV1MgU0RLIHJldHJ5IG9wdGlvbnNcbiAgICBjb25zdCByZXRyeU9wdGlvbnMgPSBwYXJzZVJldHJ5T3B0aW9ucyhldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuU2RrUmV0cnkpO1xuXG4gICAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJyB8fCBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScpIHtcbiAgICAgIC8vIEFjdCBvbiB0aGUgdGFyZ2V0IGxvZyBncm91cFxuICAgICAgYXdhaXQgY3JlYXRlTG9nR3JvdXBTYWZlKGxvZ0dyb3VwTmFtZSwgbG9nR3JvdXBSZWdpb24sIHJldHJ5T3B0aW9ucyk7XG4gICAgICBhd2FpdCBzZXRSZXRlbnRpb25Qb2xpY3kobG9nR3JvdXBOYW1lLCBsb2dHcm91cFJlZ2lvbiwgcmV0cnlPcHRpb25zLCBwYXJzZUludChldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUmV0ZW50aW9uSW5EYXlzLCAxMCkpO1xuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIC8vIFNldCBhIHJldGVudGlvbiBwb2xpY3kgb2YgMSBkYXkgb24gdGhlIGxvZ3Mgb2YgdGhpcyB2ZXJ5IGZ1bmN0aW9uLlxuICAgICAgICAvLyBEdWUgdG8gdGhlIGFzeW5jIG5hdHVyZSBvZiB0aGUgbG9nIGdyb3VwIGNyZWF0aW9uLCB0aGUgbG9nIGdyb3VwIGZvciB0aGlzIGZ1bmN0aW9uIG1pZ2h0XG4gICAgICAgIC8vIHN0aWxsIGJlIG5vdCBjcmVhdGVkIHlldCBhdCB0aGlzIHBvaW50LiBUaGVyZWZvcmUgd2UgYXR0ZW1wdCB0byBjcmVhdGUgaXQuXG4gICAgICAgIC8vIEluIGNhc2UgaXQgaXMgYmVpbmcgY3JlYXRlZCwgY3JlYXRlTG9nR3JvdXBTYWZlIHdpbGwgaGFuZGxlIHRoZSBjb25mbGljdC5cbiAgICAgICAgY29uc3QgcmVnaW9uID0gcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTjtcbiAgICAgICAgYXdhaXQgY3JlYXRlTG9nR3JvdXBTYWZlKGAvYXdzL2xhbWJkYS8ke2NvbnRleHQuZnVuY3Rpb25OYW1lfWAsIHJlZ2lvbiwgcmV0cnlPcHRpb25zKTtcbiAgICAgICAgLy8gSWYgY3JlYXRlTG9nR3JvdXBTYWZlIGZhaWxzLCB0aGUgbG9nIGdyb3VwIGlzIG5vdCBjcmVhdGVkIGV2ZW4gYWZ0ZXIgbXVsdGlwbGUgYXR0ZW1wdHMuXG4gICAgICAgIC8vIEluIHRoaXMgY2FzZSB3ZSBoYXZlIG5vdGhpbmcgdG8gc2V0IHRoZSByZXRlbnRpb24gcG9saWN5IG9uIGJ1dCBhbiBleGNlcHRpb24gd2lsbCBza2lwXG4gICAgICAgIC8vIHRoZSBuZXh0IGxpbmUuXG4gICAgICAgIGF3YWl0IHNldFJldGVudGlvblBvbGljeShgL2F3cy9sYW1iZGEvJHtjb250ZXh0LmZ1bmN0aW9uTmFtZX1gLCByZWdpb24sIHJldHJ5T3B0aW9ucywgMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgcmVzcG9uZCgnU1VDQ0VTUycsICdPSycsIGxvZ0dyb3VwTmFtZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zb2xlLmxvZyhlKTtcblxuICAgIGF3YWl0IHJlc3BvbmQoJ0ZBSUxFRCcsIGUubWVzc2FnZSwgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkxvZ0dyb3VwTmFtZSk7XG4gIH1cblxuICBmdW5jdGlvbiByZXNwb25kKHJlc3BvbnNlU3RhdHVzOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nLCBwaHlzaWNhbFJlc291cmNlSWQ6IHN0cmluZykge1xuICAgIGNvbnN0IHJlc3BvbnNlQm9keSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIFN0YXR1czogcmVzcG9uc2VTdGF0dXMsXG4gICAgICBSZWFzb246IHJlYXNvbixcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgICAgRGF0YToge1xuICAgICAgICAvLyBBZGQgbG9nIGdyb3VwIG5hbWUgYXMgcGFydCBvZiB0aGUgcmVzcG9uc2Ugc28gdGhhdCBpdCdzIGF2YWlsYWJsZSB2aWEgRm46OkdldEF0dFxuICAgICAgICBMb2dHcm91cE5hbWU6IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Mb2dHcm91cE5hbWUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coJ1Jlc3BvbmRpbmcnLCByZXNwb25zZUJvZHkpO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCBwYXJzZWRVcmwgPSByZXF1aXJlKCd1cmwnKS5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgICAgcGF0aDogcGFyc2VkVXJsLnBhdGgsXG4gICAgICBtZXRob2Q6ICdQVVQnLFxuICAgICAgaGVhZGVyczogeyAnY29udGVudC10eXBlJzogJycsICdjb250ZW50LWxlbmd0aCc6IHJlc3BvbnNlQm9keS5sZW5ndGggfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1aXJlKCdodHRwcycpLnJlcXVlc3QocmVxdWVzdE9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VSZXRyeU9wdGlvbnMocmF3T3B0aW9uczogYW55KTogU2RrUmV0cnlPcHRpb25zIHtcbiAgICBjb25zdCByZXRyeU9wdGlvbnM6IFNka1JldHJ5T3B0aW9ucyA9IHt9O1xuICAgIGlmIChyYXdPcHRpb25zKSB7XG4gICAgICBpZiAocmF3T3B0aW9ucy5tYXhSZXRyaWVzKSB7XG4gICAgICAgIHJldHJ5T3B0aW9ucy5tYXhSZXRyaWVzID0gcGFyc2VJbnQocmF3T3B0aW9ucy5tYXhSZXRyaWVzLCAxMCk7XG4gICAgICB9XG4gICAgICBpZiAocmF3T3B0aW9ucy5iYXNlKSB7XG4gICAgICAgIHJldHJ5T3B0aW9ucy5yZXRyeU9wdGlvbnMgPSB7XG4gICAgICAgICAgYmFzZTogcGFyc2VJbnQocmF3T3B0aW9ucy5iYXNlLCAxMCksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXRyeU9wdGlvbnM7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/lib/replica-handler/index.ts b/packages/@aws-cdk/aws-dynamodb/lib/replica-handler/index.ts index 36e12cc113ffe..bd90499a1732b 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/replica-handler/index.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/replica-handler/index.ts @@ -3,7 +3,7 @@ import type { IsCompleteRequest, IsCompleteResponse, OnEventRequest, OnEventResp import { DynamoDB } from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies export async function onEventHandler(event: OnEventRequest): Promise { - console.log('Event: %j', event); + console.log('Event: %j', { ...event, ResponseURL: '...' }); const dynamodb = new DynamoDB(); @@ -50,7 +50,7 @@ export async function onEventHandler(event: OnEventRequest): Promise { - console.log('Event: %j', event); + console.log('Event: %j', { ...event, ResponseURL: '...' }); const dynamodb = new DynamoDB(); diff --git a/packages/@aws-cdk/aws-dynamodb/test/global-replicas-provisioned.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js b/packages/@aws-cdk/aws-dynamodb/test/global-replicas-provisioned.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js index 6e55fd1bd6951..bc53d9780919c 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/global-replicas-provisioned.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js +++ b/packages/@aws-cdk/aws-dynamodb/test/global-replicas-provisioned.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js @@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.isCompleteHandler = exports.onEventHandler = void 0; const aws_sdk_1 = require("aws-sdk"); // eslint-disable-line import/no-extraneous-dependencies async function onEventHandler(event) { - var _a, _b; console.log('Event: %j', event); const dynamodb = new aws_sdk_1.DynamoDB(); const tableName = event.ResourceProperties.TableName; @@ -23,7 +22,7 @@ async function onEventHandler(event) { TableName: tableName, }).promise(); console.log('Describe table: %j', describeTableResult); - const replicaExists = (_b = (_a = describeTableResult.Table) === null || _a === void 0 ? void 0 : _a.Replicas) === null || _b === void 0 ? void 0 : _b.some(replica => replica.RegionName === region); + const replicaExists = describeTableResult.Table?.Replicas?.some(replica => replica.RegionName === region); updateTableAction = replicaExists ? undefined : 'Create'; } if (updateTableAction) { @@ -48,17 +47,16 @@ async function onEventHandler(event) { } exports.onEventHandler = onEventHandler; async function isCompleteHandler(event) { - var _a, _b, _c; console.log('Event: %j', event); const dynamodb = new aws_sdk_1.DynamoDB(); const data = await dynamodb.describeTable({ TableName: event.ResourceProperties.TableName, }).promise(); console.log('Describe table: %j', data); - const tableActive = ((_a = data.Table) === null || _a === void 0 ? void 0 : _a.TableStatus) === 'ACTIVE'; - const replicas = (_c = (_b = data.Table) === null || _b === void 0 ? void 0 : _b.Replicas) !== null && _c !== void 0 ? _c : []; + const tableActive = data.Table?.TableStatus === 'ACTIVE'; + const replicas = data.Table?.Replicas ?? []; const regionReplica = replicas.find(r => r.RegionName === event.ResourceProperties.Region); - const replicaActive = (regionReplica === null || regionReplica === void 0 ? void 0 : regionReplica.ReplicaStatus) === 'ACTIVE'; + const replicaActive = regionReplica?.ReplicaStatus === 'ACTIVE'; const skipReplicationCompletedWait = event.ResourceProperties.SkipReplicationCompletedWait === 'true'; switch (event.RequestType) { case 'Create': @@ -71,4 +69,4 @@ async function isCompleteHandler(event) { } } exports.isCompleteHandler = isCompleteHandler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxxQ0FBbUMsQ0FBQyx3REFBd0Q7QUFFckYsS0FBSyxVQUFVLGNBQWMsQ0FBQyxLQUFxQjs7SUFDeEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFaEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxrQkFBUSxFQUFFLENBQUM7SUFFaEMsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQztJQUNyRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDO0lBRS9DLElBQUksaUJBQTZELENBQUM7SUFDbEUsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUNwRSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO0tBQ3ZDO1NBQU0sRUFBRSxTQUFTO1FBQ2hCLGtEQUFrRDtRQUNsRCx1RkFBdUY7UUFDdkYsb0hBQW9IO1FBQ3BILDBFQUEwRTtRQUMxRSxpRkFBaUY7UUFDakYsNkdBQTZHO1FBQzdHLE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxRQUFRLENBQUMsYUFBYSxDQUFDO1lBQ3ZELFNBQVMsRUFBRSxTQUFTO1NBQ3JCLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUN2RCxNQUFNLGFBQWEsZUFBRyxtQkFBbUIsQ0FBQyxLQUFLLDBDQUFFLFFBQVEsMENBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxNQUFNLENBQUMsQ0FBQztRQUMxRyxpQkFBaUIsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0tBQzFEO0lBRUQsSUFBSSxpQkFBaUIsRUFBRTtRQUNyQixNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDdEMsU0FBUyxFQUFFLFNBQVM7WUFDcEIsY0FBYyxFQUFFO2dCQUNkO29CQUNFLENBQUMsaUJBQWlCLENBQUMsRUFBRTt3QkFDbkIsVUFBVSxFQUFFLE1BQU07cUJBQ25CO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3ZDO1NBQU07UUFDTCxPQUFPLENBQUMsR0FBRyxDQUFDLDhEQUE4RCxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQ3JGO0lBRUQsT0FBTyxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVE7UUFDckUsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxTQUFTLElBQUksTUFBTSxFQUFFLEVBQUU7UUFDbEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNULENBQUM7QUE3Q0Qsd0NBNkNDO0FBRU0sS0FBSyxVQUFVLGlCQUFpQixDQUFDLEtBQXdCOztJQUM5RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVoQyxNQUFNLFFBQVEsR0FBRyxJQUFJLGtCQUFRLEVBQUUsQ0FBQztJQUVoQyxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxhQUFhLENBQUM7UUFDeEMsU0FBUyxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTO0tBQzlDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFeEMsTUFBTSxXQUFXLEdBQUcsT0FBQSxJQUFJLENBQUMsS0FBSywwQ0FBRSxXQUFXLE1BQUssUUFBUSxDQUFDO0lBQ3pELE1BQU0sUUFBUSxlQUFHLElBQUksQ0FBQyxLQUFLLDBDQUFFLFFBQVEsbUNBQUksRUFBRSxDQUFDO0lBQzVDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxLQUFLLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzRixNQUFNLGFBQWEsR0FBRyxDQUFBLGFBQWEsYUFBYixhQUFhLHVCQUFiLGFBQWEsQ0FBRSxhQUFhLE1BQUssUUFBUSxDQUFDO0lBQ2hFLE1BQU0sNEJBQTRCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLDRCQUE0QixLQUFLLE1BQU0sQ0FBQztJQUV0RyxRQUFRLEtBQUssQ0FBQyxXQUFXLEVBQUU7UUFDekIsS0FBSyxRQUFRLENBQUM7UUFDZCxLQUFLLFFBQVE7WUFDWCw4Q0FBOEM7WUFDOUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLElBQUksQ0FBQyxhQUFhLElBQUksNEJBQTRCLENBQUMsRUFBRSxDQUFDO1FBQ3hGLEtBQUssUUFBUTtZQUNYLGdDQUFnQztZQUNoQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsSUFBSSxhQUFhLEtBQUssU0FBUyxFQUFFLENBQUM7S0FDckU7QUFDSCxDQUFDO0FBekJELDhDQXlCQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbmltcG9ydCB0eXBlIHsgSXNDb21wbGV0ZVJlcXVlc3QsIElzQ29tcGxldGVSZXNwb25zZSwgT25FdmVudFJlcXVlc3QsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG5pbXBvcnQgeyBEeW5hbW9EQiB9IGZyb20gJ2F3cy1zZGsnOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb25FdmVudEhhbmRsZXIoZXZlbnQ6IE9uRXZlbnRSZXF1ZXN0KTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgY29uc29sZS5sb2coJ0V2ZW50OiAlaicsIGV2ZW50KTtcblxuICBjb25zdCBkeW5hbW9kYiA9IG5ldyBEeW5hbW9EQigpO1xuXG4gIGNvbnN0IHRhYmxlTmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5UYWJsZU5hbWU7XG4gIGNvbnN0IHJlZ2lvbiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5SZWdpb247XG5cbiAgbGV0IHVwZGF0ZVRhYmxlQWN0aW9uOiAnQ3JlYXRlJyB8ICdVcGRhdGUnIHwgJ0RlbGV0ZScgfCB1bmRlZmluZWQ7XG4gIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScgfHwgZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnKSB7XG4gICAgdXBkYXRlVGFibGVBY3Rpb24gPSBldmVudC5SZXF1ZXN0VHlwZTtcbiAgfSBlbHNlIHsgLy8gVXBkYXRlXG4gICAgLy8gVGhlcmUgYXJlIHR3byBjYXNlcyB3aGVyZSBhbiBVcGRhdGUgY2FuIGhhcHBlbjpcbiAgICAvLyAxLiBBIHRhYmxlIHJlcGxhY2VtZW50LiBJbiB0aGF0IGNhc2UsIHdlIG5lZWQgdG8gY3JlYXRlIHRoZSByZXBsaWNhIGluIHRoZSBuZXcgVGFibGVcbiAgICAvLyAodGhlIHJlcGxpY2EgZm9yIHRoZSBcIm9sZFwiIFRhYmxlIHdpbGwgYmUgZGVsZXRlZCB3aGVuIENGTiBpc3N1ZXMgYSBEZWxldGUgZXZlbnQgb24gdGhlIG9sZCBwaHlzaWNhbCByZXNvdXJjZSBpZCkuXG4gICAgLy8gMi4gQSBjdXN0b21lciBoYXMgY2hhbmdlZCBvbmUgb2YgdGhlIHByb3BlcnRpZXMgb2YgdGhlIEN1c3RvbSBSZXNvdXJjZSxcbiAgICAvLyBsaWtlICd3YWl0Rm9yUmVwbGljYXRpb25Ub0ZpbmlzaCcuIEluIHRoYXQgY2FzZSwgd2UgZG9uJ3QgaGF2ZSB0byBkbyBhbnl0aGluZy5cbiAgICAvLyBUbyBkaWZmZXJlbnRpYXRlIHRoZSB0d28gY2FzZXMsIHdlIG1ha2UgYW4gQVBJIGNhbGwgdG8gRHluYW1vREIgdG8gY2hlY2sgd2hldGhlciBhIHJlcGxpY2EgYWxyZWFkeSBleGlzdHMuXG4gICAgY29uc3QgZGVzY3JpYmVUYWJsZVJlc3VsdCA9IGF3YWl0IGR5bmFtb2RiLmRlc2NyaWJlVGFibGUoe1xuICAgICAgVGFibGVOYW1lOiB0YWJsZU5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIGNvbnNvbGUubG9nKCdEZXNjcmliZSB0YWJsZTogJWonLCBkZXNjcmliZVRhYmxlUmVzdWx0KTtcbiAgICBjb25zdCByZXBsaWNhRXhpc3RzID0gZGVzY3JpYmVUYWJsZVJlc3VsdC5UYWJsZT8uUmVwbGljYXM/LnNvbWUocmVwbGljYSA9PiByZXBsaWNhLlJlZ2lvbk5hbWUgPT09IHJlZ2lvbik7XG4gICAgdXBkYXRlVGFibGVBY3Rpb24gPSByZXBsaWNhRXhpc3RzID8gdW5kZWZpbmVkIDogJ0NyZWF0ZSc7XG4gIH1cblxuICBpZiAodXBkYXRlVGFibGVBY3Rpb24pIHtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgZHluYW1vZGIudXBkYXRlVGFibGUoe1xuICAgICAgVGFibGVOYW1lOiB0YWJsZU5hbWUsXG4gICAgICBSZXBsaWNhVXBkYXRlczogW1xuICAgICAgICB7XG4gICAgICAgICAgW3VwZGF0ZVRhYmxlQWN0aW9uXToge1xuICAgICAgICAgICAgUmVnaW9uTmFtZTogcmVnaW9uLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pLnByb21pc2UoKTtcbiAgICBjb25zb2xlLmxvZygnVXBkYXRlIHRhYmxlOiAlaicsIGRhdGEpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUubG9nKFwiU2tpcHBpbmcgdXBkYXRpbmcgVGFibGUsIGFzIGEgcmVwbGljYSBpbiAnJXMnIGFscmVhZHkgZXhpc3RzXCIsIHJlZ2lvbik7XG4gIH1cblxuICByZXR1cm4gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnIHx8IGV2ZW50LlJlcXVlc3RUeXBlID09PSAnVXBkYXRlJ1xuICAgID8geyBQaHlzaWNhbFJlc291cmNlSWQ6IGAke3RhYmxlTmFtZX0tJHtyZWdpb259YCB9XG4gICAgOiB7fTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzQ29tcGxldGVIYW5kbGVyKGV2ZW50OiBJc0NvbXBsZXRlUmVxdWVzdCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gIGNvbnNvbGUubG9nKCdFdmVudDogJWonLCBldmVudCk7XG5cbiAgY29uc3QgZHluYW1vZGIgPSBuZXcgRHluYW1vREIoKTtcblxuICBjb25zdCBkYXRhID0gYXdhaXQgZHluYW1vZGIuZGVzY3JpYmVUYWJsZSh7XG4gICAgVGFibGVOYW1lOiBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVGFibGVOYW1lLFxuICB9KS5wcm9taXNlKCk7XG4gIGNvbnNvbGUubG9nKCdEZXNjcmliZSB0YWJsZTogJWonLCBkYXRhKTtcblxuICBjb25zdCB0YWJsZUFjdGl2ZSA9IGRhdGEuVGFibGU/LlRhYmxlU3RhdHVzID09PSAnQUNUSVZFJztcbiAgY29uc3QgcmVwbGljYXMgPSBkYXRhLlRhYmxlPy5SZXBsaWNhcyA/PyBbXTtcbiAgY29uc3QgcmVnaW9uUmVwbGljYSA9IHJlcGxpY2FzLmZpbmQociA9PiByLlJlZ2lvbk5hbWUgPT09IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5SZWdpb24pO1xuICBjb25zdCByZXBsaWNhQWN0aXZlID0gcmVnaW9uUmVwbGljYT8uUmVwbGljYVN0YXR1cyA9PT0gJ0FDVElWRSc7XG4gIGNvbnN0IHNraXBSZXBsaWNhdGlvbkNvbXBsZXRlZFdhaXQgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuU2tpcFJlcGxpY2F0aW9uQ29tcGxldGVkV2FpdCA9PT0gJ3RydWUnO1xuXG4gIHN3aXRjaCAoZXZlbnQuUmVxdWVzdFR5cGUpIHtcbiAgICBjYXNlICdDcmVhdGUnOlxuICAgIGNhc2UgJ1VwZGF0ZSc6XG4gICAgICAvLyBDb21wbGV0ZSB3aGVuIHJlcGxpY2EgaXMgcmVwb3J0ZWQgYXMgQUNUSVZFXG4gICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0YWJsZUFjdGl2ZSAmJiAocmVwbGljYUFjdGl2ZSB8fCBza2lwUmVwbGljYXRpb25Db21wbGV0ZWRXYWl0KSB9O1xuICAgIGNhc2UgJ0RlbGV0ZSc6XG4gICAgICAvLyBDb21wbGV0ZSB3aGVuIHJlcGxpY2EgaXMgZ29uZVxuICAgICAgcmV0dXJuIHsgSXNDb21wbGV0ZTogdGFibGVBY3RpdmUgJiYgcmVnaW9uUmVwbGljYSA9PT0gdW5kZWZpbmVkIH07XG4gIH1cbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxxQ0FBbUMsQ0FBQyx3REFBd0Q7QUFFckYsS0FBSyxVQUFVLGNBQWMsQ0FBQyxLQUFxQjtJQUN4RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVoQyxNQUFNLFFBQVEsR0FBRyxJQUFJLGtCQUFRLEVBQUUsQ0FBQztJQUVoQyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDO0lBQ3JELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUM7SUFFL0MsSUFBSSxpQkFBNkQsQ0FBQztJQUNsRSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFO1FBQ3BFLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7S0FDdkM7U0FBTSxFQUFFLFNBQVM7UUFDaEIsa0RBQWtEO1FBQ2xELHVGQUF1RjtRQUN2RixvSEFBb0g7UUFDcEgsMEVBQTBFO1FBQzFFLGlGQUFpRjtRQUNqRiw2R0FBNkc7UUFDN0csTUFBTSxtQkFBbUIsR0FBRyxNQUFNLFFBQVEsQ0FBQyxhQUFhLENBQUM7WUFDdkQsU0FBUyxFQUFFLFNBQVM7U0FDckIsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxNQUFNLENBQUMsQ0FBQztRQUMxRyxpQkFBaUIsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0tBQzFEO0lBRUQsSUFBSSxpQkFBaUIsRUFBRTtRQUNyQixNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDdEMsU0FBUyxFQUFFLFNBQVM7WUFDcEIsY0FBYyxFQUFFO2dCQUNkO29CQUNFLENBQUMsaUJBQWlCLENBQUMsRUFBRTt3QkFDbkIsVUFBVSxFQUFFLE1BQU07cUJBQ25CO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3ZDO1NBQU07UUFDTCxPQUFPLENBQUMsR0FBRyxDQUFDLDhEQUE4RCxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQ3JGO0lBRUQsT0FBTyxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVE7UUFDckUsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxTQUFTLElBQUksTUFBTSxFQUFFLEVBQUU7UUFDbEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNULENBQUM7QUE3Q0Qsd0NBNkNDO0FBRU0sS0FBSyxVQUFVLGlCQUFpQixDQUFDLEtBQXdCO0lBQzlELE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWhDLE1BQU0sUUFBUSxHQUFHLElBQUksa0JBQVEsRUFBRSxDQUFDO0lBRWhDLE1BQU0sSUFBSSxHQUFHLE1BQU0sUUFBUSxDQUFDLGFBQWEsQ0FBQztRQUN4QyxTQUFTLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFNBQVM7S0FDOUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsS0FBSyxRQUFRLENBQUM7SUFDekQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLElBQUksRUFBRSxDQUFDO0lBQzVDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxLQUFLLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzRixNQUFNLGFBQWEsR0FBRyxhQUFhLEVBQUUsYUFBYSxLQUFLLFFBQVEsQ0FBQztJQUNoRSxNQUFNLDRCQUE0QixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyw0QkFBNEIsS0FBSyxNQUFNLENBQUM7SUFFdEcsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3pCLEtBQUssUUFBUSxDQUFDO1FBQ2QsS0FBSyxRQUFRO1lBQ1gsOENBQThDO1lBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxJQUFJLENBQUMsYUFBYSxJQUFJLDRCQUE0QixDQUFDLEVBQUUsQ0FBQztRQUN4RixLQUFLLFFBQVE7WUFDWCxnQ0FBZ0M7WUFDaEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLElBQUksYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO0tBQ3JFO0FBQ0gsQ0FBQztBQXpCRCw4Q0F5QkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgdHlwZSB7IElzQ29tcGxldGVSZXF1ZXN0LCBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXF1ZXN0LCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuaW1wb3J0IHsgRHluYW1vREIgfSBmcm9tICdhd3Mtc2RrJzsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uRXZlbnRIYW5kbGVyKGV2ZW50OiBPbkV2ZW50UmVxdWVzdCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gIGNvbnNvbGUubG9nKCdFdmVudDogJWonLCBldmVudCk7XG5cbiAgY29uc3QgZHluYW1vZGIgPSBuZXcgRHluYW1vREIoKTtcblxuICBjb25zdCB0YWJsZU5hbWUgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVGFibGVOYW1lO1xuICBjb25zdCByZWdpb24gPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUmVnaW9uO1xuXG4gIGxldCB1cGRhdGVUYWJsZUFjdGlvbjogJ0NyZWF0ZScgfCAnVXBkYXRlJyB8ICdEZWxldGUnIHwgdW5kZWZpbmVkO1xuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnIHx8IGV2ZW50LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJykge1xuICAgIHVwZGF0ZVRhYmxlQWN0aW9uID0gZXZlbnQuUmVxdWVzdFR5cGU7XG4gIH0gZWxzZSB7IC8vIFVwZGF0ZVxuICAgIC8vIFRoZXJlIGFyZSB0d28gY2FzZXMgd2hlcmUgYW4gVXBkYXRlIGNhbiBoYXBwZW46XG4gICAgLy8gMS4gQSB0YWJsZSByZXBsYWNlbWVudC4gSW4gdGhhdCBjYXNlLCB3ZSBuZWVkIHRvIGNyZWF0ZSB0aGUgcmVwbGljYSBpbiB0aGUgbmV3IFRhYmxlXG4gICAgLy8gKHRoZSByZXBsaWNhIGZvciB0aGUgXCJvbGRcIiBUYWJsZSB3aWxsIGJlIGRlbGV0ZWQgd2hlbiBDRk4gaXNzdWVzIGEgRGVsZXRlIGV2ZW50IG9uIHRoZSBvbGQgcGh5c2ljYWwgcmVzb3VyY2UgaWQpLlxuICAgIC8vIDIuIEEgY3VzdG9tZXIgaGFzIGNoYW5nZWQgb25lIG9mIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBDdXN0b20gUmVzb3VyY2UsXG4gICAgLy8gbGlrZSAnd2FpdEZvclJlcGxpY2F0aW9uVG9GaW5pc2gnLiBJbiB0aGF0IGNhc2UsIHdlIGRvbid0IGhhdmUgdG8gZG8gYW55dGhpbmcuXG4gICAgLy8gVG8gZGlmZmVyZW50aWF0ZSB0aGUgdHdvIGNhc2VzLCB3ZSBtYWtlIGFuIEFQSSBjYWxsIHRvIER5bmFtb0RCIHRvIGNoZWNrIHdoZXRoZXIgYSByZXBsaWNhIGFscmVhZHkgZXhpc3RzLlxuICAgIGNvbnN0IGRlc2NyaWJlVGFibGVSZXN1bHQgPSBhd2FpdCBkeW5hbW9kYi5kZXNjcmliZVRhYmxlKHtcbiAgICAgIFRhYmxlTmFtZTogdGFibGVOYW1lLFxuICAgIH0pLnByb21pc2UoKTtcbiAgICBjb25zb2xlLmxvZygnRGVzY3JpYmUgdGFibGU6ICVqJywgZGVzY3JpYmVUYWJsZVJlc3VsdCk7XG4gICAgY29uc3QgcmVwbGljYUV4aXN0cyA9IGRlc2NyaWJlVGFibGVSZXN1bHQuVGFibGU/LlJlcGxpY2FzPy5zb21lKHJlcGxpY2EgPT4gcmVwbGljYS5SZWdpb25OYW1lID09PSByZWdpb24pO1xuICAgIHVwZGF0ZVRhYmxlQWN0aW9uID0gcmVwbGljYUV4aXN0cyA/IHVuZGVmaW5lZCA6ICdDcmVhdGUnO1xuICB9XG5cbiAgaWYgKHVwZGF0ZVRhYmxlQWN0aW9uKSB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IGR5bmFtb2RiLnVwZGF0ZVRhYmxlKHtcbiAgICAgIFRhYmxlTmFtZTogdGFibGVOYW1lLFxuICAgICAgUmVwbGljYVVwZGF0ZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIFt1cGRhdGVUYWJsZUFjdGlvbl06IHtcbiAgICAgICAgICAgIFJlZ2lvbk5hbWU6IHJlZ2lvbixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KS5wcm9taXNlKCk7XG4gICAgY29uc29sZS5sb2coJ1VwZGF0ZSB0YWJsZTogJWonLCBkYXRhKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZyhcIlNraXBwaW5nIHVwZGF0aW5nIFRhYmxlLCBhcyBhIHJlcGxpY2EgaW4gJyVzJyBhbHJlYWR5IGV4aXN0c1wiLCByZWdpb24pO1xuICB9XG5cbiAgcmV0dXJuIGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJyB8fCBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZSdcbiAgICA/IHsgUGh5c2ljYWxSZXNvdXJjZUlkOiBgJHt0YWJsZU5hbWV9LSR7cmVnaW9ufWAgfVxuICAgIDoge307XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpc0NvbXBsZXRlSGFuZGxlcihldmVudDogSXNDb21wbGV0ZVJlcXVlc3QpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICBjb25zb2xlLmxvZygnRXZlbnQ6ICVqJywgZXZlbnQpO1xuXG4gIGNvbnN0IGR5bmFtb2RiID0gbmV3IER5bmFtb0RCKCk7XG5cbiAgY29uc3QgZGF0YSA9IGF3YWl0IGR5bmFtb2RiLmRlc2NyaWJlVGFibGUoe1xuICAgIFRhYmxlTmFtZTogZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlRhYmxlTmFtZSxcbiAgfSkucHJvbWlzZSgpO1xuICBjb25zb2xlLmxvZygnRGVzY3JpYmUgdGFibGU6ICVqJywgZGF0YSk7XG5cbiAgY29uc3QgdGFibGVBY3RpdmUgPSBkYXRhLlRhYmxlPy5UYWJsZVN0YXR1cyA9PT0gJ0FDVElWRSc7XG4gIGNvbnN0IHJlcGxpY2FzID0gZGF0YS5UYWJsZT8uUmVwbGljYXMgPz8gW107XG4gIGNvbnN0IHJlZ2lvblJlcGxpY2EgPSByZXBsaWNhcy5maW5kKHIgPT4gci5SZWdpb25OYW1lID09PSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUmVnaW9uKTtcbiAgY29uc3QgcmVwbGljYUFjdGl2ZSA9IHJlZ2lvblJlcGxpY2E/LlJlcGxpY2FTdGF0dXMgPT09ICdBQ1RJVkUnO1xuICBjb25zdCBza2lwUmVwbGljYXRpb25Db21wbGV0ZWRXYWl0ID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlNraXBSZXBsaWNhdGlvbkNvbXBsZXRlZFdhaXQgPT09ICd0cnVlJztcblxuICBzd2l0Y2ggKGV2ZW50LlJlcXVlc3RUeXBlKSB7XG4gICAgY2FzZSAnQ3JlYXRlJzpcbiAgICBjYXNlICdVcGRhdGUnOlxuICAgICAgLy8gQ29tcGxldGUgd2hlbiByZXBsaWNhIGlzIHJlcG9ydGVkIGFzIEFDVElWRVxuICAgICAgcmV0dXJuIHsgSXNDb21wbGV0ZTogdGFibGVBY3RpdmUgJiYgKHJlcGxpY2FBY3RpdmUgfHwgc2tpcFJlcGxpY2F0aW9uQ29tcGxldGVkV2FpdCkgfTtcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgLy8gQ29tcGxldGUgd2hlbiByZXBsaWNhIGlzIGdvbmVcbiAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRhYmxlQWN0aXZlICYmIHJlZ2lvblJlcGxpY2EgPT09IHVuZGVmaW5lZCB9O1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/test/global.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js b/packages/@aws-cdk/aws-dynamodb/test/global.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js index 6e55fd1bd6951..bc53d9780919c 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/global.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js +++ b/packages/@aws-cdk/aws-dynamodb/test/global.integ.snapshot/asset.5d88959fad6bed204d22b24bf15826b8c7591c586a60a313e54f1948d9cdf80f/index.js @@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.isCompleteHandler = exports.onEventHandler = void 0; const aws_sdk_1 = require("aws-sdk"); // eslint-disable-line import/no-extraneous-dependencies async function onEventHandler(event) { - var _a, _b; console.log('Event: %j', event); const dynamodb = new aws_sdk_1.DynamoDB(); const tableName = event.ResourceProperties.TableName; @@ -23,7 +22,7 @@ async function onEventHandler(event) { TableName: tableName, }).promise(); console.log('Describe table: %j', describeTableResult); - const replicaExists = (_b = (_a = describeTableResult.Table) === null || _a === void 0 ? void 0 : _a.Replicas) === null || _b === void 0 ? void 0 : _b.some(replica => replica.RegionName === region); + const replicaExists = describeTableResult.Table?.Replicas?.some(replica => replica.RegionName === region); updateTableAction = replicaExists ? undefined : 'Create'; } if (updateTableAction) { @@ -48,17 +47,16 @@ async function onEventHandler(event) { } exports.onEventHandler = onEventHandler; async function isCompleteHandler(event) { - var _a, _b, _c; console.log('Event: %j', event); const dynamodb = new aws_sdk_1.DynamoDB(); const data = await dynamodb.describeTable({ TableName: event.ResourceProperties.TableName, }).promise(); console.log('Describe table: %j', data); - const tableActive = ((_a = data.Table) === null || _a === void 0 ? void 0 : _a.TableStatus) === 'ACTIVE'; - const replicas = (_c = (_b = data.Table) === null || _b === void 0 ? void 0 : _b.Replicas) !== null && _c !== void 0 ? _c : []; + const tableActive = data.Table?.TableStatus === 'ACTIVE'; + const replicas = data.Table?.Replicas ?? []; const regionReplica = replicas.find(r => r.RegionName === event.ResourceProperties.Region); - const replicaActive = (regionReplica === null || regionReplica === void 0 ? void 0 : regionReplica.ReplicaStatus) === 'ACTIVE'; + const replicaActive = regionReplica?.ReplicaStatus === 'ACTIVE'; const skipReplicationCompletedWait = event.ResourceProperties.SkipReplicationCompletedWait === 'true'; switch (event.RequestType) { case 'Create': @@ -71,4 +69,4 @@ async function isCompleteHandler(event) { } } exports.isCompleteHandler = isCompleteHandler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxxQ0FBbUMsQ0FBQyx3REFBd0Q7QUFFckYsS0FBSyxVQUFVLGNBQWMsQ0FBQyxLQUFxQjs7SUFDeEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFaEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxrQkFBUSxFQUFFLENBQUM7SUFFaEMsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQztJQUNyRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDO0lBRS9DLElBQUksaUJBQTZELENBQUM7SUFDbEUsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUNwRSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO0tBQ3ZDO1NBQU0sRUFBRSxTQUFTO1FBQ2hCLGtEQUFrRDtRQUNsRCx1RkFBdUY7UUFDdkYsb0hBQW9IO1FBQ3BILDBFQUEwRTtRQUMxRSxpRkFBaUY7UUFDakYsNkdBQTZHO1FBQzdHLE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxRQUFRLENBQUMsYUFBYSxDQUFDO1lBQ3ZELFNBQVMsRUFBRSxTQUFTO1NBQ3JCLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUN2RCxNQUFNLGFBQWEsZUFBRyxtQkFBbUIsQ0FBQyxLQUFLLDBDQUFFLFFBQVEsMENBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxNQUFNLENBQUMsQ0FBQztRQUMxRyxpQkFBaUIsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0tBQzFEO0lBRUQsSUFBSSxpQkFBaUIsRUFBRTtRQUNyQixNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDdEMsU0FBUyxFQUFFLFNBQVM7WUFDcEIsY0FBYyxFQUFFO2dCQUNkO29CQUNFLENBQUMsaUJBQWlCLENBQUMsRUFBRTt3QkFDbkIsVUFBVSxFQUFFLE1BQU07cUJBQ25CO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3ZDO1NBQU07UUFDTCxPQUFPLENBQUMsR0FBRyxDQUFDLDhEQUE4RCxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQ3JGO0lBRUQsT0FBTyxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVE7UUFDckUsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxTQUFTLElBQUksTUFBTSxFQUFFLEVBQUU7UUFDbEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNULENBQUM7QUE3Q0Qsd0NBNkNDO0FBRU0sS0FBSyxVQUFVLGlCQUFpQixDQUFDLEtBQXdCOztJQUM5RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVoQyxNQUFNLFFBQVEsR0FBRyxJQUFJLGtCQUFRLEVBQUUsQ0FBQztJQUVoQyxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxhQUFhLENBQUM7UUFDeEMsU0FBUyxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTO0tBQzlDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFeEMsTUFBTSxXQUFXLEdBQUcsT0FBQSxJQUFJLENBQUMsS0FBSywwQ0FBRSxXQUFXLE1BQUssUUFBUSxDQUFDO0lBQ3pELE1BQU0sUUFBUSxlQUFHLElBQUksQ0FBQyxLQUFLLDBDQUFFLFFBQVEsbUNBQUksRUFBRSxDQUFDO0lBQzVDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxLQUFLLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzRixNQUFNLGFBQWEsR0FBRyxDQUFBLGFBQWEsYUFBYixhQUFhLHVCQUFiLGFBQWEsQ0FBRSxhQUFhLE1BQUssUUFBUSxDQUFDO0lBQ2hFLE1BQU0sNEJBQTRCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLDRCQUE0QixLQUFLLE1BQU0sQ0FBQztJQUV0RyxRQUFRLEtBQUssQ0FBQyxXQUFXLEVBQUU7UUFDekIsS0FBSyxRQUFRLENBQUM7UUFDZCxLQUFLLFFBQVE7WUFDWCw4Q0FBOEM7WUFDOUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLElBQUksQ0FBQyxhQUFhLElBQUksNEJBQTRCLENBQUMsRUFBRSxDQUFDO1FBQ3hGLEtBQUssUUFBUTtZQUNYLGdDQUFnQztZQUNoQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsSUFBSSxhQUFhLEtBQUssU0FBUyxFQUFFLENBQUM7S0FDckU7QUFDSCxDQUFDO0FBekJELDhDQXlCQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbmltcG9ydCB0eXBlIHsgSXNDb21wbGV0ZVJlcXVlc3QsIElzQ29tcGxldGVSZXNwb25zZSwgT25FdmVudFJlcXVlc3QsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG5pbXBvcnQgeyBEeW5hbW9EQiB9IGZyb20gJ2F3cy1zZGsnOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb25FdmVudEhhbmRsZXIoZXZlbnQ6IE9uRXZlbnRSZXF1ZXN0KTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgY29uc29sZS5sb2coJ0V2ZW50OiAlaicsIGV2ZW50KTtcblxuICBjb25zdCBkeW5hbW9kYiA9IG5ldyBEeW5hbW9EQigpO1xuXG4gIGNvbnN0IHRhYmxlTmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5UYWJsZU5hbWU7XG4gIGNvbnN0IHJlZ2lvbiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5SZWdpb247XG5cbiAgbGV0IHVwZGF0ZVRhYmxlQWN0aW9uOiAnQ3JlYXRlJyB8ICdVcGRhdGUnIHwgJ0RlbGV0ZScgfCB1bmRlZmluZWQ7XG4gIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScgfHwgZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnKSB7XG4gICAgdXBkYXRlVGFibGVBY3Rpb24gPSBldmVudC5SZXF1ZXN0VHlwZTtcbiAgfSBlbHNlIHsgLy8gVXBkYXRlXG4gICAgLy8gVGhlcmUgYXJlIHR3byBjYXNlcyB3aGVyZSBhbiBVcGRhdGUgY2FuIGhhcHBlbjpcbiAgICAvLyAxLiBBIHRhYmxlIHJlcGxhY2VtZW50LiBJbiB0aGF0IGNhc2UsIHdlIG5lZWQgdG8gY3JlYXRlIHRoZSByZXBsaWNhIGluIHRoZSBuZXcgVGFibGVcbiAgICAvLyAodGhlIHJlcGxpY2EgZm9yIHRoZSBcIm9sZFwiIFRhYmxlIHdpbGwgYmUgZGVsZXRlZCB3aGVuIENGTiBpc3N1ZXMgYSBEZWxldGUgZXZlbnQgb24gdGhlIG9sZCBwaHlzaWNhbCByZXNvdXJjZSBpZCkuXG4gICAgLy8gMi4gQSBjdXN0b21lciBoYXMgY2hhbmdlZCBvbmUgb2YgdGhlIHByb3BlcnRpZXMgb2YgdGhlIEN1c3RvbSBSZXNvdXJjZSxcbiAgICAvLyBsaWtlICd3YWl0Rm9yUmVwbGljYXRpb25Ub0ZpbmlzaCcuIEluIHRoYXQgY2FzZSwgd2UgZG9uJ3QgaGF2ZSB0byBkbyBhbnl0aGluZy5cbiAgICAvLyBUbyBkaWZmZXJlbnRpYXRlIHRoZSB0d28gY2FzZXMsIHdlIG1ha2UgYW4gQVBJIGNhbGwgdG8gRHluYW1vREIgdG8gY2hlY2sgd2hldGhlciBhIHJlcGxpY2EgYWxyZWFkeSBleGlzdHMuXG4gICAgY29uc3QgZGVzY3JpYmVUYWJsZVJlc3VsdCA9IGF3YWl0IGR5bmFtb2RiLmRlc2NyaWJlVGFibGUoe1xuICAgICAgVGFibGVOYW1lOiB0YWJsZU5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIGNvbnNvbGUubG9nKCdEZXNjcmliZSB0YWJsZTogJWonLCBkZXNjcmliZVRhYmxlUmVzdWx0KTtcbiAgICBjb25zdCByZXBsaWNhRXhpc3RzID0gZGVzY3JpYmVUYWJsZVJlc3VsdC5UYWJsZT8uUmVwbGljYXM/LnNvbWUocmVwbGljYSA9PiByZXBsaWNhLlJlZ2lvbk5hbWUgPT09IHJlZ2lvbik7XG4gICAgdXBkYXRlVGFibGVBY3Rpb24gPSByZXBsaWNhRXhpc3RzID8gdW5kZWZpbmVkIDogJ0NyZWF0ZSc7XG4gIH1cblxuICBpZiAodXBkYXRlVGFibGVBY3Rpb24pIHtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgZHluYW1vZGIudXBkYXRlVGFibGUoe1xuICAgICAgVGFibGVOYW1lOiB0YWJsZU5hbWUsXG4gICAgICBSZXBsaWNhVXBkYXRlczogW1xuICAgICAgICB7XG4gICAgICAgICAgW3VwZGF0ZVRhYmxlQWN0aW9uXToge1xuICAgICAgICAgICAgUmVnaW9uTmFtZTogcmVnaW9uLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pLnByb21pc2UoKTtcbiAgICBjb25zb2xlLmxvZygnVXBkYXRlIHRhYmxlOiAlaicsIGRhdGEpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUubG9nKFwiU2tpcHBpbmcgdXBkYXRpbmcgVGFibGUsIGFzIGEgcmVwbGljYSBpbiAnJXMnIGFscmVhZHkgZXhpc3RzXCIsIHJlZ2lvbik7XG4gIH1cblxuICByZXR1cm4gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnIHx8IGV2ZW50LlJlcXVlc3RUeXBlID09PSAnVXBkYXRlJ1xuICAgID8geyBQaHlzaWNhbFJlc291cmNlSWQ6IGAke3RhYmxlTmFtZX0tJHtyZWdpb259YCB9XG4gICAgOiB7fTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzQ29tcGxldGVIYW5kbGVyKGV2ZW50OiBJc0NvbXBsZXRlUmVxdWVzdCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gIGNvbnNvbGUubG9nKCdFdmVudDogJWonLCBldmVudCk7XG5cbiAgY29uc3QgZHluYW1vZGIgPSBuZXcgRHluYW1vREIoKTtcblxuICBjb25zdCBkYXRhID0gYXdhaXQgZHluYW1vZGIuZGVzY3JpYmVUYWJsZSh7XG4gICAgVGFibGVOYW1lOiBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVGFibGVOYW1lLFxuICB9KS5wcm9taXNlKCk7XG4gIGNvbnNvbGUubG9nKCdEZXNjcmliZSB0YWJsZTogJWonLCBkYXRhKTtcblxuICBjb25zdCB0YWJsZUFjdGl2ZSA9IGRhdGEuVGFibGU/LlRhYmxlU3RhdHVzID09PSAnQUNUSVZFJztcbiAgY29uc3QgcmVwbGljYXMgPSBkYXRhLlRhYmxlPy5SZXBsaWNhcyA/PyBbXTtcbiAgY29uc3QgcmVnaW9uUmVwbGljYSA9IHJlcGxpY2FzLmZpbmQociA9PiByLlJlZ2lvbk5hbWUgPT09IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5SZWdpb24pO1xuICBjb25zdCByZXBsaWNhQWN0aXZlID0gcmVnaW9uUmVwbGljYT8uUmVwbGljYVN0YXR1cyA9PT0gJ0FDVElWRSc7XG4gIGNvbnN0IHNraXBSZXBsaWNhdGlvbkNvbXBsZXRlZFdhaXQgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuU2tpcFJlcGxpY2F0aW9uQ29tcGxldGVkV2FpdCA9PT0gJ3RydWUnO1xuXG4gIHN3aXRjaCAoZXZlbnQuUmVxdWVzdFR5cGUpIHtcbiAgICBjYXNlICdDcmVhdGUnOlxuICAgIGNhc2UgJ1VwZGF0ZSc6XG4gICAgICAvLyBDb21wbGV0ZSB3aGVuIHJlcGxpY2EgaXMgcmVwb3J0ZWQgYXMgQUNUSVZFXG4gICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0YWJsZUFjdGl2ZSAmJiAocmVwbGljYUFjdGl2ZSB8fCBza2lwUmVwbGljYXRpb25Db21wbGV0ZWRXYWl0KSB9O1xuICAgIGNhc2UgJ0RlbGV0ZSc6XG4gICAgICAvLyBDb21wbGV0ZSB3aGVuIHJlcGxpY2EgaXMgZ29uZVxuICAgICAgcmV0dXJuIHsgSXNDb21wbGV0ZTogdGFibGVBY3RpdmUgJiYgcmVnaW9uUmVwbGljYSA9PT0gdW5kZWZpbmVkIH07XG4gIH1cbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxxQ0FBbUMsQ0FBQyx3REFBd0Q7QUFFckYsS0FBSyxVQUFVLGNBQWMsQ0FBQyxLQUFxQjtJQUN4RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVoQyxNQUFNLFFBQVEsR0FBRyxJQUFJLGtCQUFRLEVBQUUsQ0FBQztJQUVoQyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDO0lBQ3JELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUM7SUFFL0MsSUFBSSxpQkFBNkQsQ0FBQztJQUNsRSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFO1FBQ3BFLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7S0FDdkM7U0FBTSxFQUFFLFNBQVM7UUFDaEIsa0RBQWtEO1FBQ2xELHVGQUF1RjtRQUN2RixvSEFBb0g7UUFDcEgsMEVBQTBFO1FBQzFFLGlGQUFpRjtRQUNqRiw2R0FBNkc7UUFDN0csTUFBTSxtQkFBbUIsR0FBRyxNQUFNLFFBQVEsQ0FBQyxhQUFhLENBQUM7WUFDdkQsU0FBUyxFQUFFLFNBQVM7U0FDckIsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxNQUFNLENBQUMsQ0FBQztRQUMxRyxpQkFBaUIsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0tBQzFEO0lBRUQsSUFBSSxpQkFBaUIsRUFBRTtRQUNyQixNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDdEMsU0FBUyxFQUFFLFNBQVM7WUFDcEIsY0FBYyxFQUFFO2dCQUNkO29CQUNFLENBQUMsaUJBQWlCLENBQUMsRUFBRTt3QkFDbkIsVUFBVSxFQUFFLE1BQU07cUJBQ25CO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3ZDO1NBQU07UUFDTCxPQUFPLENBQUMsR0FBRyxDQUFDLDhEQUE4RCxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQ3JGO0lBRUQsT0FBTyxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVE7UUFDckUsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxTQUFTLElBQUksTUFBTSxFQUFFLEVBQUU7UUFDbEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNULENBQUM7QUE3Q0Qsd0NBNkNDO0FBRU0sS0FBSyxVQUFVLGlCQUFpQixDQUFDLEtBQXdCO0lBQzlELE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWhDLE1BQU0sUUFBUSxHQUFHLElBQUksa0JBQVEsRUFBRSxDQUFDO0lBRWhDLE1BQU0sSUFBSSxHQUFHLE1BQU0sUUFBUSxDQUFDLGFBQWEsQ0FBQztRQUN4QyxTQUFTLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFNBQVM7S0FDOUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsS0FBSyxRQUFRLENBQUM7SUFDekQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLElBQUksRUFBRSxDQUFDO0lBQzVDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxLQUFLLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzRixNQUFNLGFBQWEsR0FBRyxhQUFhLEVBQUUsYUFBYSxLQUFLLFFBQVEsQ0FBQztJQUNoRSxNQUFNLDRCQUE0QixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyw0QkFBNEIsS0FBSyxNQUFNLENBQUM7SUFFdEcsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3pCLEtBQUssUUFBUSxDQUFDO1FBQ2QsS0FBSyxRQUFRO1lBQ1gsOENBQThDO1lBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxJQUFJLENBQUMsYUFBYSxJQUFJLDRCQUE0QixDQUFDLEVBQUUsQ0FBQztRQUN4RixLQUFLLFFBQVE7WUFDWCxnQ0FBZ0M7WUFDaEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLElBQUksYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO0tBQ3JFO0FBQ0gsQ0FBQztBQXpCRCw4Q0F5QkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgdHlwZSB7IElzQ29tcGxldGVSZXF1ZXN0LCBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXF1ZXN0LCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuaW1wb3J0IHsgRHluYW1vREIgfSBmcm9tICdhd3Mtc2RrJzsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uRXZlbnRIYW5kbGVyKGV2ZW50OiBPbkV2ZW50UmVxdWVzdCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gIGNvbnNvbGUubG9nKCdFdmVudDogJWonLCBldmVudCk7XG5cbiAgY29uc3QgZHluYW1vZGIgPSBuZXcgRHluYW1vREIoKTtcblxuICBjb25zdCB0YWJsZU5hbWUgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVGFibGVOYW1lO1xuICBjb25zdCByZWdpb24gPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUmVnaW9uO1xuXG4gIGxldCB1cGRhdGVUYWJsZUFjdGlvbjogJ0NyZWF0ZScgfCAnVXBkYXRlJyB8ICdEZWxldGUnIHwgdW5kZWZpbmVkO1xuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnIHx8IGV2ZW50LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJykge1xuICAgIHVwZGF0ZVRhYmxlQWN0aW9uID0gZXZlbnQuUmVxdWVzdFR5cGU7XG4gIH0gZWxzZSB7IC8vIFVwZGF0ZVxuICAgIC8vIFRoZXJlIGFyZSB0d28gY2FzZXMgd2hlcmUgYW4gVXBkYXRlIGNhbiBoYXBwZW46XG4gICAgLy8gMS4gQSB0YWJsZSByZXBsYWNlbWVudC4gSW4gdGhhdCBjYXNlLCB3ZSBuZWVkIHRvIGNyZWF0ZSB0aGUgcmVwbGljYSBpbiB0aGUgbmV3IFRhYmxlXG4gICAgLy8gKHRoZSByZXBsaWNhIGZvciB0aGUgXCJvbGRcIiBUYWJsZSB3aWxsIGJlIGRlbGV0ZWQgd2hlbiBDRk4gaXNzdWVzIGEgRGVsZXRlIGV2ZW50IG9uIHRoZSBvbGQgcGh5c2ljYWwgcmVzb3VyY2UgaWQpLlxuICAgIC8vIDIuIEEgY3VzdG9tZXIgaGFzIGNoYW5nZWQgb25lIG9mIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBDdXN0b20gUmVzb3VyY2UsXG4gICAgLy8gbGlrZSAnd2FpdEZvclJlcGxpY2F0aW9uVG9GaW5pc2gnLiBJbiB0aGF0IGNhc2UsIHdlIGRvbid0IGhhdmUgdG8gZG8gYW55dGhpbmcuXG4gICAgLy8gVG8gZGlmZmVyZW50aWF0ZSB0aGUgdHdvIGNhc2VzLCB3ZSBtYWtlIGFuIEFQSSBjYWxsIHRvIER5bmFtb0RCIHRvIGNoZWNrIHdoZXRoZXIgYSByZXBsaWNhIGFscmVhZHkgZXhpc3RzLlxuICAgIGNvbnN0IGRlc2NyaWJlVGFibGVSZXN1bHQgPSBhd2FpdCBkeW5hbW9kYi5kZXNjcmliZVRhYmxlKHtcbiAgICAgIFRhYmxlTmFtZTogdGFibGVOYW1lLFxuICAgIH0pLnByb21pc2UoKTtcbiAgICBjb25zb2xlLmxvZygnRGVzY3JpYmUgdGFibGU6ICVqJywgZGVzY3JpYmVUYWJsZVJlc3VsdCk7XG4gICAgY29uc3QgcmVwbGljYUV4aXN0cyA9IGRlc2NyaWJlVGFibGVSZXN1bHQuVGFibGU/LlJlcGxpY2FzPy5zb21lKHJlcGxpY2EgPT4gcmVwbGljYS5SZWdpb25OYW1lID09PSByZWdpb24pO1xuICAgIHVwZGF0ZVRhYmxlQWN0aW9uID0gcmVwbGljYUV4aXN0cyA/IHVuZGVmaW5lZCA6ICdDcmVhdGUnO1xuICB9XG5cbiAgaWYgKHVwZGF0ZVRhYmxlQWN0aW9uKSB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IGR5bmFtb2RiLnVwZGF0ZVRhYmxlKHtcbiAgICAgIFRhYmxlTmFtZTogdGFibGVOYW1lLFxuICAgICAgUmVwbGljYVVwZGF0ZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIFt1cGRhdGVUYWJsZUFjdGlvbl06IHtcbiAgICAgICAgICAgIFJlZ2lvbk5hbWU6IHJlZ2lvbixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KS5wcm9taXNlKCk7XG4gICAgY29uc29sZS5sb2coJ1VwZGF0ZSB0YWJsZTogJWonLCBkYXRhKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZyhcIlNraXBwaW5nIHVwZGF0aW5nIFRhYmxlLCBhcyBhIHJlcGxpY2EgaW4gJyVzJyBhbHJlYWR5IGV4aXN0c1wiLCByZWdpb24pO1xuICB9XG5cbiAgcmV0dXJuIGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJyB8fCBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZSdcbiAgICA/IHsgUGh5c2ljYWxSZXNvdXJjZUlkOiBgJHt0YWJsZU5hbWV9LSR7cmVnaW9ufWAgfVxuICAgIDoge307XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpc0NvbXBsZXRlSGFuZGxlcihldmVudDogSXNDb21wbGV0ZVJlcXVlc3QpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICBjb25zb2xlLmxvZygnRXZlbnQ6ICVqJywgZXZlbnQpO1xuXG4gIGNvbnN0IGR5bmFtb2RiID0gbmV3IER5bmFtb0RCKCk7XG5cbiAgY29uc3QgZGF0YSA9IGF3YWl0IGR5bmFtb2RiLmRlc2NyaWJlVGFibGUoe1xuICAgIFRhYmxlTmFtZTogZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlRhYmxlTmFtZSxcbiAgfSkucHJvbWlzZSgpO1xuICBjb25zb2xlLmxvZygnRGVzY3JpYmUgdGFibGU6ICVqJywgZGF0YSk7XG5cbiAgY29uc3QgdGFibGVBY3RpdmUgPSBkYXRhLlRhYmxlPy5UYWJsZVN0YXR1cyA9PT0gJ0FDVElWRSc7XG4gIGNvbnN0IHJlcGxpY2FzID0gZGF0YS5UYWJsZT8uUmVwbGljYXMgPz8gW107XG4gIGNvbnN0IHJlZ2lvblJlcGxpY2EgPSByZXBsaWNhcy5maW5kKHIgPT4gci5SZWdpb25OYW1lID09PSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuUmVnaW9uKTtcbiAgY29uc3QgcmVwbGljYUFjdGl2ZSA9IHJlZ2lvblJlcGxpY2E/LlJlcGxpY2FTdGF0dXMgPT09ICdBQ1RJVkUnO1xuICBjb25zdCBza2lwUmVwbGljYXRpb25Db21wbGV0ZWRXYWl0ID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlNraXBSZXBsaWNhdGlvbkNvbXBsZXRlZFdhaXQgPT09ICd0cnVlJztcblxuICBzd2l0Y2ggKGV2ZW50LlJlcXVlc3RUeXBlKSB7XG4gICAgY2FzZSAnQ3JlYXRlJzpcbiAgICBjYXNlICdVcGRhdGUnOlxuICAgICAgLy8gQ29tcGxldGUgd2hlbiByZXBsaWNhIGlzIHJlcG9ydGVkIGFzIEFDVElWRVxuICAgICAgcmV0dXJuIHsgSXNDb21wbGV0ZTogdGFibGVBY3RpdmUgJiYgKHJlcGxpY2FBY3RpdmUgfHwgc2tpcFJlcGxpY2F0aW9uQ29tcGxldGVkV2FpdCkgfTtcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgLy8gQ29tcGxldGUgd2hlbiByZXBsaWNhIGlzIGdvbmVcbiAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRhYmxlQWN0aXZlICYmIHJlZ2lvblJlcGxpY2EgPT09IHVuZGVmaW5lZCB9O1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.assets.json index 10632e6f5e4b8..d02130559f74c 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "9abf2316979a565d3a86e43cce5b25037aee1b5cd3885835f8b3daec825b517e": { + "2cc27380df0d00a7348926c8fe9b6ae056ac18cee09087d824792e9611cde97e": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9abf2316979a565d3a86e43cce5b25037aee1b5cd3885835f8b3daec825b517e.json", + "objectKey": "2cc27380df0d00a7348926c8fe9b6ae056ac18cee09087d824792e9611cde97e.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.template.json index 1c7c44c5325cf..0be8262ae5985 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/aws-ecs-integ.template.json @@ -729,7 +729,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/manifest.json index 5b97a01091f7d..c50bfa1c4c065 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/manifest.json @@ -321,6 +321,12 @@ "data": "myServiceTaskDefTaskRole1C1DE6CC" } ], + "/aws-ecs-integ/myService/TaskDef/TaskRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "myServiceTaskDefTaskRoleDefaultPolicyD48473C0" + } + ], "/aws-ecs-integ/myService/TaskDef/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/tree.json index a7b1126c52c1d..9f84deb07027d 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/multiple-application-load-balanced-ecs-service.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1143,7 +1143,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1240,7 +1240,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { @@ -1735,6 +1735,54 @@ "fqn": "@aws-cdk/aws-iam.CfnRole", "version": "0.0.0" } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-ecs-integ/myService/TaskDef/TaskRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-integ/myService/TaskDef/TaskRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "myServiceTaskDefTaskRoleDefaultPolicyD48473C0", + "roles": [ + { + "Ref": "myServiceTaskDefTaskRole1C1DE6CC" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } } }, "constructInfo": { @@ -1942,6 +1990,7 @@ "minimumHealthyPercent": 50 }, "enableEcsManagedTags": false, + "enableExecuteCommand": true, "healthCheckGracePeriodSeconds": 60, "launchType": "EC2", "loadBalancers": [ diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json index 4f433ce8c056d..52856e869e677 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "62462a0ca4f5e1fde18ddd2e2ad6537c111d2bd84b82653a8628047c552bca14": { + "ef02919701446f0e1c908b12e2e437448544c6ac7df2f65225cb0cd189188fd1": { "source": { "path": "aws-ecs-integ-ecs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "62462a0ca4f5e1fde18ddd2e2ad6537c111d2bd84b82653a8628047c552bca14.json", + "objectKey": "ef02919701446f0e1c908b12e2e437448544c6ac7df2f65225cb0cd189188fd1.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json index 22bd56aa3a632..10a6a31985ccc 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json @@ -532,7 +532,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/tree.json index ed9a2e25abba8..895170266a8ab 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/scheduled-ecs-task.lit.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-ecs": { @@ -825,7 +825,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -922,7 +922,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/lib/drain-hook/lambda-source/index.py b/packages/@aws-cdk/aws-ecs/lib/drain-hook/lambda-source/index.py index 0b4590f9e4768..73502aca37ac2 100644 --- a/packages/@aws-cdk/aws-ecs/lib/drain-hook/lambda-source/index.py +++ b/packages/@aws-cdk/aws-ecs/lib/drain-hook/lambda-source/index.py @@ -5,13 +5,13 @@ def lambda_handler(event, context): - print(json.dumps(event)) + print(json.dumps(dict(event, ResponseURL='...'))) cluster = os.environ['CLUSTER'] snsTopicArn = event['Records'][0]['Sns']['TopicArn'] lifecycle_event = json.loads(event['Records'][0]['Sns']['Message']) instance_id = lifecycle_event.get('EC2InstanceId') if not instance_id: - print('Got event without EC2InstanceId: %s', json.dumps(event)) + print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...'))) return instance_arn = container_instance_arn(cluster, instance_id) @@ -21,7 +21,7 @@ def lambda_handler(event, context): return task_arns = container_instance_task_arns(cluster, instance_arn) - + if task_arns: print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns))) @@ -70,11 +70,11 @@ def has_tasks(cluster, instance_arn, task_arns): if tasks: # Consider any non-stopped tasks as running task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount'] - + if not task_count: # Fallback to instance task counts if detailed task information is unavailable task_count = instance['runningTasksCount'] + instance['pendingTasksCount'] - + print('Instance %s has %s tasks' % (instance_arn, task_count)) return task_count > 0 diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.assets.json index 5789ea5687210..1ab9b4723b913 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "7394cc2d5795ed107942fc97dc607f855891f6d0faad71ce9ce117f212950396": { + "260a3149191409f3d7f327066a7aacd76a4cd04b00b8bfbb8b20426e33fa3e98": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7394cc2d5795ed107942fc97dc607f855891f6d0faad71ce9ce117f212950396.json", + "objectKey": "260a3149191409f3d7f327066a7aacd76a4cd04b00b8bfbb8b20426e33fa3e98.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.template.json index 7f3053bbd43a7..0727b8b63cdf6 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/aws-ecs-integ.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/tree.json index db4e7078b71a0..d874f4e4ce35c 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/app-mesh-proxy-config.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.assets.json index ff7d87f507356..85e2dd7b9c428 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "53566d1f850005909cb07f2c57a7751eaf5cb7b92c2b3319ff2b94c2347ad8c1": { + "210f85d7a4711abdd1a82d02368b3735815f4862d796b79d3f93aa4a12e899d3": { "source": { "path": "aws-ecs-integ-bottlerocket.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "53566d1f850005909cb07f2c57a7751eaf5cb7b92c2b3319ff2b94c2347ad8c1.json", + "objectKey": "210f85d7a4711abdd1a82d02368b3735815f4862d796b79d3f93aa4a12e899d3.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.template.json index 534e644102517..b64a9e8fa178a 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/aws-ecs-integ-bottlerocket.template.json @@ -702,7 +702,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/tree.json index aa0bc72d3c0ab..9e8b3c585f203 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/bottlerocket.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-bottlerocket": { @@ -1092,7 +1092,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1189,7 +1189,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.assets.json index 00a24a8b7b09c..b8bdc6685e334 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "90ed284ac69a21c2eb59258e3f72bae1ab1fb69d2a3d14ef67d0ff1434720dc7": { + "26e60053ecf7db8f26882e73bccc9581855eca5fdb825ad84ee1ebb15eaa3503": { "source": { "path": "integ-ec2-capacity-provider.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "90ed284ac69a21c2eb59258e3f72bae1ab1fb69d2a3d14ef67d0ff1434720dc7.json", + "objectKey": "26e60053ecf7db8f26882e73bccc9581855eca5fdb825ad84ee1ebb15eaa3503.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.template.json index e683a76ccc363..ca113d4b523dd 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/integ-ec2-capacity-provider.template.json @@ -762,7 +762,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/tree.json index ccf6fab0d1dc1..815779c1046b5 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/capacity-provider.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "integ-ec2-capacity-provider": { @@ -1229,7 +1229,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1326,7 +1326,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.assets.json index b345bd7a2907a..231fb8a0d72ed 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "83bb192a1fe6f490af006a6b1325632945dd1f84ed5cbdbec44b888a13f9410c": { + "b738db881375282bfd1e8c1823f02bf200e99c0456ed04099e04bd945f993120": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "83bb192a1fe6f490af006a6b1325632945dd1f84ed5cbdbec44b888a13f9410c.json", + "objectKey": "b738db881375282bfd1e8c1823f02bf200e99c0456ed04099e04bd945f993120.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.template.json index 983f8005671fc..3d88c55ffc323 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/aws-ecs-integ.template.json @@ -729,7 +729,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/tree.json index 8d4565c711760..1a33b0af7e30a 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/clb-host-nw.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1143,7 +1143,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1240,7 +1240,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.assets.json index 4319a6d79680c..34f78aff9a449 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "a6c4c4f650fc7da017da1a0858eecee50fe9cc015b42bb33acbec0546ce18d58": { + "95f15a5314a4c4b4dcc58f538eff2934ab3502879e49f65497bf0040de83e522": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a6c4c4f650fc7da017da1a0858eecee50fe9cc015b42bb33acbec0546ce18d58.json", + "objectKey": "95f15a5314a4c4b4dcc58f538eff2934ab3502879e49f65497bf0040de83e522.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.template.json index 73eeefaf66870..c6a39ef80fd97 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/aws-ecs-integ.template.json @@ -516,7 +516,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/tree.json index ec989047a6871..5c3bedc398a1e 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/cloudmap-container-port.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -790,7 +790,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -887,7 +887,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a.zip b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a.zip deleted file mode 100644 index e5db626206eef..0000000000000 Binary files a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a.zip and /dev/null differ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/__entrypoint__.js b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/__entrypoint__.js deleted file mode 100644 index 3475719002c73..0000000000000 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/__entrypoint__.js +++ /dev/null @@ -1,119 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.handler = exports.external = void 0; -const https = require("https"); -const url = require("url"); -// for unit tests -exports.external = { - sendHttpRequest: defaultSendHttpRequest, - log: defaultLog, - includeStackTraces: true, - userHandlerIndex: './index', -}; -const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; -const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; -async function handler(event, context) { - exports.external.log(JSON.stringify(event, undefined, 2)); - // ignore DELETE event when the physical resource ID is the marker that - // indicates that this DELETE is a subsequent DELETE to a failed CREATE - // operation. - if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { - exports.external.log('ignoring DELETE event caused by a failed CREATE event'); - await submitResponse('SUCCESS', event); - return; - } - try { - // invoke the user handler. this is intentionally inside the try-catch to - // ensure that if there is an error it's reported as a failure to - // cloudformation (otherwise cfn waits). - // eslint-disable-next-line @typescript-eslint/no-require-imports - const userHandler = require(exports.external.userHandlerIndex).handler; - const result = await userHandler(event, context); - // validate user response and create the combined event - const responseEvent = renderResponse(event, result); - // submit to cfn as success - await submitResponse('SUCCESS', responseEvent); - } - catch (e) { - const resp = { - ...event, - Reason: exports.external.includeStackTraces ? e.stack : e.message, - }; - if (!resp.PhysicalResourceId) { - // special case: if CREATE fails, which usually implies, we usually don't - // have a physical resource id. in this case, the subsequent DELETE - // operation does not have any meaning, and will likely fail as well. to - // address this, we use a marker so the provider framework can simply - // ignore the subsequent DELETE. - if (event.RequestType === 'Create') { - exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); - resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; - } - else { - // otherwise, if PhysicalResourceId is not specified, something is - // terribly wrong because all other events should have an ID. - exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); - } - } - // this is an actual error, fail the activity altogether and exist. - await submitResponse('FAILED', resp); - } -} -exports.handler = handler; -function renderResponse(cfnRequest, handlerResponse = {}) { - var _a, _b; - // if physical ID is not returned, we have some defaults for you based - // on the request type. - const physicalResourceId = (_b = (_a = handlerResponse.PhysicalResourceId) !== null && _a !== void 0 ? _a : cfnRequest.PhysicalResourceId) !== null && _b !== void 0 ? _b : cfnRequest.RequestId; - // if we are in DELETE and physical ID was changed, it's an error. - if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { - throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); - } - // merge request event and result event (result prevails). - return { - ...cfnRequest, - ...handlerResponse, - PhysicalResourceId: physicalResourceId, - }; -} -async function submitResponse(status, event) { - var _a; - const json = { - Status: status, - Reason: (_a = event.Reason) !== null && _a !== void 0 ? _a : status, - StackId: event.StackId, - RequestId: event.RequestId, - PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, - LogicalResourceId: event.LogicalResourceId, - NoEcho: event.NoEcho, - Data: event.Data, - }; - exports.external.log('submit response to cloudformation', json); - const responseBody = JSON.stringify(json); - const parsedUrl = url.parse(event.ResponseURL); - const req = { - hostname: parsedUrl.hostname, - path: parsedUrl.path, - method: 'PUT', - headers: { 'content-type': '', 'content-length': responseBody.length }, - }; - await exports.external.sendHttpRequest(req, responseBody); -} -async function defaultSendHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, _ => resolve()); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -function defaultLog(fmt, ...params) { - // eslint-disable-next-line no-console - console.log(fmt, ...params); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFbEQsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFakQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbERELDBCQWtEQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRzs7SUFFN0Msc0VBQXNFO0lBQ3RFLHVCQUF1QjtJQUN2QixNQUFNLGtCQUFrQixlQUFHLGVBQWUsQ0FBQyxrQkFBa0IsbUNBQUksVUFBVSxDQUFDLGtCQUFrQixtQ0FBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7O0lBQ3pFLE1BQU0sSUFBSSxHQUFtRDtRQUMzRCxNQUFNLEVBQUUsTUFBTTtRQUNkLE1BQU0sUUFBRSxLQUFLLENBQUMsTUFBTSxtQ0FBSSxNQUFNO1FBQzlCLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztRQUN0QixTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7UUFDMUIsa0JBQWtCLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixJQUFJLDBCQUEwQjtRQUMxRSxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1FBQzFDLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtRQUNwQixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7S0FDakIsQ0FBQztJQUVGLGdCQUFRLENBQUMsR0FBRyxDQUFDLG1DQUFtQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBRXhELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDL0MsTUFBTSxHQUFHLEdBQUc7UUFDVixRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVE7UUFDNUIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO1FBQ3BCLE1BQU0sRUFBRSxLQUFLO1FBQ2IsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsTUFBTSxFQUFFO0tBQ3ZFLENBQUM7SUFFRixNQUFNLGdCQUFRLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBRUQsS0FBSyxVQUFVLHNCQUFzQixDQUFDLE9BQTZCLEVBQUUsWUFBb0I7SUFDdkYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsR0FBVyxFQUFFLEdBQUcsTUFBYTtJQUMvQyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuaW1wb3J0ICogYXMgdXJsIGZyb20gJ3VybCc7XG5cbi8vIGZvciB1bml0IHRlc3RzXG5leHBvcnQgY29uc3QgZXh0ZXJuYWwgPSB7XG4gIHNlbmRIdHRwUmVxdWVzdDogZGVmYXVsdFNlbmRIdHRwUmVxdWVzdCxcbiAgbG9nOiBkZWZhdWx0TG9nLFxuICBpbmNsdWRlU3RhY2tUcmFjZXM6IHRydWUsXG4gIHVzZXJIYW5kbGVySW5kZXg6ICcuL2luZGV4Jyxcbn07XG5cbmNvbnN0IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSID0gJ0FXU0NESzo6Q3VzdG9tUmVzb3VyY2VQcm92aWRlckZyYW1ld29yazo6Q1JFQVRFX0ZBSUxFRCc7XG5jb25zdCBNSVNTSU5HX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6Ok1JU1NJTkdfUEhZU0lDQUxfSUQnO1xuXG5leHBvcnQgdHlwZSBSZXNwb25zZSA9IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQgJiBIYW5kbGVyUmVzcG9uc2U7XG5leHBvcnQgdHlwZSBIYW5kbGVyID0gKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBjb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dCkgPT4gUHJvbWlzZTxIYW5kbGVyUmVzcG9uc2UgfCB2b2lkPjtcbmV4cG9ydCB0eXBlIEhhbmRsZXJSZXNwb25zZSA9IHVuZGVmaW5lZCB8IHtcbiAgRGF0YT86IGFueTtcbiAgUGh5c2ljYWxSZXNvdXJjZUlkPzogc3RyaW5nO1xuICBSZWFzb24/OiBzdHJpbmc7XG4gIE5vRWNobz86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlcihldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpIHtcbiAgZXh0ZXJuYWwubG9nKEpTT04uc3RyaW5naWZ5KGV2ZW50LCB1bmRlZmluZWQsIDIpKTtcblxuICAvLyBpZ25vcmUgREVMRVRFIGV2ZW50IHdoZW4gdGhlIHBoeXNpY2FsIHJlc291cmNlIElEIGlzIHRoZSBtYXJrZXIgdGhhdFxuICAvLyBpbmRpY2F0ZXMgdGhhdCB0aGlzIERFTEVURSBpcyBhIHN1YnNlcXVlbnQgREVMRVRFIHRvIGEgZmFpbGVkIENSRUFURVxuICAvLyBvcGVyYXRpb24uXG4gIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScgJiYgZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkID09PSBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUikge1xuICAgIGV4dGVybmFsLmxvZygnaWdub3JpbmcgREVMRVRFIGV2ZW50IGNhdXNlZCBieSBhIGZhaWxlZCBDUkVBVEUgZXZlbnQnKTtcbiAgICBhd2FpdCBzdWJtaXRSZXNwb25zZSgnU1VDQ0VTUycsIGV2ZW50KTtcbiAgICByZXR1cm47XG4gIH1cblxuICB0cnkge1xuICAgIC8vIGludm9rZSB0aGUgdXNlciBoYW5kbGVyLiB0aGlzIGlzIGludGVudGlvbmFsbHkgaW5zaWRlIHRoZSB0cnktY2F0Y2ggdG9cbiAgICAvLyBlbnN1cmUgdGhhdCBpZiB0aGVyZSBpcyBhbiBlcnJvciBpdCdzIHJlcG9ydGVkIGFzIGEgZmFpbHVyZSB0b1xuICAgIC8vIGNsb3VkZm9ybWF0aW9uIChvdGhlcndpc2UgY2ZuIHdhaXRzKS5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IHVzZXJIYW5kbGVyOiBIYW5kbGVyID0gcmVxdWlyZShleHRlcm5hbC51c2VySGFuZGxlckluZGV4KS5oYW5kbGVyO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHVzZXJIYW5kbGVyKGV2ZW50LCBjb250ZXh0KTtcblxuICAgIC8vIHZhbGlkYXRlIHVzZXIgcmVzcG9uc2UgYW5kIGNyZWF0ZSB0aGUgY29tYmluZWQgZXZlbnRcbiAgICBjb25zdCByZXNwb25zZUV2ZW50ID0gcmVuZGVyUmVzcG9uc2UoZXZlbnQsIHJlc3VsdCk7XG5cbiAgICAvLyBzdWJtaXQgdG8gY2ZuIGFzIHN1Y2Nlc3NcbiAgICBhd2FpdCBzdWJtaXRSZXNwb25zZSgnU1VDQ0VTUycsIHJlc3BvbnNlRXZlbnQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc3QgcmVzcDogUmVzcG9uc2UgPSB7XG4gICAgICAuLi5ldmVudCxcbiAgICAgIFJlYXNvbjogZXh0ZXJuYWwuaW5jbHVkZVN0YWNrVHJhY2VzID8gZS5zdGFjayA6IGUubWVzc2FnZSxcbiAgICB9O1xuXG4gICAgaWYgKCFyZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBDUkVBVEUgZmFpbHMsIHdoaWNoIHVzdWFsbHkgaW1wbGllcywgd2UgdXN1YWxseSBkb24ndFxuICAgICAgLy8gaGF2ZSBhIHBoeXNpY2FsIHJlc291cmNlIGlkLiBpbiB0aGlzIGNhc2UsIHRoZSBzdWJzZXF1ZW50IERFTEVURVxuICAgICAgLy8gb3BlcmF0aW9uIGRvZXMgbm90IGhhdmUgYW55IG1lYW5pbmcsIGFuZCB3aWxsIGxpa2VseSBmYWlsIGFzIHdlbGwuIHRvXG4gICAgICAvLyBhZGRyZXNzIHRoaXMsIHdlIHVzZSBhIG1hcmtlciBzbyB0aGUgcHJvdmlkZXIgZnJhbWV3b3JrIGNhbiBzaW1wbHlcbiAgICAgIC8vIGlnbm9yZSB0aGUgc3Vic2VxdWVudCBERUxFVEUuXG4gICAgICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgICAgIGV4dGVybmFsLmxvZygnQ1JFQVRFIGZhaWxlZCwgcmVzcG9uZGluZyB3aXRoIGEgbWFya2VyIHBoeXNpY2FsIHJlc291cmNlIGlkIHNvIHRoYXQgdGhlIHN1YnNlcXVlbnQgREVMRVRFIHdpbGwgYmUgaWdub3JlZCcpO1xuICAgICAgICByZXNwLlBoeXNpY2FsUmVzb3VyY2VJZCA9IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBpZiBQaHlzaWNhbFJlc291cmNlSWQgaXMgbm90IHNwZWNpZmllZCwgc29tZXRoaW5nIGlzXG4gICAgICAgIC8vIHRlcnJpYmx5IHdyb25nIGJlY2F1c2UgYWxsIG90aGVyIGV2ZW50cyBzaG91bGQgaGF2ZSBhbiBJRC5cbiAgICAgICAgZXh0ZXJuYWwubG9nKGBFUlJPUjogTWFsZm9ybWVkIGV2ZW50LiBcIlBoeXNpY2FsUmVzb3VyY2VJZFwiIGlzIHJlcXVpcmVkOiAke0pTT04uc3RyaW5naWZ5KGV2ZW50KX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFuIGFjdHVhbCBlcnJvciwgZmFpbCB0aGUgYWN0aXZpdHkgYWx0b2dldGhlciBhbmQgZXhpc3QuXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ0ZBSUxFRCcsIHJlc3ApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3BvbnNlKFxuICBjZm5SZXF1ZXN0OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgeyBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgaGFuZGxlclJlc3BvbnNlOiB2b2lkIHwgSGFuZGxlclJlc3BvbnNlID0geyB9KTogUmVzcG9uc2Uge1xuXG4gIC8vIGlmIHBoeXNpY2FsIElEIGlzIG5vdCByZXR1cm5lZCwgd2UgaGF2ZSBzb21lIGRlZmF1bHRzIGZvciB5b3UgYmFzZWRcbiAgLy8gb24gdGhlIHJlcXVlc3QgdHlwZS5cbiAgY29uc3QgcGh5c2ljYWxSZXNvdXJjZUlkID0gaGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCA/PyBjZm5SZXF1ZXN0LlJlcXVlc3RJZDtcblxuICAvLyBpZiB3ZSBhcmUgaW4gREVMRVRFIGFuZCBwaHlzaWNhbCBJRCB3YXMgY2hhbmdlZCwgaXQncyBhbiBlcnJvci5cbiAgaWYgKGNmblJlcXVlc3QuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIHBoeXNpY2FsUmVzb3VyY2VJZCAhPT0gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERFTEVURTogY2Fubm90IGNoYW5nZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgZnJvbSBcIiR7Y2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWR9XCIgdG8gXCIke2hhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWR9XCIgZHVyaW5nIGRlbGV0aW9uYCk7XG4gIH1cblxuICAvLyBtZXJnZSByZXF1ZXN0IGV2ZW50IGFuZCByZXN1bHQgZXZlbnQgKHJlc3VsdCBwcmV2YWlscykuXG4gIHJldHVybiB7XG4gICAgLi4uY2ZuUmVxdWVzdCxcbiAgICAuLi5oYW5kbGVyUmVzcG9uc2UsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN1Ym1pdFJlc3BvbnNlKHN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCcsIGV2ZW50OiBSZXNwb25zZSkge1xuICBjb25zdCBqc29uOiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlID0ge1xuICAgIFN0YXR1czogc3RhdHVzLFxuICAgIFJlYXNvbjogZXZlbnQuUmVhc29uID8/IHN0YXR1cyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIHx8IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBOb0VjaG86IGV2ZW50Lk5vRWNobyxcbiAgICBEYXRhOiBldmVudC5EYXRhLFxuICB9O1xuXG4gIGV4dGVybmFsLmxvZygnc3VibWl0IHJlc3BvbnNlIHRvIGNsb3VkZm9ybWF0aW9uJywganNvbik7XG5cbiAgY29uc3QgcmVzcG9uc2VCb2R5ID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XG4gIGNvbnN0IHBhcnNlZFVybCA9IHVybC5wYXJzZShldmVudC5SZXNwb25zZVVSTCk7XG4gIGNvbnN0IHJlcSA9IHtcbiAgICBob3N0bmFtZTogcGFyc2VkVXJsLmhvc3RuYW1lLFxuICAgIHBhdGg6IHBhcnNlZFVybC5wYXRoLFxuICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgaGVhZGVyczogeyAnY29udGVudC10eXBlJzogJycsICdjb250ZW50LWxlbmd0aCc6IHJlc3BvbnNlQm9keS5sZW5ndGggfSxcbiAgfTtcblxuICBhd2FpdCBleHRlcm5hbC5zZW5kSHR0cFJlcXVlc3QocmVxLCByZXNwb25zZUJvZHkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCBfID0+IHJlc29sdmUoKSk7XG4gICAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICByZXF1ZXN0LndyaXRlKHJlc3BvbnNlQm9keSk7XG4gICAgICByZXF1ZXN0LmVuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJlamVjdChlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TG9nKGZtdDogc3RyaW5nLCAuLi5wYXJhbXM6IGFueVtdKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGZtdCwgLi4ucGFyYW1zKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.d.ts b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.d.ts deleted file mode 100644 index 3554dc94d4617..0000000000000 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare function handler(event: AWSLambda.CloudFormationCustomResourceEvent): Promise; diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js deleted file mode 100644 index 7ce4156d4ba41..0000000000000 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js +++ /dev/null @@ -1,78 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.handler = void 0; -// eslint-disable-next-line import/no-extraneous-dependencies -const aws_sdk_1 = require("aws-sdk"); -const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; -const s3 = new aws_sdk_1.S3(); -async function handler(event) { - switch (event.RequestType) { - case 'Create': - return; - case 'Update': - return onUpdate(event); - case 'Delete': - return onDelete(event.ResourceProperties?.BucketName); - } -} -exports.handler = handler; -async function onUpdate(event) { - const updateEvent = event; - const oldBucketName = updateEvent.OldResourceProperties?.BucketName; - const newBucketName = updateEvent.ResourceProperties?.BucketName; - const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; - /* If the name of the bucket has changed, CloudFormation will try to delete the bucket - and create a new one with the new name. So we have to delete the contents of the - bucket so that this operation does not fail. */ - if (bucketNameHasChanged) { - return onDelete(oldBucketName); - } -} -/** - * Recursively delete all items in the bucket - * - * @param bucketName the bucket name - */ -async function emptyBucket(bucketName) { - const listedObjects = await s3.listObjectVersions({ Bucket: bucketName }).promise(); - const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; - if (contents.length === 0) { - return; - } - const records = contents.map((record) => ({ Key: record.Key, VersionId: record.VersionId })); - await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); - if (listedObjects?.IsTruncated) { - await emptyBucket(bucketName); - } -} -async function onDelete(bucketName) { - if (!bucketName) { - throw new Error('No BucketName was provided.'); - } - if (!await isBucketTaggedForDeletion(bucketName)) { - process.stdout.write(`Bucket does not have '${AUTO_DELETE_OBJECTS_TAG}' tag, skipping cleaning.\n`); - return; - } - try { - await emptyBucket(bucketName); - } - catch (e) { - if (e.code !== 'NoSuchBucket') { - throw e; - } - // Bucket doesn't exist. Ignoring - } -} -/** - * The bucket will only be tagged for deletion if it's being deleted in the same - * deployment as this Custom Resource. - * - * If the Custom Resource is every deleted before the bucket, it must be because - * `autoDeleteObjects` has been switched to false, in which case the tag would have - * been removed before we get to this Delete event. - */ -async function isBucketTaggedForDeletion(bucketName) { - const response = await s3.getBucketTagging({ Bucket: bucketName }).promise(); - return response.TagSet.some(tag => tag.Key === AUTO_DELETE_OBJECTS_TAG && tag.Value === 'true'); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0QscUNBQTZCO0FBRTdCLE1BQU0sdUJBQXVCLEdBQUcsNkJBQTZCLENBQUM7QUFFOUQsTUFBTSxFQUFFLEdBQUcsSUFBSSxZQUFFLEVBQUUsQ0FBQztBQUViLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7SUFDOUUsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3pCLEtBQUssUUFBUTtZQUNYLE9BQU87UUFDVCxLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUM7S0FDekQ7QUFDSCxDQUFDO0FBVEQsMEJBU0M7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLEtBQWtEO0lBQ3hFLE1BQU0sV0FBVyxHQUFHLEtBQTBELENBQUM7SUFDL0UsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDLHFCQUFxQixFQUFFLFVBQVUsQ0FBQztJQUNwRSxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDO0lBQ2pFLE1BQU0sb0JBQW9CLEdBQUcsYUFBYSxJQUFJLElBQUksSUFBSSxhQUFhLElBQUksSUFBSSxJQUFJLGFBQWEsS0FBSyxhQUFhLENBQUM7SUFFL0c7O3NEQUVrRDtJQUNsRCxJQUFJLG9CQUFvQixFQUFFO1FBQ3hCLE9BQU8sUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0tBQ2hDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsV0FBVyxDQUFDLFVBQWtCO0lBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLEdBQUcsYUFBYSxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN6RixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3pCLE9BQU87S0FDUjtJQUVELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLEVBQUUsQ0FBQyxhQUFhLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFFdkYsSUFBSSxhQUFhLEVBQUUsV0FBVyxFQUFFO1FBQzlCLE1BQU0sV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0tBQy9CO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsVUFBbUI7SUFDekMsSUFBSSxDQUFDLFVBQVUsRUFBRTtRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztLQUNoRDtJQUNELElBQUksQ0FBQyxNQUFNLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQ2hELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5Qix1QkFBdUIsNkJBQTZCLENBQUMsQ0FBQztRQUNwRyxPQUFPO0tBQ1I7SUFDRCxJQUFJO1FBQ0YsTUFBTSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7S0FDL0I7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxjQUFjLEVBQUU7WUFDN0IsTUFBTSxDQUFDLENBQUM7U0FDVDtRQUNELGlDQUFpQztLQUNsQztBQUNILENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLHlCQUF5QixDQUFDLFVBQWtCO0lBQ3pELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDN0UsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssdUJBQXVCLElBQUksR0FBRyxDQUFDLEtBQUssS0FBSyxNQUFNLENBQUMsQ0FBQztBQUNsRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgUzMgfSBmcm9tICdhd3Mtc2RrJztcblxuY29uc3QgQVVUT19ERUxFVEVfT0JKRUNUU19UQUcgPSAnYXdzLWNkazphdXRvLWRlbGV0ZS1vYmplY3RzJztcblxuY29uc3QgczMgPSBuZXcgUzMoKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgc3dpdGNoIChldmVudC5SZXF1ZXN0VHlwZSkge1xuICAgIGNhc2UgJ0NyZWF0ZSc6XG4gICAgICByZXR1cm47XG4gICAgY2FzZSAnVXBkYXRlJzpcbiAgICAgIHJldHVybiBvblVwZGF0ZShldmVudCk7XG4gICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgIHJldHVybiBvbkRlbGV0ZShldmVudC5SZXNvdXJjZVByb3BlcnRpZXM/LkJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uVXBkYXRlKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50KSB7XG4gIGNvbnN0IHVwZGF0ZUV2ZW50ID0gZXZlbnQgYXMgQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VVcGRhdGVFdmVudDtcbiAgY29uc3Qgb2xkQnVja2V0TmFtZSA9IHVwZGF0ZUV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZTtcbiAgY29uc3QgbmV3QnVja2V0TmFtZSA9IHVwZGF0ZUV2ZW50LlJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZTtcbiAgY29uc3QgYnVja2V0TmFtZUhhc0NoYW5nZWQgPSBuZXdCdWNrZXROYW1lICE9IG51bGwgJiYgb2xkQnVja2V0TmFtZSAhPSBudWxsICYmIG5ld0J1Y2tldE5hbWUgIT09IG9sZEJ1Y2tldE5hbWU7XG5cbiAgLyogSWYgdGhlIG5hbWUgb2YgdGhlIGJ1Y2tldCBoYXMgY2hhbmdlZCwgQ2xvdWRGb3JtYXRpb24gd2lsbCB0cnkgdG8gZGVsZXRlIHRoZSBidWNrZXRcbiAgICAgYW5kIGNyZWF0ZSBhIG5ldyBvbmUgd2l0aCB0aGUgbmV3IG5hbWUuIFNvIHdlIGhhdmUgdG8gZGVsZXRlIHRoZSBjb250ZW50cyBvZiB0aGVcbiAgICAgYnVja2V0IHNvIHRoYXQgdGhpcyBvcGVyYXRpb24gZG9lcyBub3QgZmFpbC4gKi9cbiAgaWYgKGJ1Y2tldE5hbWVIYXNDaGFuZ2VkKSB7XG4gICAgcmV0dXJuIG9uRGVsZXRlKG9sZEJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgZGVsZXRlIGFsbCBpdGVtcyBpbiB0aGUgYnVja2V0XG4gKlxuICogQHBhcmFtIGJ1Y2tldE5hbWUgdGhlIGJ1Y2tldCBuYW1lXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVtcHR5QnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICBjb25zdCBsaXN0ZWRPYmplY3RzID0gYXdhaXQgczMubGlzdE9iamVjdFZlcnNpb25zKHsgQnVja2V0OiBidWNrZXROYW1lIH0pLnByb21pc2UoKTtcbiAgY29uc3QgY29udGVudHMgPSBbLi4ubGlzdGVkT2JqZWN0cy5WZXJzaW9ucyA/PyBbXSwgLi4ubGlzdGVkT2JqZWN0cy5EZWxldGVNYXJrZXJzID8/IFtdXTtcbiAgaWYgKGNvbnRlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHJlY29yZHMgPSBjb250ZW50cy5tYXAoKHJlY29yZDogYW55KSA9PiAoeyBLZXk6IHJlY29yZC5LZXksIFZlcnNpb25JZDogcmVjb3JkLlZlcnNpb25JZCB9KSk7XG4gIGF3YWl0IHMzLmRlbGV0ZU9iamVjdHMoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUsIERlbGV0ZTogeyBPYmplY3RzOiByZWNvcmRzIH0gfSkucHJvbWlzZSgpO1xuXG4gIGlmIChsaXN0ZWRPYmplY3RzPy5Jc1RydW5jYXRlZCkge1xuICAgIGF3YWl0IGVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uRGVsZXRlKGJ1Y2tldE5hbWU/OiBzdHJpbmcpIHtcbiAgaWYgKCFidWNrZXROYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdObyBCdWNrZXROYW1lIHdhcyBwcm92aWRlZC4nKTtcbiAgfVxuICBpZiAoIWF3YWl0IGlzQnVja2V0VGFnZ2VkRm9yRGVsZXRpb24oYnVja2V0TmFtZSkpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgQnVja2V0IGRvZXMgbm90IGhhdmUgJyR7QVVUT19ERUxFVEVfT0JKRUNUU19UQUd9JyB0YWcsIHNraXBwaW5nIGNsZWFuaW5nLlxcbmApO1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IGVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUuY29kZSAhPT0gJ05vU3VjaEJ1Y2tldCcpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIC8vIEJ1Y2tldCBkb2Vzbid0IGV4aXN0LiBJZ25vcmluZ1xuICB9XG59XG5cbi8qKlxuICogVGhlIGJ1Y2tldCB3aWxsIG9ubHkgYmUgdGFnZ2VkIGZvciBkZWxldGlvbiBpZiBpdCdzIGJlaW5nIGRlbGV0ZWQgaW4gdGhlIHNhbWVcbiAqIGRlcGxveW1lbnQgYXMgdGhpcyBDdXN0b20gUmVzb3VyY2UuXG4gKlxuICogSWYgdGhlIEN1c3RvbSBSZXNvdXJjZSBpcyBldmVyeSBkZWxldGVkIGJlZm9yZSB0aGUgYnVja2V0LCBpdCBtdXN0IGJlIGJlY2F1c2VcbiAqIGBhdXRvRGVsZXRlT2JqZWN0c2AgaGFzIGJlZW4gc3dpdGNoZWQgdG8gZmFsc2UsIGluIHdoaWNoIGNhc2UgdGhlIHRhZyB3b3VsZCBoYXZlXG4gKiBiZWVuIHJlbW92ZWQgYmVmb3JlIHdlIGdldCB0byB0aGlzIERlbGV0ZSBldmVudC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaXNCdWNrZXRUYWdnZWRGb3JEZWxldGlvbihidWNrZXROYW1lOiBzdHJpbmcpIHtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzMy5nZXRCdWNrZXRUYWdnaW5nKHsgQnVja2V0OiBidWNrZXROYW1lIH0pLnByb21pc2UoKTtcbiAgcmV0dXJuIHJlc3BvbnNlLlRhZ1NldC5zb21lKHRhZyA9PiB0YWcuS2V5ID09PSBBVVRPX0RFTEVURV9PQkpFQ1RTX1RBRyAmJiB0YWcuVmFsdWUgPT09ICd0cnVlJyk7XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.ts b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.ts deleted file mode 100644 index 2459d44ab1d18..0000000000000 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.ts +++ /dev/null @@ -1,82 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { S3 } from 'aws-sdk'; - -const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; - -const s3 = new S3(); - -export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { - switch (event.RequestType) { - case 'Create': - return; - case 'Update': - return onUpdate(event); - case 'Delete': - return onDelete(event.ResourceProperties?.BucketName); - } -} - -async function onUpdate(event: AWSLambda.CloudFormationCustomResourceEvent) { - const updateEvent = event as AWSLambda.CloudFormationCustomResourceUpdateEvent; - const oldBucketName = updateEvent.OldResourceProperties?.BucketName; - const newBucketName = updateEvent.ResourceProperties?.BucketName; - const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; - - /* If the name of the bucket has changed, CloudFormation will try to delete the bucket - and create a new one with the new name. So we have to delete the contents of the - bucket so that this operation does not fail. */ - if (bucketNameHasChanged) { - return onDelete(oldBucketName); - } -} - -/** - * Recursively delete all items in the bucket - * - * @param bucketName the bucket name - */ -async function emptyBucket(bucketName: string) { - const listedObjects = await s3.listObjectVersions({ Bucket: bucketName }).promise(); - const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; - if (contents.length === 0) { - return; - } - - const records = contents.map((record: any) => ({ Key: record.Key, VersionId: record.VersionId })); - await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); - - if (listedObjects?.IsTruncated) { - await emptyBucket(bucketName); - } -} - -async function onDelete(bucketName?: string) { - if (!bucketName) { - throw new Error('No BucketName was provided.'); - } - if (!await isBucketTaggedForDeletion(bucketName)) { - process.stdout.write(`Bucket does not have '${AUTO_DELETE_OBJECTS_TAG}' tag, skipping cleaning.\n`); - return; - } - try { - await emptyBucket(bucketName); - } catch (e) { - if (e.code !== 'NoSuchBucket') { - throw e; - } - // Bucket doesn't exist. Ignoring - } -} - -/** - * The bucket will only be tagged for deletion if it's being deleted in the same - * deployment as this Custom Resource. - * - * If the Custom Resource is every deleted before the bucket, it must be because - * `autoDeleteObjects` has been switched to false, in which case the tag would have - * been removed before we get to this Delete event. - */ -async function isBucketTaggedForDeletion(bucketName: string) { - const response = await s3.getBucketTagging({ Bucket: bucketName }).promise(); - return response.TagSet.some(tag => tag.Key === AUTO_DELETE_OBJECTS_TAG && tag.Value === 'true'); -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.assets.json index 94c8de453b3b8..e179c2a016345 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.assets.json @@ -1,28 +1,28 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824": { + "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb": { "source": { - "path": "asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", + "path": "asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824.zip", + "objectKey": "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "01e9cf93416a1f67b17dad851459445bdaaafcc2f3ab4390c03984fd57b2f476": { + "9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7": { "source": { - "path": "asset.01e9cf93416a1f67b17dad851459445bdaaafcc2f3ab4390c03984fd57b2f476.zip", + "path": "asset.9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7.zip", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "01e9cf93416a1f67b17dad851459445bdaaafcc2f3ab4390c03984fd57b2f476.zip", + "objectKey": "9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -66,7 +66,7 @@ } } }, - "9f4f5517a472e263ebefe980b14927752a617d1f89b759330046e586893fee58": { + "0470cd0f2732f264b2932cdb44082afcf0d6c96eb67566fdbb5a1363a1ceb621": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -74,7 +74,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9f4f5517a472e263ebefe980b14927752a617d1f89b759330046e586893fee58.json", + "objectKey": "0470cd0f2732f264b2932cdb44082afcf0d6c96eb67566fdbb5a1363a1ceb621.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.template.json index 32bdbba1a3c0a..0f3734dc75d0e 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/aws-ecs-integ.template.json @@ -120,7 +120,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3Bucket09A62232" + "Ref": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3Bucket196AD8D5" }, "S3Key": { "Fn::Join": [ @@ -133,7 +133,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3VersionKeyA28118BE" + "Ref": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3VersionKey53E5B9FA" } ] } @@ -146,7 +146,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3VersionKeyA28118BE" + "Ref": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3VersionKey53E5B9FA" } ] } @@ -891,7 +891,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ @@ -1186,7 +1186,7 @@ "Properties": { "Content": { "S3Bucket": { - "Ref": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3Bucket16472AE2" + "Ref": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3Bucket9BBA77AD" }, "S3Key": { "Fn::Join": [ @@ -1199,7 +1199,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A" + "Ref": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B" } ] } @@ -1212,7 +1212,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A" + "Ref": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B" } ] } @@ -1525,29 +1525,29 @@ } }, "Parameters": { - "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3Bucket09A62232": { + "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3Bucket196AD8D5": { "Type": "String", - "Description": "S3 bucket for asset \"be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824\"" + "Description": "S3 bucket for asset \"17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb\"" }, - "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3VersionKeyA28118BE": { + "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3VersionKey53E5B9FA": { "Type": "String", - "Description": "S3 key for asset version \"be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824\"" + "Description": "S3 key for asset version \"17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb\"" }, - "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824ArtifactHash76F8FCF2": { + "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbArtifactHash35F1B2CD": { "Type": "String", - "Description": "Artifact hash for asset \"be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824\"" + "Description": "Artifact hash for asset \"17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb\"" }, - "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3Bucket16472AE2": { + "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3Bucket9BBA77AD": { "Type": "String", - "Description": "S3 bucket for asset \"8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a\"" + "Description": "S3 bucket for asset \"9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7\"" }, - "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A": { + "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B": { "Type": "String", - "Description": "S3 key for asset version \"8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a\"" + "Description": "S3 key for asset version \"9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7\"" }, - "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aArtifactHash08E93340": { + "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7ArtifactHash38855E14": { "Type": "String", - "Description": "Artifact hash for asset \"8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a\"" + "Description": "Artifact hash for asset \"9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7\"" }, "AssetParametersf98b78092dcdd31f5e6d47489beb5f804d4835ef86a8085d0a2053cb9ae711daS3BucketF23C0DE7": { "Type": "String", diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/manifest.json index 02d9340ebb26e..808e6da4d46de 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/manifest.json @@ -19,25 +19,25 @@ { "type": "aws:cdk:asset", "data": { - "path": "asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", - "id": "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", + "path": "asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb", + "id": "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb", "packaging": "zip", - "sourceHash": "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", - "s3BucketParameter": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3Bucket09A62232", - "s3KeyParameter": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3VersionKeyA28118BE", - "artifactHashParameter": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824ArtifactHash76F8FCF2" + "sourceHash": "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb", + "s3BucketParameter": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3Bucket196AD8D5", + "s3KeyParameter": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3VersionKey53E5B9FA", + "artifactHashParameter": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbArtifactHash35F1B2CD" } }, { "type": "aws:cdk:asset", "data": { - "path": "asset.8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a.zip", - "id": "8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a", + "path": "asset.9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7.zip", + "id": "9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7", "packaging": "file", - "sourceHash": "8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a", - "s3BucketParameter": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3Bucket16472AE2", - "s3KeyParameter": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A", - "artifactHashParameter": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aArtifactHash08E93340" + "sourceHash": "9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7", + "s3BucketParameter": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3Bucket9BBA77AD", + "s3KeyParameter": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B", + "artifactHashParameter": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7ArtifactHash38855E14" } }, { @@ -107,40 +107,40 @@ "data": "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F" } ], - "/aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/S3Bucket": [ + "/aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/S3Bucket": [ { "type": "aws:cdk:logicalId", - "data": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3Bucket09A62232" + "data": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3Bucket196AD8D5" } ], - "/aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/S3VersionKey": [ + "/aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/S3VersionKey": [ { "type": "aws:cdk:logicalId", - "data": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824S3VersionKeyA28118BE" + "data": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbS3VersionKey53E5B9FA" } ], - "/aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/ArtifactHash": [ + "/aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/ArtifactHash": [ { "type": "aws:cdk:logicalId", - "data": "AssetParametersbe270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824ArtifactHash76F8FCF2" + "data": "AssetParameters17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccbArtifactHash35F1B2CD" } ], - "/aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a/S3Bucket": [ + "/aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7/S3Bucket": [ { "type": "aws:cdk:logicalId", - "data": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3Bucket16472AE2" + "data": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3Bucket9BBA77AD" } ], - "/aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a/S3VersionKey": [ + "/aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7/S3VersionKey": [ { "type": "aws:cdk:logicalId", - "data": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A" + "data": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B" } ], - "/aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a/ArtifactHash": [ + "/aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7/ArtifactHash": [ { "type": "aws:cdk:logicalId", - "data": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aArtifactHash08E93340" + "data": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7ArtifactHash38855E14" } ], "/aws-ecs-integ/AssetParameters/f98b78092dcdd31f5e6d47489beb5f804d4835ef86a8085d0a2053cb9ae711da/S3Bucket": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/tree.json index 4f286629bab77..a8afb7f3d8803 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/environment-file.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -180,13 +180,13 @@ "id": "AssetParameters", "path": "aws-ecs-integ/AssetParameters", "children": { - "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824": { - "id": "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", - "path": "aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", + "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb": { + "id": "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb", + "path": "aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb", "children": { "S3Bucket": { "id": "S3Bucket", - "path": "aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/S3Bucket", + "path": "aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/S3Bucket", "constructInfo": { "fqn": "@aws-cdk/core.CfnParameter", "version": "0.0.0" @@ -194,7 +194,7 @@ }, "S3VersionKey": { "id": "S3VersionKey", - "path": "aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/S3VersionKey", + "path": "aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/S3VersionKey", "constructInfo": { "fqn": "@aws-cdk/core.CfnParameter", "version": "0.0.0" @@ -202,7 +202,7 @@ }, "ArtifactHash": { "id": "ArtifactHash", - "path": "aws-ecs-integ/AssetParameters/be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/ArtifactHash", + "path": "aws-ecs-integ/AssetParameters/17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/ArtifactHash", "constructInfo": { "fqn": "@aws-cdk/core.CfnParameter", "version": "0.0.0" @@ -211,16 +211,16 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, - "8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a": { - "id": "8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a", - "path": "aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a", + "9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7": { + "id": "9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7", + "path": "aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7", "children": { "S3Bucket": { "id": "S3Bucket", - "path": "aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a/S3Bucket", + "path": "aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7/S3Bucket", "constructInfo": { "fqn": "@aws-cdk/core.CfnParameter", "version": "0.0.0" @@ -228,7 +228,7 @@ }, "S3VersionKey": { "id": "S3VersionKey", - "path": "aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a/S3VersionKey", + "path": "aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7/S3VersionKey", "constructInfo": { "fqn": "@aws-cdk/core.CfnParameter", "version": "0.0.0" @@ -236,7 +236,7 @@ }, "ArtifactHash": { "id": "ArtifactHash", - "path": "aws-ecs-integ/AssetParameters/8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6a/ArtifactHash", + "path": "aws-ecs-integ/AssetParameters/9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7/ArtifactHash", "constructInfo": { "fqn": "@aws-cdk/core.CfnParameter", "version": "0.0.0" @@ -245,7 +245,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "f98b78092dcdd31f5e6d47489beb5f804d4835ef86a8085d0a2053cb9ae711da": { @@ -279,7 +279,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "972240f9dd6e036a93d5f081af9a24315b2053828ac049b3b19b2fa12d7ae64a": { @@ -313,7 +313,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "872561bf078edd1685d50c9ff821cdd60d2b2ddfb0013c4087e79bf2bb50724d": { @@ -347,13 +347,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "Vpc": { @@ -1454,7 +1454,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1551,7 +1551,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { @@ -1975,7 +1975,7 @@ "aws:cdk:cloudformation:props": { "content": { "s3Bucket": { - "Ref": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3Bucket16472AE2" + "Ref": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3Bucket9BBA77AD" }, "s3Key": { "Fn::Join": [ @@ -1988,7 +1988,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A" + "Ref": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B" } ] } @@ -2001,7 +2001,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters8ad7bbf8be94e05d569da95ddb82511dcc959f25054825394cbb86028ccd1b6aS3VersionKeyFAAA537A" + "Ref": "AssetParameters9224197a0988613189788525036306b333034895bb69a8220b40e52dced6a8b7S3VersionKeyCDBA2F4B" } ] } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.assets.json index 30ddde02c66f8..59f8f48cda05a 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "777bde7edf0b72b31bd3dfe7978b49e6226738f4d5bb7ce52dc86eb07f5ab11b": { + "3bda9b483be4720f02c18f2d5701a3ce8f2a778360731a0c2dcc62837de2819a": { "source": { "path": "aws-ecs-integ-exec-command.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "777bde7edf0b72b31bd3dfe7978b49e6226738f4d5bb7ce52dc86eb07f5ab11b.json", + "objectKey": "3bda9b483be4720f02c18f2d5701a3ce8f2a778360731a0c2dcc62837de2819a.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.template.json index 11811c31cbbb0..e1dddfed2b44c 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/aws-ecs-integ-exec-command.template.json @@ -852,7 +852,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/tree.json index 671c7b10ec541..bc63a2ad0e997 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/exec-command.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-exec-command": { @@ -1305,7 +1305,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1402,7 +1402,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.assets.json index acd89a55a0bb4..76f30fcff9f13 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.assets.json @@ -1,5 +1,5 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { "2ca891b3a73a4a36630bba20580e3390a104d2ac9ff1f22a6bcadf575f8a5a61": { "source": { @@ -14,7 +14,7 @@ } } }, - "3c4700849a24aae47192423919135347dc96616a3269cd5b6420c78f704908ac": { + "01584d25438205ef278fbf01a671fd340ab6bbb6a0d69ec5f3c0640cd15b3f18": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3c4700849a24aae47192423919135347dc96616a3269cd5b6420c78f704908ac.json", + "objectKey": "01584d25438205ef278fbf01a671fd340ab6bbb6a0d69ec5f3c0640cd15b3f18.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.template.json index 9d794f4e0302c..266f93c3d6a3f 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/aws-ecs-integ.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/tree.json index 45ce77e2e4ed5..dd8ad6a477634 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/firelens-s3-config.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { @@ -1819,13 +1819,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "SsmParameterValue:--aws--service--aws-for-fluent-bit--2.1.0:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.assets.json index 28338c44bbb31..757436e5f3034 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "2ecc17004e9391b2ef3321bf479bdd48424cdde971a6e82d0debc3e4a2f51291": { + "6d7a13d2995a1e7d3b3c347527801589af873a83af2c3538de5edcdc5d51ee68": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2ecc17004e9391b2ef3321bf479bdd48424cdde971a6e82d0debc3e4a2f51291.json", + "objectKey": "6d7a13d2995a1e7d3b3c347527801589af873a83af2c3538de5edcdc5d51ee68.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.template.json index 4d5c0c9343359..8553db7fe5945 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/aws-ecs-integ.template.json @@ -734,7 +734,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/tree.json index 18b857c7b1067..ce00db8ab790d 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/graviton-bottlerocket.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1140,7 +1140,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1237,7 +1237,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.assets.json index f85d28f195504..042b8661405e2 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "8d9a913948699c0797f7a7c8864ed87c4d276a4bdc2d894b2e144dc7a2730e7f": { + "a3a4ae53bc89e74287961a849517b5f064b534fac500b07c8b50c68d8b4042f0": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8d9a913948699c0797f7a7c8864ed87c4d276a4bdc2d894b2e144dc7a2730e7f.json", + "objectKey": "a3a4ae53bc89e74287961a849517b5f064b534fac500b07c8b50c68d8b4042f0.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.template.json index 1952bc98db613..2953ae2f5225f 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/aws-ecs-integ.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/tree.json index 9ba440e26fa18..03352877a7de5 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/graviton.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.assets.json index e506d8adf6d52..4212a66e4d0ed 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "324a22da223d687db17405376ed72b0320275e13eb5d69db964ff86289479754": { + "0c104ab8e691f03c700d5423c521ef82f59cbe5b71dc410b487d2b2a82c098fa": { "source": { "path": "aws-ecs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "324a22da223d687db17405376ed72b0320275e13eb5d69db964ff86289479754.json", + "objectKey": "0c104ab8e691f03c700d5423c521ef82f59cbe5b71dc410b487d2b2a82c098fa.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.template.json index d0c888622ac88..90d5a55670af4 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/aws-ecs-integ.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/tree.json index ae2427745daeb..d8e8cb92a2363 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/lb-awsvpc-nw.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json index 66527a2375135..ad1d22262ddcb 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "88288789b4eaa54ca379bd257e8d7b83fdf3e9e984373f94b4edf5f0f8150226": { + "5820dedacd5953116e248340791754ee29538c5b5afa9f7e385f04371d457c4d": { "source": { "path": "aws-ecs-integ-ecs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "88288789b4eaa54ca379bd257e8d7b83fdf3e9e984373f94b4edf5f0f8150226.json", + "objectKey": "5820dedacd5953116e248340791754ee29538c5b5afa9f7e385f04371d457c4d.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json index 08e02e1903690..0b813f3e1917b 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json @@ -729,7 +729,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/tree.json index 4dd3076b19212..049626e4ab31b 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/lb-bridge-nw.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-ecs": { @@ -1143,7 +1143,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1240,7 +1240,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json index b25962f31390a..7adcb7216e057 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "b41479382315bf2719d6399d980a7514e37ea1654e2d11dc71302e9406d3e7a6": { + "234e639642cfbf2437cd48a4592a15f7e06058ae9b1c803da6c4b8217acecf77": { "source": { "path": "aws-ecs-integ-ecs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b41479382315bf2719d6399d980a7514e37ea1654e2d11dc71302e9406d3e7a6.json", + "objectKey": "234e639642cfbf2437cd48a4592a15f7e06058ae9b1c803da6c4b8217acecf77.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.template.json index 9f1ccdb2d29b5..249c70cbd385d 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/aws-ecs-integ-ecs.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/tree.json index 1cd2c2c4326e9..c319c897a4be0 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/sd-awsvpc-nw.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-ecs": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json index 56adfc3343591..eab123697337f 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "8da36a4fc2258a02d47490ee2e834672042e61161b3267dbe84ae96120e613c6": { + "7b5c0d4027664acc9fd16a0138cae81796d73cfac96ecac213d8f70477737c9e": { "source": { "path": "aws-ecs-integ-ecs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8da36a4fc2258a02d47490ee2e834672042e61161b3267dbe84ae96120e613c6.json", + "objectKey": "7b5c0d4027664acc9fd16a0138cae81796d73cfac96ecac213d8f70477737c9e.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json index 95436e4851d87..18f1537133829 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/aws-ecs-integ-ecs.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/tree.json index ffbeaf72a6ebb..2951e440da795 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/sd-bridge-nw.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-ecs": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.assets.json b/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.assets.json index 2e9210a9ec9bc..d91cccf8825b6 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.assets.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "510ea00ffe058b6a6c75c91b1432aa5d3c873fb590f1fee6c666b4b5555d0171": { + "20644bf6267ed004d956fd15e2579db74eeb6ab4f453bb31e98bb6388cee922b": { "source": { "path": "aws-ecs-integ-spot.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "510ea00ffe058b6a6c75c91b1432aa5d3c873fb590f1fee6c666b4b5555d0171.json", + "objectKey": "20644bf6267ed004d956fd15e2579db74eeb6ab4f453bb31e98bb6388cee922b.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.template.json b/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.template.json index 6ff3b71cbac99..726fdf79ea267 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.template.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/aws-ecs-integ-spot.template.json @@ -710,7 +710,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ @@ -1175,7 +1175,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/tree.json index 6380f1599dc17..a99edd53c4646 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/spot-drain.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-spot": { @@ -1116,7 +1116,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1213,7 +1213,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { @@ -1811,7 +1811,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1908,7 +1908,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-eks-legacy/lib/cluster-resource/index.py b/packages/@aws-cdk/aws-eks-legacy/lib/cluster-resource/index.py index 07cad9a8db1ba..d641e03b7e2a3 100644 --- a/packages/@aws-cdk/aws-eks-legacy/lib/cluster-resource/index.py +++ b/packages/@aws-cdk/aws-eks-legacy/lib/cluster-resource/index.py @@ -27,7 +27,7 @@ def cfn_error(message=None): cfn_send(event, context, CFN_FAILED, reason=message) try: - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) stack_id = event['StackId'] request_id = event['RequestId'] # used to generate cluster name @@ -75,12 +75,12 @@ def should_replace_cluster(): if old_resourcesVpcConfig != resourcesVpcConfig: logger.info("'resourcesVpcConfig' change requires replacement (old=%s, new=%s)" % (old_resourcesVpcConfig, resourcesVpcConfig)) return True - + old_roleArn = old_config.get('roleArn', None) if old_roleArn != roleArn: logger.info("'roleArn' change requires replacement (old=%s, new=%s)" % (old_roleArn, roleArn)) return True - + return False # delete is a special case diff --git a/packages/@aws-cdk/aws-eks-legacy/lib/helm-chart/index.py b/packages/@aws-cdk/aws-eks-legacy/lib/helm-chart/index.py index 0b311f61e0fcd..838ae8e5d0c57 100644 --- a/packages/@aws-cdk/aws-eks-legacy/lib/helm-chart/index.py +++ b/packages/@aws-cdk/aws-eks-legacy/lib/helm-chart/index.py @@ -25,7 +25,7 @@ def cfn_error(message=None): cfn_send(event, context, CFN_FAILED, reason=message) try: - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) request_type = event['RequestType'] props = event['ResourceProperties'] @@ -41,7 +41,7 @@ def cfn_error(message=None): if cluster_name is None: cfn_error("CLUSTER_NAME is missing in environment") return - + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', '--name', cluster_name, '--kubeconfig', kubeconfig diff --git a/packages/@aws-cdk/aws-eks-legacy/lib/k8s-resource/index.py b/packages/@aws-cdk/aws-eks-legacy/lib/k8s-resource/index.py index 3f16e9cb5a305..b58640fa432b0 100644 --- a/packages/@aws-cdk/aws-eks-legacy/lib/k8s-resource/index.py +++ b/packages/@aws-cdk/aws-eks-legacy/lib/k8s-resource/index.py @@ -25,7 +25,7 @@ def cfn_error(message=None): cfn_send(event, context, CFN_FAILED, reason=message) try: - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) request_type = event['RequestType'] props = event['ResourceProperties'] diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py index 038d379f8478a..60984a21a41e0 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/apply/__init__.py @@ -14,7 +14,7 @@ def apply_handler(event, context): - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) request_type = event['RequestType'] props = event['ResourceProperties'] diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py index 4fb3b162765ca..2811dca09cf1e 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/get/__init__.py @@ -15,7 +15,7 @@ def get_handler(event, context): - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) request_type = event['RequestType'] props = event['ResourceProperties'] diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py index f1bb6a0dbdd9c..b9a741c8972c4 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/helm/__init__.py @@ -29,7 +29,7 @@ def get_chart_asset_from_url(chart_asset_url): return chart_dir def helm_handler(event, context): - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) request_type = event['RequestType'] props = event['ResourceProperties'] diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/index.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/index.py index 60b6ce78b2af6..26f5b116f8dc5 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/index.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/index.py @@ -7,7 +7,7 @@ from get import get_handler def handler(event, context): - print(json.dumps(event)) + print(json.dumps(dict(event, ResponseURL='...'))) resource_type = event['ResourceType'] if resource_type == 'Custom::AWSCDK-EKS-KubernetesResource': diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py index a18455663b7f3..d7a73c67ee88d 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-handler/patch/__init__.py @@ -14,7 +14,7 @@ def patch_handler(event, context): - logger.info(json.dumps(event)) + logger.info(json.dumps(dict(event, ResponseURL='...'))) request_type = event['RequestType'] props = event['ResourceProperties'] diff --git a/packages/@aws-cdk/aws-eks/test/eks-oidc-provider.integ.snapshot/asset.5507835727e005832a615aef2a6b437860f432c6cd052d07c0244464aedbe2b2/index.js b/packages/@aws-cdk/aws-eks/test/eks-oidc-provider.integ.snapshot/asset.5507835727e005832a615aef2a6b437860f432c6cd052d07c0244464aedbe2b2/index.js index 12b78dec14ec7..6d3ea074b033e 100644 --- a/packages/@aws-cdk/aws-eks/test/eks-oidc-provider.integ.snapshot/asset.5507835727e005832a615aef2a6b437860f432c6cd052d07c0244464aedbe2b2/index.js +++ b/packages/@aws-cdk/aws-eks/test/eks-oidc-provider.integ.snapshot/asset.5507835727e005832a615aef2a6b437860f432c6cd052d07c0244464aedbe2b2/index.js @@ -17,10 +17,9 @@ async function handler(event) { } exports.handler = handler; async function onCreate(event) { - var _a, _b; const issuerUrl = event.ResourceProperties.Url; - const thumbprints = ((_a = event.ResourceProperties.ThumbprintList) !== null && _a !== void 0 ? _a : []).sort(); // keep sorted for UPDATE - const clients = ((_b = event.ResourceProperties.ClientIDList) !== null && _b !== void 0 ? _b : []).sort(); + const thumbprints = (event.ResourceProperties.ThumbprintList ?? []).sort(); // keep sorted for UPDATE + const clients = (event.ResourceProperties.ClientIDList ?? []).sort(); if (thumbprints.length === 0) { thumbprints.push(await external_1.external.downloadThumbprint(issuerUrl)); } @@ -34,10 +33,9 @@ async function onCreate(event) { }; } async function onUpdate(event) { - var _a, _b; const issuerUrl = event.ResourceProperties.Url; - const thumbprints = ((_a = event.ResourceProperties.ThumbprintList) !== null && _a !== void 0 ? _a : []).sort(); // keep sorted for UPDATE - const clients = ((_b = event.ResourceProperties.ClientIDList) !== null && _b !== void 0 ? _b : []).sort(); + const thumbprints = (event.ResourceProperties.ThumbprintList ?? []).sort(); // keep sorted for UPDATE + const clients = (event.ResourceProperties.ClientIDList ?? []).sort(); // determine which update we are talking about. const oldIssuerUrl = event.OldResourceProperties.Url; // if this is a URL update, then we basically create a new resource and cfn will delete the old one @@ -83,4 +81,4 @@ async function onDelete(deleteEvent) { OpenIDConnectProviderArn: deleteEvent.PhysicalResourceId, }); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpQ0FBbUM7QUFDbkMseUNBQXNDO0FBRS9CLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7SUFDOUUsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQUU7SUFDL0QsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQUU7SUFDL0QsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQUU7SUFDL0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBQzFDLENBQUM7QUFMRCwwQkFLQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsS0FBd0Q7O0lBQzlFLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUM7SUFDL0MsTUFBTSxXQUFXLEdBQWEsT0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsY0FBYyxtQ0FBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLHlCQUF5QjtJQUMvRyxNQUFNLE9BQU8sR0FBYSxPQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLG1DQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBRS9FLElBQUksV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDNUIsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLG1CQUFRLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztLQUNoRTtJQUVELE1BQU0sSUFBSSxHQUFHLE1BQU0sbUJBQVEsQ0FBQywyQkFBMkIsQ0FBQztRQUN0RCxHQUFHLEVBQUUsU0FBUztRQUNkLFlBQVksRUFBRSxPQUFPO1FBQ3JCLGNBQWMsRUFBRSxXQUFXO0tBQzVCLENBQUMsQ0FBQztJQUVILE9BQU87UUFDTCxrQkFBa0IsRUFBRSxJQUFJLENBQUMsd0JBQXdCO0tBQ2xELENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLFFBQVEsQ0FBQyxLQUF3RDs7SUFDOUUsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztJQUMvQyxNQUFNLFdBQVcsR0FBYSxPQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLG1DQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMseUJBQXlCO0lBQy9HLE1BQU0sT0FBTyxHQUFhLE9BQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFlBQVksbUNBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFL0UsK0NBQStDO0lBQy9DLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUM7SUFFckQsbUdBQW1HO0lBQ25HLDhDQUE4QztJQUM5QyxJQUFJLFlBQVksS0FBSyxTQUFTLEVBQUU7UUFDOUIsT0FBTyxRQUFRLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztLQUN0RDtJQUVELE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztJQUU3QyxtR0FBbUc7SUFDbkcsaUVBQWlFO0lBQ2pFLE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNqRixJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsRUFBRTtRQUNsRSxNQUFNLGNBQWMsR0FBRyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sbUJBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzdHLG1CQUFRLENBQUMsR0FBRyxDQUFDLCtCQUErQixFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDakYsTUFBTSxtQkFBUSxDQUFDLHFDQUFxQyxDQUFDO1lBQ25ELHdCQUF3QixFQUFFLFdBQVc7WUFDckMsY0FBYyxFQUFFLGNBQWM7U0FDL0IsQ0FBQyxDQUFDO1FBRUgsOENBQThDO0tBQy9DO0lBRUQsZ0ZBQWdGO0lBQ2hGLE1BQU0sVUFBVSxHQUFhLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFlBQVksSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNyRixNQUFNLElBQUksR0FBRyxnQkFBUyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM1QyxtQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFeEQsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ2pDLG1CQUFRLENBQUMsR0FBRyxDQUFDLHFCQUFxQixTQUFTLGlCQUFpQixXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLE1BQU0sbUJBQVEsQ0FBQyxrQ0FBa0MsQ0FBQztZQUNoRCx3QkFBd0IsRUFBRSxXQUFXO1lBQ3JDLFFBQVEsRUFBRSxTQUFTO1NBQ3BCLENBQUMsQ0FBQztLQUNKO0lBRUQsS0FBSyxNQUFNLFlBQVksSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1FBQ3ZDLG1CQUFRLENBQUMsR0FBRyxDQUFDLHVCQUF1QixZQUFZLG1CQUFtQixXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sbUJBQVEsQ0FBQyx1Q0FBdUMsQ0FBQztZQUNyRCx3QkFBd0IsRUFBRSxXQUFXO1lBQ3JDLFFBQVEsRUFBRSxZQUFZO1NBQ3ZCLENBQUMsQ0FBQztLQUNKO0lBRUQsT0FBTztBQUNULENBQUM7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLFdBQThEO0lBQ3BGLE1BQU0sbUJBQVEsQ0FBQywyQkFBMkIsQ0FBQztRQUN6Qyx3QkFBd0IsRUFBRSxXQUFXLENBQUMsa0JBQWtCO0tBQ3pELENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBhcnJheURpZmYgfSBmcm9tICcuL2RpZmYnO1xuaW1wb3J0IHsgZXh0ZXJuYWwgfSBmcm9tICcuL2V4dGVybmFsJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJykgeyByZXR1cm4gb25DcmVhdGUoZXZlbnQpOyB9XG4gIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScpIHsgcmV0dXJuIG9uVXBkYXRlKGV2ZW50KTsgfVxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnKSB7IHJldHVybiBvbkRlbGV0ZShldmVudCk7IH1cbiAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlcXVlc3QgdHlwZScpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBvbkNyZWF0ZShldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VDcmVhdGVFdmVudCkge1xuICBjb25zdCBpc3N1ZXJVcmwgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVXJsO1xuICBjb25zdCB0aHVtYnByaW50czogc3RyaW5nW10gPSAoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlRodW1icHJpbnRMaXN0ID8/IFtdKS5zb3J0KCk7IC8vIGtlZXAgc29ydGVkIGZvciBVUERBVEVcbiAgY29uc3QgY2xpZW50czogc3RyaW5nW10gPSAoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNsaWVudElETGlzdCA/PyBbXSkuc29ydCgpO1xuXG4gIGlmICh0aHVtYnByaW50cy5sZW5ndGggPT09IDApIHtcbiAgICB0aHVtYnByaW50cy5wdXNoKGF3YWl0IGV4dGVybmFsLmRvd25sb2FkVGh1bWJwcmludChpc3N1ZXJVcmwpKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3AgPSBhd2FpdCBleHRlcm5hbC5jcmVhdGVPcGVuSURDb25uZWN0UHJvdmlkZXIoe1xuICAgIFVybDogaXNzdWVyVXJsLFxuICAgIENsaWVudElETGlzdDogY2xpZW50cyxcbiAgICBUaHVtYnByaW50TGlzdDogdGh1bWJwcmludHMsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiByZXNwLk9wZW5JRENvbm5lY3RQcm92aWRlckFybixcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gb25VcGRhdGUoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlVXBkYXRlRXZlbnQpIHtcbiAgY29uc3QgaXNzdWVyVXJsID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlVybDtcbiAgY29uc3QgdGh1bWJwcmludHM6IHN0cmluZ1tdID0gKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5UaHVtYnByaW50TGlzdCA/PyBbXSkuc29ydCgpOyAvLyBrZWVwIHNvcnRlZCBmb3IgVVBEQVRFXG4gIGNvbnN0IGNsaWVudHM6IHN0cmluZ1tdID0gKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5DbGllbnRJRExpc3QgPz8gW10pLnNvcnQoKTtcblxuICAvLyBkZXRlcm1pbmUgd2hpY2ggdXBkYXRlIHdlIGFyZSB0YWxraW5nIGFib3V0LlxuICBjb25zdCBvbGRJc3N1ZXJVcmwgPSBldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMuVXJsO1xuXG4gIC8vIGlmIHRoaXMgaXMgYSBVUkwgdXBkYXRlLCB0aGVuIHdlIGJhc2ljYWxseSBjcmVhdGUgYSBuZXcgcmVzb3VyY2UgYW5kIGNmbiB3aWxsIGRlbGV0ZSB0aGUgb2xkIG9uZVxuICAvLyBzaW5jZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgd2lsbCBjaGFuZ2UuXG4gIGlmIChvbGRJc3N1ZXJVcmwgIT09IGlzc3VlclVybCkge1xuICAgIHJldHVybiBvbkNyZWF0ZSh7IC4uLmV2ZW50LCBSZXF1ZXN0VHlwZTogJ0NyZWF0ZScgfSk7XG4gIH1cblxuICBjb25zdCBwcm92aWRlckFybiA9IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZDtcblxuICAvLyBpZiB0aHVtYnByaW50cyBjaGFuZ2VkLCB3ZSBjYW4gdXBkYXRlIGluLXBsYWNlLCBidXQgYmVhciBpbiBtaW5kIHRoYXQgaWYgdGhlIG5ldyB0aHVtYnByaW50IGxpc3RcbiAgLy8gaXMgZW1wdHksIHdlIHdpbGwgZ3JhYiBpdCBmcm9tIHRoZSBzZXJ2ZXIgbGlrZSB3ZSBkbyBpbiBDUkVBVEVcbiAgY29uc3Qgb2xkVGh1bWJwcmludHMgPSAoZXZlbnQuT2xkUmVzb3VyY2VQcm9wZXJ0aWVzLlRodW1icHJpbnRMaXN0IHx8IFtdKS5zb3J0KCk7XG4gIGlmIChKU09OLnN0cmluZ2lmeShvbGRUaHVtYnByaW50cykgIT09IEpTT04uc3RyaW5naWZ5KHRodW1icHJpbnRzKSkge1xuICAgIGNvbnN0IHRodW1icHJpbnRMaXN0ID0gdGh1bWJwcmludHMubGVuZ3RoID4gMCA/IHRodW1icHJpbnRzIDogW2F3YWl0IGV4dGVybmFsLmRvd25sb2FkVGh1bWJwcmludChpc3N1ZXJVcmwpXTtcbiAgICBleHRlcm5hbC5sb2coJ3VwZGF0aW5nIHRodW1icHJpbnQgbGlzdCBmcm9tJywgb2xkVGh1bWJwcmludHMsICd0bycsIHRodW1icHJpbnRzKTtcbiAgICBhd2FpdCBleHRlcm5hbC51cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50KHtcbiAgICAgIE9wZW5JRENvbm5lY3RQcm92aWRlckFybjogcHJvdmlkZXJBcm4sXG4gICAgICBUaHVtYnByaW50TGlzdDogdGh1bWJwcmludExpc3QsXG4gICAgfSk7XG5cbiAgICAvLyBkb24ndCByZXR1cm4sIHdlIG1pZ2h0IGhhdmUgbW9yZSB1cGRhdGVzLi4uXG4gIH1cblxuICAvLyBpZiBjbGllbnQgSUQgbGlzdCBoYXMgY2hhbmdlZCwgZGV0ZXJtaW5lIFwiZGlmZlwiIGJlY2F1c2UgdGhlIEFQSSBpcyBhZGQvcmVtb3ZlXG4gIGNvbnN0IG9sZENsaWVudHM6IHN0cmluZ1tdID0gKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcy5DbGllbnRJRExpc3QgfHwgW10pLnNvcnQoKTtcbiAgY29uc3QgZGlmZiA9IGFycmF5RGlmZihvbGRDbGllbnRzLCBjbGllbnRzKTtcbiAgZXh0ZXJuYWwubG9nKGBjbGllbnQgSUQgZGlmZjogJHtKU09OLnN0cmluZ2lmeShkaWZmKX1gKTtcblxuICBmb3IgKGNvbnN0IGFkZENsaWVudCBvZiBkaWZmLmFkZHMpIHtcbiAgICBleHRlcm5hbC5sb2coYGFkZGluZyBjbGllbnQgaWQgXCIke2FkZENsaWVudH1cIiB0byBwcm92aWRlciAke3Byb3ZpZGVyQXJufWApO1xuICAgIGF3YWl0IGV4dGVybmFsLmFkZENsaWVudElEVG9PcGVuSURDb25uZWN0UHJvdmlkZXIoe1xuICAgICAgT3BlbklEQ29ubmVjdFByb3ZpZGVyQXJuOiBwcm92aWRlckFybixcbiAgICAgIENsaWVudElEOiBhZGRDbGllbnQsXG4gICAgfSk7XG4gIH1cblxuICBmb3IgKGNvbnN0IGRlbGV0ZUNsaWVudCBvZiBkaWZmLmRlbGV0ZXMpIHtcbiAgICBleHRlcm5hbC5sb2coYHJlbW92aW5nIGNsaWVudCBpZCBcIiR7ZGVsZXRlQ2xpZW50fVwiIGZyb20gcHJvdmlkZXIgJHtwcm92aWRlckFybn1gKTtcbiAgICBhd2FpdCBleHRlcm5hbC5yZW1vdmVDbGllbnRJREZyb21PcGVuSURDb25uZWN0UHJvdmlkZXIoe1xuICAgICAgT3BlbklEQ29ubmVjdFByb3ZpZGVyQXJuOiBwcm92aWRlckFybixcbiAgICAgIENsaWVudElEOiBkZWxldGVDbGllbnQsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm47XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uRGVsZXRlKGRlbGV0ZUV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZURlbGV0ZUV2ZW50KSB7XG4gIGF3YWl0IGV4dGVybmFsLmRlbGV0ZU9wZW5JRENvbm5lY3RQcm92aWRlcih7XG4gICAgT3BlbklEQ29ubmVjdFByb3ZpZGVyQXJuOiBkZWxldGVFdmVudC5QaHlzaWNhbFJlc291cmNlSWQsXG4gIH0pO1xufVxuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpQ0FBbUM7QUFDbkMseUNBQXNDO0FBRS9CLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7SUFDOUUsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQUU7SUFDL0QsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQUU7SUFDL0QsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtRQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQUU7SUFDL0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBQzFDLENBQUM7QUFMRCwwQkFLQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsS0FBd0Q7SUFDOUUsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztJQUMvQyxNQUFNLFdBQVcsR0FBYSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyx5QkFBeUI7SUFDL0csTUFBTSxPQUFPLEdBQWEsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBRS9FLElBQUksV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDNUIsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLG1CQUFRLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztLQUNoRTtJQUVELE1BQU0sSUFBSSxHQUFHLE1BQU0sbUJBQVEsQ0FBQywyQkFBMkIsQ0FBQztRQUN0RCxHQUFHLEVBQUUsU0FBUztRQUNkLFlBQVksRUFBRSxPQUFPO1FBQ3JCLGNBQWMsRUFBRSxXQUFXO0tBQzVCLENBQUMsQ0FBQztJQUVILE9BQU87UUFDTCxrQkFBa0IsRUFBRSxJQUFJLENBQUMsd0JBQXdCO0tBQ2xELENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLFFBQVEsQ0FBQyxLQUF3RDtJQUM5RSxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDO0lBQy9DLE1BQU0sV0FBVyxHQUFhLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLHlCQUF5QjtJQUMvRyxNQUFNLE9BQU8sR0FBYSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFL0UsK0NBQStDO0lBQy9DLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUM7SUFFckQsbUdBQW1HO0lBQ25HLDhDQUE4QztJQUM5QyxJQUFJLFlBQVksS0FBSyxTQUFTLEVBQUU7UUFDOUIsT0FBTyxRQUFRLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztLQUN0RDtJQUVELE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztJQUU3QyxtR0FBbUc7SUFDbkcsaUVBQWlFO0lBQ2pFLE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNqRixJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsRUFBRTtRQUNsRSxNQUFNLGNBQWMsR0FBRyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sbUJBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzdHLG1CQUFRLENBQUMsR0FBRyxDQUFDLCtCQUErQixFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDakYsTUFBTSxtQkFBUSxDQUFDLHFDQUFxQyxDQUFDO1lBQ25ELHdCQUF3QixFQUFFLFdBQVc7WUFDckMsY0FBYyxFQUFFLGNBQWM7U0FDL0IsQ0FBQyxDQUFDO1FBRUgsOENBQThDO0tBQy9DO0lBRUQsZ0ZBQWdGO0lBQ2hGLE1BQU0sVUFBVSxHQUFhLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFlBQVksSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNyRixNQUFNLElBQUksR0FBRyxnQkFBUyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM1QyxtQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFeEQsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ2pDLG1CQUFRLENBQUMsR0FBRyxDQUFDLHFCQUFxQixTQUFTLGlCQUFpQixXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLE1BQU0sbUJBQVEsQ0FBQyxrQ0FBa0MsQ0FBQztZQUNoRCx3QkFBd0IsRUFBRSxXQUFXO1lBQ3JDLFFBQVEsRUFBRSxTQUFTO1NBQ3BCLENBQUMsQ0FBQztLQUNKO0lBRUQsS0FBSyxNQUFNLFlBQVksSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1FBQ3ZDLG1CQUFRLENBQUMsR0FBRyxDQUFDLHVCQUF1QixZQUFZLG1CQUFtQixXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sbUJBQVEsQ0FBQyx1Q0FBdUMsQ0FBQztZQUNyRCx3QkFBd0IsRUFBRSxXQUFXO1lBQ3JDLFFBQVEsRUFBRSxZQUFZO1NBQ3ZCLENBQUMsQ0FBQztLQUNKO0lBRUQsT0FBTztBQUNULENBQUM7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLFdBQThEO0lBQ3BGLE1BQU0sbUJBQVEsQ0FBQywyQkFBMkIsQ0FBQztRQUN6Qyx3QkFBd0IsRUFBRSxXQUFXLENBQUMsa0JBQWtCO0tBQ3pELENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBhcnJheURpZmYgfSBmcm9tICcuL2RpZmYnO1xuaW1wb3J0IHsgZXh0ZXJuYWwgfSBmcm9tICcuL2V4dGVybmFsJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJykgeyByZXR1cm4gb25DcmVhdGUoZXZlbnQpOyB9XG4gIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScpIHsgcmV0dXJuIG9uVXBkYXRlKGV2ZW50KTsgfVxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnKSB7IHJldHVybiBvbkRlbGV0ZShldmVudCk7IH1cbiAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlcXVlc3QgdHlwZScpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBvbkNyZWF0ZShldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VDcmVhdGVFdmVudCkge1xuICBjb25zdCBpc3N1ZXJVcmwgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuVXJsO1xuICBjb25zdCB0aHVtYnByaW50czogc3RyaW5nW10gPSAoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlRodW1icHJpbnRMaXN0ID8/IFtdKS5zb3J0KCk7IC8vIGtlZXAgc29ydGVkIGZvciBVUERBVEVcbiAgY29uc3QgY2xpZW50czogc3RyaW5nW10gPSAoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNsaWVudElETGlzdCA/PyBbXSkuc29ydCgpO1xuXG4gIGlmICh0aHVtYnByaW50cy5sZW5ndGggPT09IDApIHtcbiAgICB0aHVtYnByaW50cy5wdXNoKGF3YWl0IGV4dGVybmFsLmRvd25sb2FkVGh1bWJwcmludChpc3N1ZXJVcmwpKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3AgPSBhd2FpdCBleHRlcm5hbC5jcmVhdGVPcGVuSURDb25uZWN0UHJvdmlkZXIoe1xuICAgIFVybDogaXNzdWVyVXJsLFxuICAgIENsaWVudElETGlzdDogY2xpZW50cyxcbiAgICBUaHVtYnByaW50TGlzdDogdGh1bWJwcmludHMsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiByZXNwLk9wZW5JRENvbm5lY3RQcm92aWRlckFybixcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gb25VcGRhdGUoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlVXBkYXRlRXZlbnQpIHtcbiAgY29uc3QgaXNzdWVyVXJsID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlVybDtcbiAgY29uc3QgdGh1bWJwcmludHM6IHN0cmluZ1tdID0gKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5UaHVtYnByaW50TGlzdCA/PyBbXSkuc29ydCgpOyAvLyBrZWVwIHNvcnRlZCBmb3IgVVBEQVRFXG4gIGNvbnN0IGNsaWVudHM6IHN0cmluZ1tdID0gKGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5DbGllbnRJRExpc3QgPz8gW10pLnNvcnQoKTtcblxuICAvLyBkZXRlcm1pbmUgd2hpY2ggdXBkYXRlIHdlIGFyZSB0YWxraW5nIGFib3V0LlxuICBjb25zdCBvbGRJc3N1ZXJVcmwgPSBldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMuVXJsO1xuXG4gIC8vIGlmIHRoaXMgaXMgYSBVUkwgdXBkYXRlLCB0aGVuIHdlIGJhc2ljYWxseSBjcmVhdGUgYSBuZXcgcmVzb3VyY2UgYW5kIGNmbiB3aWxsIGRlbGV0ZSB0aGUgb2xkIG9uZVxuICAvLyBzaW5jZSB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgd2lsbCBjaGFuZ2UuXG4gIGlmIChvbGRJc3N1ZXJVcmwgIT09IGlzc3VlclVybCkge1xuICAgIHJldHVybiBvbkNyZWF0ZSh7IC4uLmV2ZW50LCBSZXF1ZXN0VHlwZTogJ0NyZWF0ZScgfSk7XG4gIH1cblxuICBjb25zdCBwcm92aWRlckFybiA9IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZDtcblxuICAvLyBpZiB0aHVtYnByaW50cyBjaGFuZ2VkLCB3ZSBjYW4gdXBkYXRlIGluLXBsYWNlLCBidXQgYmVhciBpbiBtaW5kIHRoYXQgaWYgdGhlIG5ldyB0aHVtYnByaW50IGxpc3RcbiAgLy8gaXMgZW1wdHksIHdlIHdpbGwgZ3JhYiBpdCBmcm9tIHRoZSBzZXJ2ZXIgbGlrZSB3ZSBkbyBpbiBDUkVBVEVcbiAgY29uc3Qgb2xkVGh1bWJwcmludHMgPSAoZXZlbnQuT2xkUmVzb3VyY2VQcm9wZXJ0aWVzLlRodW1icHJpbnRMaXN0IHx8IFtdKS5zb3J0KCk7XG4gIGlmIChKU09OLnN0cmluZ2lmeShvbGRUaHVtYnByaW50cykgIT09IEpTT04uc3RyaW5naWZ5KHRodW1icHJpbnRzKSkge1xuICAgIGNvbnN0IHRodW1icHJpbnRMaXN0ID0gdGh1bWJwcmludHMubGVuZ3RoID4gMCA/IHRodW1icHJpbnRzIDogW2F3YWl0IGV4dGVybmFsLmRvd25sb2FkVGh1bWJwcmludChpc3N1ZXJVcmwpXTtcbiAgICBleHRlcm5hbC5sb2coJ3VwZGF0aW5nIHRodW1icHJpbnQgbGlzdCBmcm9tJywgb2xkVGh1bWJwcmludHMsICd0bycsIHRodW1icHJpbnRzKTtcbiAgICBhd2FpdCBleHRlcm5hbC51cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50KHtcbiAgICAgIE9wZW5JRENvbm5lY3RQcm92aWRlckFybjogcHJvdmlkZXJBcm4sXG4gICAgICBUaHVtYnByaW50TGlzdDogdGh1bWJwcmludExpc3QsXG4gICAgfSk7XG5cbiAgICAvLyBkb24ndCByZXR1cm4sIHdlIG1pZ2h0IGhhdmUgbW9yZSB1cGRhdGVzLi4uXG4gIH1cblxuICAvLyBpZiBjbGllbnQgSUQgbGlzdCBoYXMgY2hhbmdlZCwgZGV0ZXJtaW5lIFwiZGlmZlwiIGJlY2F1c2UgdGhlIEFQSSBpcyBhZGQvcmVtb3ZlXG4gIGNvbnN0IG9sZENsaWVudHM6IHN0cmluZ1tdID0gKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcy5DbGllbnRJRExpc3QgfHwgW10pLnNvcnQoKTtcbiAgY29uc3QgZGlmZiA9IGFycmF5RGlmZihvbGRDbGllbnRzLCBjbGllbnRzKTtcbiAgZXh0ZXJuYWwubG9nKGBjbGllbnQgSUQgZGlmZjogJHtKU09OLnN0cmluZ2lmeShkaWZmKX1gKTtcblxuICBmb3IgKGNvbnN0IGFkZENsaWVudCBvZiBkaWZmLmFkZHMpIHtcbiAgICBleHRlcm5hbC5sb2coYGFkZGluZyBjbGllbnQgaWQgXCIke2FkZENsaWVudH1cIiB0byBwcm92aWRlciAke3Byb3ZpZGVyQXJufWApO1xuICAgIGF3YWl0IGV4dGVybmFsLmFkZENsaWVudElEVG9PcGVuSURDb25uZWN0UHJvdmlkZXIoe1xuICAgICAgT3BlbklEQ29ubmVjdFByb3ZpZGVyQXJuOiBwcm92aWRlckFybixcbiAgICAgIENsaWVudElEOiBhZGRDbGllbnQsXG4gICAgfSk7XG4gIH1cblxuICBmb3IgKGNvbnN0IGRlbGV0ZUNsaWVudCBvZiBkaWZmLmRlbGV0ZXMpIHtcbiAgICBleHRlcm5hbC5sb2coYHJlbW92aW5nIGNsaWVudCBpZCBcIiR7ZGVsZXRlQ2xpZW50fVwiIGZyb20gcHJvdmlkZXIgJHtwcm92aWRlckFybn1gKTtcbiAgICBhd2FpdCBleHRlcm5hbC5yZW1vdmVDbGllbnRJREZyb21PcGVuSURDb25uZWN0UHJvdmlkZXIoe1xuICAgICAgT3BlbklEQ29ubmVjdFByb3ZpZGVyQXJuOiBwcm92aWRlckFybixcbiAgICAgIENsaWVudElEOiBkZWxldGVDbGllbnQsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm47XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uRGVsZXRlKGRlbGV0ZUV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZURlbGV0ZUV2ZW50KSB7XG4gIGF3YWl0IGV4dGVybmFsLmRlbGV0ZU9wZW5JRENvbm5lY3RQcm92aWRlcih7XG4gICAgT3BlbklEQ29ubmVjdFByb3ZpZGVyQXJuOiBkZWxldGVFdmVudC5QaHlzaWNhbFJlc291cmNlSWQsXG4gIH0pO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/lib/aws-api-handler/index.ts b/packages/@aws-cdk/aws-events-targets/lib/aws-api-handler/index.ts index 88158298e2e7c..7fbe236328c44 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/aws-api-handler/index.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/aws-api-handler/index.ts @@ -4,7 +4,7 @@ import * as AWS from 'aws-sdk'; import { AwsApiInput } from '../aws-api'; export async function handler(event: AwsApiInput) { - console.log('Event: %j', event); + console.log('Event: %j', { ...event, ResponseURL: '...' }); console.log('AWS SDK VERSION: ' + (AWS as any).VERSION); const awsService = new (AWS as any)[event.service](event.apiVersion && { apiVersion: event.apiVersion }); diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json index 7dee8dca73db1..cb55f7d816f58 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "9a74d9d8095350705e05eac5bf248c6f6bd9e38a50ab7303628d6ca28a1abb5a": { + "3c50421f7823038cd9fabd7e8e3e52667d7e61da2760abe3c2a76725bedb06b8": { "source": { "path": "aws-ecs-integ-ecs.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9a74d9d8095350705e05eac5bf248c6f6bd9e38a50ab7303628d6ca28a1abb5a.json", + "objectKey": "3c50421f7823038cd9fabd7e8e3e52667d7e61da2760abe3c2a76725bedb06b8.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json index 325c016edc0e7..122842ca14a76 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/aws-ecs-integ-ecs.template.json @@ -532,7 +532,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/manifest.json index 8bfa061ab610e..0067ad2e9dffc 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/manifest.json @@ -217,10 +217,7 @@ "/aws-ecs-integ-ecs/TaskDef/Resource": [ { "type": "aws:cdk:logicalId", - "data": "TaskDef54694570", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "TaskDef54694570" } ], "/aws-ecs-integ-ecs/TaskDef/TheContainer/LogGroup/Resource": [ diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/tree.json b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/tree.json index 2f623fa912b25..71cc0011f7c87 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/event-ec2-task.lit.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ-ecs": { @@ -825,7 +825,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -922,7 +922,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.lit.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js b/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.lit.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js index 82fedbce3efac..7ce4156d4ba41 100644 --- a/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.lit.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js +++ b/packages/@aws-cdk/aws-kinesisfirehose-destinations/test/s3-bucket.lit.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js @@ -6,22 +6,20 @@ const aws_sdk_1 = require("aws-sdk"); const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; const s3 = new aws_sdk_1.S3(); async function handler(event) { - var _a; switch (event.RequestType) { case 'Create': return; case 'Update': return onUpdate(event); case 'Delete': - return onDelete((_a = event.ResourceProperties) === null || _a === void 0 ? void 0 : _a.BucketName); + return onDelete(event.ResourceProperties?.BucketName); } } exports.handler = handler; async function onUpdate(event) { - var _a, _b; const updateEvent = event; - const oldBucketName = (_a = updateEvent.OldResourceProperties) === null || _a === void 0 ? void 0 : _a.BucketName; - const newBucketName = (_b = updateEvent.ResourceProperties) === null || _b === void 0 ? void 0 : _b.BucketName; + const oldBucketName = updateEvent.OldResourceProperties?.BucketName; + const newBucketName = updateEvent.ResourceProperties?.BucketName; const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; /* If the name of the bucket has changed, CloudFormation will try to delete the bucket and create a new one with the new name. So we have to delete the contents of the @@ -36,15 +34,14 @@ async function onUpdate(event) { * @param bucketName the bucket name */ async function emptyBucket(bucketName) { - var _a, _b; const listedObjects = await s3.listObjectVersions({ Bucket: bucketName }).promise(); - const contents = [...(_a = listedObjects.Versions) !== null && _a !== void 0 ? _a : [], ...(_b = listedObjects.DeleteMarkers) !== null && _b !== void 0 ? _b : []]; + const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; if (contents.length === 0) { return; } const records = contents.map((record) => ({ Key: record.Key, VersionId: record.VersionId })); await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); - if (listedObjects === null || listedObjects === void 0 ? void 0 : listedObjects.IsTruncated) { + if (listedObjects?.IsTruncated) { await emptyBucket(bucketName); } } @@ -78,4 +75,4 @@ async function isBucketTaggedForDeletion(bucketName) { const response = await s3.getBucketTagging({ Bucket: bucketName }).promise(); return response.TagSet.some(tag => tag.Key === AUTO_DELETE_OBJECTS_TAG && tag.Value === 'true'); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0QscUNBQTZCO0FBRTdCLE1BQU0sdUJBQXVCLEdBQUcsNkJBQTZCLENBQUM7QUFFOUQsTUFBTSxFQUFFLEdBQUcsSUFBSSxZQUFFLEVBQUUsQ0FBQztBQUViLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7O0lBQzlFLFFBQVEsS0FBSyxDQUFDLFdBQVcsRUFBRTtRQUN6QixLQUFLLFFBQVE7WUFDWCxPQUFPO1FBQ1QsS0FBSyxRQUFRO1lBQ1gsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsS0FBSyxRQUFRO1lBQ1gsT0FBTyxRQUFRLE9BQUMsS0FBSyxDQUFDLGtCQUFrQiwwQ0FBRSxVQUFVLENBQUMsQ0FBQztLQUN6RDtBQUNILENBQUM7QUFURCwwQkFTQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsS0FBa0Q7O0lBQ3hFLE1BQU0sV0FBVyxHQUFHLEtBQTBELENBQUM7SUFDL0UsTUFBTSxhQUFhLFNBQUcsV0FBVyxDQUFDLHFCQUFxQiwwQ0FBRSxVQUFVLENBQUM7SUFDcEUsTUFBTSxhQUFhLFNBQUcsV0FBVyxDQUFDLGtCQUFrQiwwQ0FBRSxVQUFVLENBQUM7SUFDakUsTUFBTSxvQkFBb0IsR0FBRyxhQUFhLElBQUksSUFBSSxJQUFJLGFBQWEsSUFBSSxJQUFJLElBQUksYUFBYSxLQUFLLGFBQWEsQ0FBQztJQUUvRzs7c0RBRWtEO0lBQ2xELElBQUksb0JBQW9CLEVBQUU7UUFDeEIsT0FBTyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDaEM7QUFDSCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxXQUFXLENBQUMsVUFBa0I7O0lBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxTQUFHLGFBQWEsQ0FBQyxRQUFRLG1DQUFJLEVBQUUsRUFBRSxTQUFHLGFBQWEsQ0FBQyxhQUFhLG1DQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDekIsT0FBTztLQUNSO0lBRUQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLE1BQU0sRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUV2RixJQUFJLGFBQWEsYUFBYixhQUFhLHVCQUFiLGFBQWEsQ0FBRSxXQUFXLEVBQUU7UUFDOUIsTUFBTSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7S0FDL0I7QUFDSCxDQUFDO0FBRUQsS0FBSyxVQUFVLFFBQVEsQ0FBQyxVQUFtQjtJQUN6QyxJQUFJLENBQUMsVUFBVSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0tBQ2hEO0lBQ0QsSUFBSSxDQUFDLE1BQU0seUJBQXlCLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFDaEQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMseUJBQXlCLHVCQUF1Qiw2QkFBNkIsQ0FBQyxDQUFDO1FBQ3BHLE9BQU87S0FDUjtJQUNELElBQUk7UUFDRixNQUFNLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQztLQUMvQjtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUM3QixNQUFNLENBQUMsQ0FBQztTQUNUO1FBQ0QsaUNBQWlDO0tBQ2xDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxLQUFLLFVBQVUseUJBQXlCLENBQUMsVUFBa0I7SUFDekQsTUFBTSxRQUFRLEdBQUcsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUM3RSxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyx1QkFBdUIsSUFBSSxHQUFHLENBQUMsS0FBSyxLQUFLLE1BQU0sQ0FBQyxDQUFDO0FBQ2xHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBTMyB9IGZyb20gJ2F3cy1zZGsnO1xuXG5jb25zdCBBVVRPX0RFTEVURV9PQkpFQ1RTX1RBRyA9ICdhd3MtY2RrOmF1dG8tZGVsZXRlLW9iamVjdHMnO1xuXG5jb25zdCBzMyA9IG5ldyBTMygpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlcihldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCkge1xuICBzd2l0Y2ggKGV2ZW50LlJlcXVlc3RUeXBlKSB7XG4gICAgY2FzZSAnQ3JlYXRlJzpcbiAgICAgIHJldHVybjtcbiAgICBjYXNlICdVcGRhdGUnOlxuICAgICAgcmV0dXJuIG9uVXBkYXRlKGV2ZW50KTtcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgcmV0dXJuIG9uRGVsZXRlKGV2ZW50LlJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gb25VcGRhdGUoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgY29uc3QgdXBkYXRlRXZlbnQgPSBldmVudCBhcyBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVVwZGF0ZUV2ZW50O1xuICBjb25zdCBvbGRCdWNrZXROYW1lID0gdXBkYXRlRXZlbnQuT2xkUmVzb3VyY2VQcm9wZXJ0aWVzPy5CdWNrZXROYW1lO1xuICBjb25zdCBuZXdCdWNrZXROYW1lID0gdXBkYXRlRXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzPy5CdWNrZXROYW1lO1xuICBjb25zdCBidWNrZXROYW1lSGFzQ2hhbmdlZCA9IG5ld0J1Y2tldE5hbWUgIT0gbnVsbCAmJiBvbGRCdWNrZXROYW1lICE9IG51bGwgJiYgbmV3QnVja2V0TmFtZSAhPT0gb2xkQnVja2V0TmFtZTtcblxuICAvKiBJZiB0aGUgbmFtZSBvZiB0aGUgYnVja2V0IGhhcyBjaGFuZ2VkLCBDbG91ZEZvcm1hdGlvbiB3aWxsIHRyeSB0byBkZWxldGUgdGhlIGJ1Y2tldFxuICAgICBhbmQgY3JlYXRlIGEgbmV3IG9uZSB3aXRoIHRoZSBuZXcgbmFtZS4gU28gd2UgaGF2ZSB0byBkZWxldGUgdGhlIGNvbnRlbnRzIG9mIHRoZVxuICAgICBidWNrZXQgc28gdGhhdCB0aGlzIG9wZXJhdGlvbiBkb2VzIG5vdCBmYWlsLiAqL1xuICBpZiAoYnVja2V0TmFtZUhhc0NoYW5nZWQpIHtcbiAgICByZXR1cm4gb25EZWxldGUob2xkQnVja2V0TmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBkZWxldGUgYWxsIGl0ZW1zIGluIHRoZSBidWNrZXRcbiAqXG4gKiBAcGFyYW0gYnVja2V0TmFtZSB0aGUgYnVja2V0IG5hbWVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZW1wdHlCdWNrZXQoYnVja2V0TmFtZTogc3RyaW5nKSB7XG4gIGNvbnN0IGxpc3RlZE9iamVjdHMgPSBhd2FpdCBzMy5saXN0T2JqZWN0VmVyc2lvbnMoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUgfSkucHJvbWlzZSgpO1xuICBjb25zdCBjb250ZW50cyA9IFsuLi5saXN0ZWRPYmplY3RzLlZlcnNpb25zID8/IFtdLCAuLi5saXN0ZWRPYmplY3RzLkRlbGV0ZU1hcmtlcnMgPz8gW11dO1xuICBpZiAoY29udGVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgcmVjb3JkcyA9IGNvbnRlbnRzLm1hcCgocmVjb3JkOiBhbnkpID0+ICh7IEtleTogcmVjb3JkLktleSwgVmVyc2lvbklkOiByZWNvcmQuVmVyc2lvbklkIH0pKTtcbiAgYXdhaXQgczMuZGVsZXRlT2JqZWN0cyh7IEJ1Y2tldDogYnVja2V0TmFtZSwgRGVsZXRlOiB7IE9iamVjdHM6IHJlY29yZHMgfSB9KS5wcm9taXNlKCk7XG5cbiAgaWYgKGxpc3RlZE9iamVjdHM/LklzVHJ1bmNhdGVkKSB7XG4gICAgYXdhaXQgZW1wdHlCdWNrZXQoYnVja2V0TmFtZSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gb25EZWxldGUoYnVja2V0TmFtZT86IHN0cmluZykge1xuICBpZiAoIWJ1Y2tldE5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIEJ1Y2tldE5hbWUgd2FzIHByb3ZpZGVkLicpO1xuICB9XG4gIGlmICghYXdhaXQgaXNCdWNrZXRUYWdnZWRGb3JEZWxldGlvbihidWNrZXROYW1lKSkge1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGBCdWNrZXQgZG9lcyBub3QgaGF2ZSAnJHtBVVRPX0RFTEVURV9PQkpFQ1RTX1RBR30nIHRhZywgc2tpcHBpbmcgY2xlYW5pbmcuXFxuYCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRyeSB7XG4gICAgYXdhaXQgZW1wdHlCdWNrZXQoYnVja2V0TmFtZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZS5jb2RlICE9PSAnTm9TdWNoQnVja2V0Jykge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgLy8gQnVja2V0IGRvZXNuJ3QgZXhpc3QuIElnbm9yaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgYnVja2V0IHdpbGwgb25seSBiZSB0YWdnZWQgZm9yIGRlbGV0aW9uIGlmIGl0J3MgYmVpbmcgZGVsZXRlZCBpbiB0aGUgc2FtZVxuICogZGVwbG95bWVudCBhcyB0aGlzIEN1c3RvbSBSZXNvdXJjZS5cbiAqXG4gKiBJZiB0aGUgQ3VzdG9tIFJlc291cmNlIGlzIGV2ZXJ5IGRlbGV0ZWQgYmVmb3JlIHRoZSBidWNrZXQsIGl0IG11c3QgYmUgYmVjYXVzZVxuICogYGF1dG9EZWxldGVPYmplY3RzYCBoYXMgYmVlbiBzd2l0Y2hlZCB0byBmYWxzZSwgaW4gd2hpY2ggY2FzZSB0aGUgdGFnIHdvdWxkIGhhdmVcbiAqIGJlZW4gcmVtb3ZlZCBiZWZvcmUgd2UgZ2V0IHRvIHRoaXMgRGVsZXRlIGV2ZW50LlxuICovXG5hc3luYyBmdW5jdGlvbiBpc0J1Y2tldFRhZ2dlZEZvckRlbGV0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHMzLmdldEJ1Y2tldFRhZ2dpbmcoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUgfSkucHJvbWlzZSgpO1xuICByZXR1cm4gcmVzcG9uc2UuVGFnU2V0LnNvbWUodGFnID0+IHRhZy5LZXkgPT09IEFVVE9fREVMRVRFX09CSkVDVFNfVEFHICYmIHRhZy5WYWx1ZSA9PT0gJ3RydWUnKTtcbn0iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0QscUNBQTZCO0FBRTdCLE1BQU0sdUJBQXVCLEdBQUcsNkJBQTZCLENBQUM7QUFFOUQsTUFBTSxFQUFFLEdBQUcsSUFBSSxZQUFFLEVBQUUsQ0FBQztBQUViLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7SUFDOUUsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3pCLEtBQUssUUFBUTtZQUNYLE9BQU87UUFDVCxLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUM7S0FDekQ7QUFDSCxDQUFDO0FBVEQsMEJBU0M7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLEtBQWtEO0lBQ3hFLE1BQU0sV0FBVyxHQUFHLEtBQTBELENBQUM7SUFDL0UsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDLHFCQUFxQixFQUFFLFVBQVUsQ0FBQztJQUNwRSxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDO0lBQ2pFLE1BQU0sb0JBQW9CLEdBQUcsYUFBYSxJQUFJLElBQUksSUFBSSxhQUFhLElBQUksSUFBSSxJQUFJLGFBQWEsS0FBSyxhQUFhLENBQUM7SUFFL0c7O3NEQUVrRDtJQUNsRCxJQUFJLG9CQUFvQixFQUFFO1FBQ3hCLE9BQU8sUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0tBQ2hDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsV0FBVyxDQUFDLFVBQWtCO0lBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLEdBQUcsYUFBYSxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN6RixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3pCLE9BQU87S0FDUjtJQUVELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLEVBQUUsQ0FBQyxhQUFhLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFFdkYsSUFBSSxhQUFhLEVBQUUsV0FBVyxFQUFFO1FBQzlCLE1BQU0sV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0tBQy9CO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsVUFBbUI7SUFDekMsSUFBSSxDQUFDLFVBQVUsRUFBRTtRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztLQUNoRDtJQUNELElBQUksQ0FBQyxNQUFNLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQ2hELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5Qix1QkFBdUIsNkJBQTZCLENBQUMsQ0FBQztRQUNwRyxPQUFPO0tBQ1I7SUFDRCxJQUFJO1FBQ0YsTUFBTSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7S0FDL0I7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxjQUFjLEVBQUU7WUFDN0IsTUFBTSxDQUFDLENBQUM7U0FDVDtRQUNELGlDQUFpQztLQUNsQztBQUNILENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLHlCQUF5QixDQUFDLFVBQWtCO0lBQ3pELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDN0UsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssdUJBQXVCLElBQUksR0FBRyxDQUFDLEtBQUssS0FBSyxNQUFNLENBQUMsQ0FBQztBQUNsRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgUzMgfSBmcm9tICdhd3Mtc2RrJztcblxuY29uc3QgQVVUT19ERUxFVEVfT0JKRUNUU19UQUcgPSAnYXdzLWNkazphdXRvLWRlbGV0ZS1vYmplY3RzJztcblxuY29uc3QgczMgPSBuZXcgUzMoKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgc3dpdGNoIChldmVudC5SZXF1ZXN0VHlwZSkge1xuICAgIGNhc2UgJ0NyZWF0ZSc6XG4gICAgICByZXR1cm47XG4gICAgY2FzZSAnVXBkYXRlJzpcbiAgICAgIHJldHVybiBvblVwZGF0ZShldmVudCk7XG4gICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgIHJldHVybiBvbkRlbGV0ZShldmVudC5SZXNvdXJjZVByb3BlcnRpZXM/LkJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uVXBkYXRlKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50KSB7XG4gIGNvbnN0IHVwZGF0ZUV2ZW50ID0gZXZlbnQgYXMgQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VVcGRhdGVFdmVudDtcbiAgY29uc3Qgb2xkQnVja2V0TmFtZSA9IHVwZGF0ZUV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZTtcbiAgY29uc3QgbmV3QnVja2V0TmFtZSA9IHVwZGF0ZUV2ZW50LlJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZTtcbiAgY29uc3QgYnVja2V0TmFtZUhhc0NoYW5nZWQgPSBuZXdCdWNrZXROYW1lICE9IG51bGwgJiYgb2xkQnVja2V0TmFtZSAhPSBudWxsICYmIG5ld0J1Y2tldE5hbWUgIT09IG9sZEJ1Y2tldE5hbWU7XG5cbiAgLyogSWYgdGhlIG5hbWUgb2YgdGhlIGJ1Y2tldCBoYXMgY2hhbmdlZCwgQ2xvdWRGb3JtYXRpb24gd2lsbCB0cnkgdG8gZGVsZXRlIHRoZSBidWNrZXRcbiAgICAgYW5kIGNyZWF0ZSBhIG5ldyBvbmUgd2l0aCB0aGUgbmV3IG5hbWUuIFNvIHdlIGhhdmUgdG8gZGVsZXRlIHRoZSBjb250ZW50cyBvZiB0aGVcbiAgICAgYnVja2V0IHNvIHRoYXQgdGhpcyBvcGVyYXRpb24gZG9lcyBub3QgZmFpbC4gKi9cbiAgaWYgKGJ1Y2tldE5hbWVIYXNDaGFuZ2VkKSB7XG4gICAgcmV0dXJuIG9uRGVsZXRlKG9sZEJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgZGVsZXRlIGFsbCBpdGVtcyBpbiB0aGUgYnVja2V0XG4gKlxuICogQHBhcmFtIGJ1Y2tldE5hbWUgdGhlIGJ1Y2tldCBuYW1lXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVtcHR5QnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICBjb25zdCBsaXN0ZWRPYmplY3RzID0gYXdhaXQgczMubGlzdE9iamVjdFZlcnNpb25zKHsgQnVja2V0OiBidWNrZXROYW1lIH0pLnByb21pc2UoKTtcbiAgY29uc3QgY29udGVudHMgPSBbLi4ubGlzdGVkT2JqZWN0cy5WZXJzaW9ucyA/PyBbXSwgLi4ubGlzdGVkT2JqZWN0cy5EZWxldGVNYXJrZXJzID8/IFtdXTtcbiAgaWYgKGNvbnRlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHJlY29yZHMgPSBjb250ZW50cy5tYXAoKHJlY29yZDogYW55KSA9PiAoeyBLZXk6IHJlY29yZC5LZXksIFZlcnNpb25JZDogcmVjb3JkLlZlcnNpb25JZCB9KSk7XG4gIGF3YWl0IHMzLmRlbGV0ZU9iamVjdHMoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUsIERlbGV0ZTogeyBPYmplY3RzOiByZWNvcmRzIH0gfSkucHJvbWlzZSgpO1xuXG4gIGlmIChsaXN0ZWRPYmplY3RzPy5Jc1RydW5jYXRlZCkge1xuICAgIGF3YWl0IGVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uRGVsZXRlKGJ1Y2tldE5hbWU/OiBzdHJpbmcpIHtcbiAgaWYgKCFidWNrZXROYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdObyBCdWNrZXROYW1lIHdhcyBwcm92aWRlZC4nKTtcbiAgfVxuICBpZiAoIWF3YWl0IGlzQnVja2V0VGFnZ2VkRm9yRGVsZXRpb24oYnVja2V0TmFtZSkpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgQnVja2V0IGRvZXMgbm90IGhhdmUgJyR7QVVUT19ERUxFVEVfT0JKRUNUU19UQUd9JyB0YWcsIHNraXBwaW5nIGNsZWFuaW5nLlxcbmApO1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IGVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUuY29kZSAhPT0gJ05vU3VjaEJ1Y2tldCcpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIC8vIEJ1Y2tldCBkb2Vzbid0IGV4aXN0LiBJZ25vcmluZ1xuICB9XG59XG5cbi8qKlxuICogVGhlIGJ1Y2tldCB3aWxsIG9ubHkgYmUgdGFnZ2VkIGZvciBkZWxldGlvbiBpZiBpdCdzIGJlaW5nIGRlbGV0ZWQgaW4gdGhlIHNhbWVcbiAqIGRlcGxveW1lbnQgYXMgdGhpcyBDdXN0b20gUmVzb3VyY2UuXG4gKlxuICogSWYgdGhlIEN1c3RvbSBSZXNvdXJjZSBpcyBldmVyeSBkZWxldGVkIGJlZm9yZSB0aGUgYnVja2V0LCBpdCBtdXN0IGJlIGJlY2F1c2VcbiAqIGBhdXRvRGVsZXRlT2JqZWN0c2AgaGFzIGJlZW4gc3dpdGNoZWQgdG8gZmFsc2UsIGluIHdoaWNoIGNhc2UgdGhlIHRhZyB3b3VsZCBoYXZlXG4gKiBiZWVuIHJlbW92ZWQgYmVmb3JlIHdlIGdldCB0byB0aGlzIERlbGV0ZSBldmVudC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaXNCdWNrZXRUYWdnZWRGb3JEZWxldGlvbihidWNrZXROYW1lOiBzdHJpbmcpIHtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzMy5nZXRCdWNrZXRUYWdnaW5nKHsgQnVja2V0OiBidWNrZXROYW1lIH0pLnByb21pc2UoKTtcbiAgcmV0dXJuIHJlc3BvbnNlLlRhZ1NldC5zb21lKHRhZyA9PiB0YWcuS2V5ID09PSBBVVRPX0RFTEVURV9PQkpFQ1RTX1RBRyAmJiB0YWcuVmFsdWUgPT09ICd0cnVlJyk7XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/s3.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js b/packages/@aws-cdk/aws-lambda-event-sources/test/s3.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js index 82fedbce3efac..7ce4156d4ba41 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/s3.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/s3.integ.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js @@ -6,22 +6,20 @@ const aws_sdk_1 = require("aws-sdk"); const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; const s3 = new aws_sdk_1.S3(); async function handler(event) { - var _a; switch (event.RequestType) { case 'Create': return; case 'Update': return onUpdate(event); case 'Delete': - return onDelete((_a = event.ResourceProperties) === null || _a === void 0 ? void 0 : _a.BucketName); + return onDelete(event.ResourceProperties?.BucketName); } } exports.handler = handler; async function onUpdate(event) { - var _a, _b; const updateEvent = event; - const oldBucketName = (_a = updateEvent.OldResourceProperties) === null || _a === void 0 ? void 0 : _a.BucketName; - const newBucketName = (_b = updateEvent.ResourceProperties) === null || _b === void 0 ? void 0 : _b.BucketName; + const oldBucketName = updateEvent.OldResourceProperties?.BucketName; + const newBucketName = updateEvent.ResourceProperties?.BucketName; const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; /* If the name of the bucket has changed, CloudFormation will try to delete the bucket and create a new one with the new name. So we have to delete the contents of the @@ -36,15 +34,14 @@ async function onUpdate(event) { * @param bucketName the bucket name */ async function emptyBucket(bucketName) { - var _a, _b; const listedObjects = await s3.listObjectVersions({ Bucket: bucketName }).promise(); - const contents = [...(_a = listedObjects.Versions) !== null && _a !== void 0 ? _a : [], ...(_b = listedObjects.DeleteMarkers) !== null && _b !== void 0 ? _b : []]; + const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; if (contents.length === 0) { return; } const records = contents.map((record) => ({ Key: record.Key, VersionId: record.VersionId })); await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); - if (listedObjects === null || listedObjects === void 0 ? void 0 : listedObjects.IsTruncated) { + if (listedObjects?.IsTruncated) { await emptyBucket(bucketName); } } @@ -78,4 +75,4 @@ async function isBucketTaggedForDeletion(bucketName) { const response = await s3.getBucketTagging({ Bucket: bucketName }).promise(); return response.TagSet.some(tag => tag.Key === AUTO_DELETE_OBJECTS_TAG && tag.Value === 'true'); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0QscUNBQTZCO0FBRTdCLE1BQU0sdUJBQXVCLEdBQUcsNkJBQTZCLENBQUM7QUFFOUQsTUFBTSxFQUFFLEdBQUcsSUFBSSxZQUFFLEVBQUUsQ0FBQztBQUViLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7O0lBQzlFLFFBQVEsS0FBSyxDQUFDLFdBQVcsRUFBRTtRQUN6QixLQUFLLFFBQVE7WUFDWCxPQUFPO1FBQ1QsS0FBSyxRQUFRO1lBQ1gsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsS0FBSyxRQUFRO1lBQ1gsT0FBTyxRQUFRLE9BQUMsS0FBSyxDQUFDLGtCQUFrQiwwQ0FBRSxVQUFVLENBQUMsQ0FBQztLQUN6RDtBQUNILENBQUM7QUFURCwwQkFTQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsS0FBa0Q7O0lBQ3hFLE1BQU0sV0FBVyxHQUFHLEtBQTBELENBQUM7SUFDL0UsTUFBTSxhQUFhLFNBQUcsV0FBVyxDQUFDLHFCQUFxQiwwQ0FBRSxVQUFVLENBQUM7SUFDcEUsTUFBTSxhQUFhLFNBQUcsV0FBVyxDQUFDLGtCQUFrQiwwQ0FBRSxVQUFVLENBQUM7SUFDakUsTUFBTSxvQkFBb0IsR0FBRyxhQUFhLElBQUksSUFBSSxJQUFJLGFBQWEsSUFBSSxJQUFJLElBQUksYUFBYSxLQUFLLGFBQWEsQ0FBQztJQUUvRzs7c0RBRWtEO0lBQ2xELElBQUksb0JBQW9CLEVBQUU7UUFDeEIsT0FBTyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDaEM7QUFDSCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxXQUFXLENBQUMsVUFBa0I7O0lBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxTQUFHLGFBQWEsQ0FBQyxRQUFRLG1DQUFJLEVBQUUsRUFBRSxTQUFHLGFBQWEsQ0FBQyxhQUFhLG1DQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDekIsT0FBTztLQUNSO0lBRUQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLE1BQU0sRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUV2RixJQUFJLGFBQWEsYUFBYixhQUFhLHVCQUFiLGFBQWEsQ0FBRSxXQUFXLEVBQUU7UUFDOUIsTUFBTSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7S0FDL0I7QUFDSCxDQUFDO0FBRUQsS0FBSyxVQUFVLFFBQVEsQ0FBQyxVQUFtQjtJQUN6QyxJQUFJLENBQUMsVUFBVSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0tBQ2hEO0lBQ0QsSUFBSSxDQUFDLE1BQU0seUJBQXlCLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFDaEQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMseUJBQXlCLHVCQUF1Qiw2QkFBNkIsQ0FBQyxDQUFDO1FBQ3BHLE9BQU87S0FDUjtJQUNELElBQUk7UUFDRixNQUFNLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQztLQUMvQjtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUM3QixNQUFNLENBQUMsQ0FBQztTQUNUO1FBQ0QsaUNBQWlDO0tBQ2xDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxLQUFLLFVBQVUseUJBQXlCLENBQUMsVUFBa0I7SUFDekQsTUFBTSxRQUFRLEdBQUcsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUM3RSxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyx1QkFBdUIsSUFBSSxHQUFHLENBQUMsS0FBSyxLQUFLLE1BQU0sQ0FBQyxDQUFDO0FBQ2xHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBTMyB9IGZyb20gJ2F3cy1zZGsnO1xuXG5jb25zdCBBVVRPX0RFTEVURV9PQkpFQ1RTX1RBRyA9ICdhd3MtY2RrOmF1dG8tZGVsZXRlLW9iamVjdHMnO1xuXG5jb25zdCBzMyA9IG5ldyBTMygpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlcihldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCkge1xuICBzd2l0Y2ggKGV2ZW50LlJlcXVlc3RUeXBlKSB7XG4gICAgY2FzZSAnQ3JlYXRlJzpcbiAgICAgIHJldHVybjtcbiAgICBjYXNlICdVcGRhdGUnOlxuICAgICAgcmV0dXJuIG9uVXBkYXRlKGV2ZW50KTtcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgcmV0dXJuIG9uRGVsZXRlKGV2ZW50LlJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gb25VcGRhdGUoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgY29uc3QgdXBkYXRlRXZlbnQgPSBldmVudCBhcyBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVVwZGF0ZUV2ZW50O1xuICBjb25zdCBvbGRCdWNrZXROYW1lID0gdXBkYXRlRXZlbnQuT2xkUmVzb3VyY2VQcm9wZXJ0aWVzPy5CdWNrZXROYW1lO1xuICBjb25zdCBuZXdCdWNrZXROYW1lID0gdXBkYXRlRXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzPy5CdWNrZXROYW1lO1xuICBjb25zdCBidWNrZXROYW1lSGFzQ2hhbmdlZCA9IG5ld0J1Y2tldE5hbWUgIT0gbnVsbCAmJiBvbGRCdWNrZXROYW1lICE9IG51bGwgJiYgbmV3QnVja2V0TmFtZSAhPT0gb2xkQnVja2V0TmFtZTtcblxuICAvKiBJZiB0aGUgbmFtZSBvZiB0aGUgYnVja2V0IGhhcyBjaGFuZ2VkLCBDbG91ZEZvcm1hdGlvbiB3aWxsIHRyeSB0byBkZWxldGUgdGhlIGJ1Y2tldFxuICAgICBhbmQgY3JlYXRlIGEgbmV3IG9uZSB3aXRoIHRoZSBuZXcgbmFtZS4gU28gd2UgaGF2ZSB0byBkZWxldGUgdGhlIGNvbnRlbnRzIG9mIHRoZVxuICAgICBidWNrZXQgc28gdGhhdCB0aGlzIG9wZXJhdGlvbiBkb2VzIG5vdCBmYWlsLiAqL1xuICBpZiAoYnVja2V0TmFtZUhhc0NoYW5nZWQpIHtcbiAgICByZXR1cm4gb25EZWxldGUob2xkQnVja2V0TmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBkZWxldGUgYWxsIGl0ZW1zIGluIHRoZSBidWNrZXRcbiAqXG4gKiBAcGFyYW0gYnVja2V0TmFtZSB0aGUgYnVja2V0IG5hbWVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZW1wdHlCdWNrZXQoYnVja2V0TmFtZTogc3RyaW5nKSB7XG4gIGNvbnN0IGxpc3RlZE9iamVjdHMgPSBhd2FpdCBzMy5saXN0T2JqZWN0VmVyc2lvbnMoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUgfSkucHJvbWlzZSgpO1xuICBjb25zdCBjb250ZW50cyA9IFsuLi5saXN0ZWRPYmplY3RzLlZlcnNpb25zID8/IFtdLCAuLi5saXN0ZWRPYmplY3RzLkRlbGV0ZU1hcmtlcnMgPz8gW11dO1xuICBpZiAoY29udGVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgcmVjb3JkcyA9IGNvbnRlbnRzLm1hcCgocmVjb3JkOiBhbnkpID0+ICh7IEtleTogcmVjb3JkLktleSwgVmVyc2lvbklkOiByZWNvcmQuVmVyc2lvbklkIH0pKTtcbiAgYXdhaXQgczMuZGVsZXRlT2JqZWN0cyh7IEJ1Y2tldDogYnVja2V0TmFtZSwgRGVsZXRlOiB7IE9iamVjdHM6IHJlY29yZHMgfSB9KS5wcm9taXNlKCk7XG5cbiAgaWYgKGxpc3RlZE9iamVjdHM/LklzVHJ1bmNhdGVkKSB7XG4gICAgYXdhaXQgZW1wdHlCdWNrZXQoYnVja2V0TmFtZSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gb25EZWxldGUoYnVja2V0TmFtZT86IHN0cmluZykge1xuICBpZiAoIWJ1Y2tldE5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIEJ1Y2tldE5hbWUgd2FzIHByb3ZpZGVkLicpO1xuICB9XG4gIGlmICghYXdhaXQgaXNCdWNrZXRUYWdnZWRGb3JEZWxldGlvbihidWNrZXROYW1lKSkge1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGBCdWNrZXQgZG9lcyBub3QgaGF2ZSAnJHtBVVRPX0RFTEVURV9PQkpFQ1RTX1RBR30nIHRhZywgc2tpcHBpbmcgY2xlYW5pbmcuXFxuYCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRyeSB7XG4gICAgYXdhaXQgZW1wdHlCdWNrZXQoYnVja2V0TmFtZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZS5jb2RlICE9PSAnTm9TdWNoQnVja2V0Jykge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgLy8gQnVja2V0IGRvZXNuJ3QgZXhpc3QuIElnbm9yaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgYnVja2V0IHdpbGwgb25seSBiZSB0YWdnZWQgZm9yIGRlbGV0aW9uIGlmIGl0J3MgYmVpbmcgZGVsZXRlZCBpbiB0aGUgc2FtZVxuICogZGVwbG95bWVudCBhcyB0aGlzIEN1c3RvbSBSZXNvdXJjZS5cbiAqXG4gKiBJZiB0aGUgQ3VzdG9tIFJlc291cmNlIGlzIGV2ZXJ5IGRlbGV0ZWQgYmVmb3JlIHRoZSBidWNrZXQsIGl0IG11c3QgYmUgYmVjYXVzZVxuICogYGF1dG9EZWxldGVPYmplY3RzYCBoYXMgYmVlbiBzd2l0Y2hlZCB0byBmYWxzZSwgaW4gd2hpY2ggY2FzZSB0aGUgdGFnIHdvdWxkIGhhdmVcbiAqIGJlZW4gcmVtb3ZlZCBiZWZvcmUgd2UgZ2V0IHRvIHRoaXMgRGVsZXRlIGV2ZW50LlxuICovXG5hc3luYyBmdW5jdGlvbiBpc0J1Y2tldFRhZ2dlZEZvckRlbGV0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHMzLmdldEJ1Y2tldFRhZ2dpbmcoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUgfSkucHJvbWlzZSgpO1xuICByZXR1cm4gcmVzcG9uc2UuVGFnU2V0LnNvbWUodGFnID0+IHRhZy5LZXkgPT09IEFVVE9fREVMRVRFX09CSkVDVFNfVEFHICYmIHRhZy5WYWx1ZSA9PT0gJ3RydWUnKTtcbn0iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0QscUNBQTZCO0FBRTdCLE1BQU0sdUJBQXVCLEdBQUcsNkJBQTZCLENBQUM7QUFFOUQsTUFBTSxFQUFFLEdBQUcsSUFBSSxZQUFFLEVBQUUsQ0FBQztBQUViLEtBQUssVUFBVSxPQUFPLENBQUMsS0FBa0Q7SUFDOUUsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFO1FBQ3pCLEtBQUssUUFBUTtZQUNYLE9BQU87UUFDVCxLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixLQUFLLFFBQVE7WUFDWCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUM7S0FDekQ7QUFDSCxDQUFDO0FBVEQsMEJBU0M7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLEtBQWtEO0lBQ3hFLE1BQU0sV0FBVyxHQUFHLEtBQTBELENBQUM7SUFDL0UsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDLHFCQUFxQixFQUFFLFVBQVUsQ0FBQztJQUNwRSxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDO0lBQ2pFLE1BQU0sb0JBQW9CLEdBQUcsYUFBYSxJQUFJLElBQUksSUFBSSxhQUFhLElBQUksSUFBSSxJQUFJLGFBQWEsS0FBSyxhQUFhLENBQUM7SUFFL0c7O3NEQUVrRDtJQUNsRCxJQUFJLG9CQUFvQixFQUFFO1FBQ3hCLE9BQU8sUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0tBQ2hDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsV0FBVyxDQUFDLFVBQWtCO0lBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLEdBQUcsYUFBYSxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN6RixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3pCLE9BQU87S0FDUjtJQUVELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLEVBQUUsQ0FBQyxhQUFhLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFFdkYsSUFBSSxhQUFhLEVBQUUsV0FBVyxFQUFFO1FBQzlCLE1BQU0sV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0tBQy9CO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsVUFBbUI7SUFDekMsSUFBSSxDQUFDLFVBQVUsRUFBRTtRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztLQUNoRDtJQUNELElBQUksQ0FBQyxNQUFNLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQ2hELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5Qix1QkFBdUIsNkJBQTZCLENBQUMsQ0FBQztRQUNwRyxPQUFPO0tBQ1I7SUFDRCxJQUFJO1FBQ0YsTUFBTSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7S0FDL0I7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxjQUFjLEVBQUU7WUFDN0IsTUFBTSxDQUFDLENBQUM7U0FDVDtRQUNELGlDQUFpQztLQUNsQztBQUNILENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLHlCQUF5QixDQUFDLFVBQWtCO0lBQ3pELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDN0UsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssdUJBQXVCLElBQUksR0FBRyxDQUFDLEtBQUssS0FBSyxNQUFNLENBQUMsQ0FBQztBQUNsRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgUzMgfSBmcm9tICdhd3Mtc2RrJztcblxuY29uc3QgQVVUT19ERUxFVEVfT0JKRUNUU19UQUcgPSAnYXdzLWNkazphdXRvLWRlbGV0ZS1vYmplY3RzJztcblxuY29uc3QgczMgPSBuZXcgUzMoKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgc3dpdGNoIChldmVudC5SZXF1ZXN0VHlwZSkge1xuICAgIGNhc2UgJ0NyZWF0ZSc6XG4gICAgICByZXR1cm47XG4gICAgY2FzZSAnVXBkYXRlJzpcbiAgICAgIHJldHVybiBvblVwZGF0ZShldmVudCk7XG4gICAgY2FzZSAnRGVsZXRlJzpcbiAgICAgIHJldHVybiBvbkRlbGV0ZShldmVudC5SZXNvdXJjZVByb3BlcnRpZXM/LkJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uVXBkYXRlKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50KSB7XG4gIGNvbnN0IHVwZGF0ZUV2ZW50ID0gZXZlbnQgYXMgQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VVcGRhdGVFdmVudDtcbiAgY29uc3Qgb2xkQnVja2V0TmFtZSA9IHVwZGF0ZUV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZTtcbiAgY29uc3QgbmV3QnVja2V0TmFtZSA9IHVwZGF0ZUV2ZW50LlJlc291cmNlUHJvcGVydGllcz8uQnVja2V0TmFtZTtcbiAgY29uc3QgYnVja2V0TmFtZUhhc0NoYW5nZWQgPSBuZXdCdWNrZXROYW1lICE9IG51bGwgJiYgb2xkQnVja2V0TmFtZSAhPSBudWxsICYmIG5ld0J1Y2tldE5hbWUgIT09IG9sZEJ1Y2tldE5hbWU7XG5cbiAgLyogSWYgdGhlIG5hbWUgb2YgdGhlIGJ1Y2tldCBoYXMgY2hhbmdlZCwgQ2xvdWRGb3JtYXRpb24gd2lsbCB0cnkgdG8gZGVsZXRlIHRoZSBidWNrZXRcbiAgICAgYW5kIGNyZWF0ZSBhIG5ldyBvbmUgd2l0aCB0aGUgbmV3IG5hbWUuIFNvIHdlIGhhdmUgdG8gZGVsZXRlIHRoZSBjb250ZW50cyBvZiB0aGVcbiAgICAgYnVja2V0IHNvIHRoYXQgdGhpcyBvcGVyYXRpb24gZG9lcyBub3QgZmFpbC4gKi9cbiAgaWYgKGJ1Y2tldE5hbWVIYXNDaGFuZ2VkKSB7XG4gICAgcmV0dXJuIG9uRGVsZXRlKG9sZEJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgZGVsZXRlIGFsbCBpdGVtcyBpbiB0aGUgYnVja2V0XG4gKlxuICogQHBhcmFtIGJ1Y2tldE5hbWUgdGhlIGJ1Y2tldCBuYW1lXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVtcHR5QnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICBjb25zdCBsaXN0ZWRPYmplY3RzID0gYXdhaXQgczMubGlzdE9iamVjdFZlcnNpb25zKHsgQnVja2V0OiBidWNrZXROYW1lIH0pLnByb21pc2UoKTtcbiAgY29uc3QgY29udGVudHMgPSBbLi4ubGlzdGVkT2JqZWN0cy5WZXJzaW9ucyA/PyBbXSwgLi4ubGlzdGVkT2JqZWN0cy5EZWxldGVNYXJrZXJzID8/IFtdXTtcbiAgaWYgKGNvbnRlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHJlY29yZHMgPSBjb250ZW50cy5tYXAoKHJlY29yZDogYW55KSA9PiAoeyBLZXk6IHJlY29yZC5LZXksIFZlcnNpb25JZDogcmVjb3JkLlZlcnNpb25JZCB9KSk7XG4gIGF3YWl0IHMzLmRlbGV0ZU9iamVjdHMoeyBCdWNrZXQ6IGJ1Y2tldE5hbWUsIERlbGV0ZTogeyBPYmplY3RzOiByZWNvcmRzIH0gfSkucHJvbWlzZSgpO1xuXG4gIGlmIChsaXN0ZWRPYmplY3RzPy5Jc1RydW5jYXRlZCkge1xuICAgIGF3YWl0IGVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uRGVsZXRlKGJ1Y2tldE5hbWU/OiBzdHJpbmcpIHtcbiAgaWYgKCFidWNrZXROYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdObyBCdWNrZXROYW1lIHdhcyBwcm92aWRlZC4nKTtcbiAgfVxuICBpZiAoIWF3YWl0IGlzQnVja2V0VGFnZ2VkRm9yRGVsZXRpb24oYnVja2V0TmFtZSkpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgQnVja2V0IGRvZXMgbm90IGhhdmUgJyR7QVVUT19ERUxFVEVfT0JKRUNUU19UQUd9JyB0YWcsIHNraXBwaW5nIGNsZWFuaW5nLlxcbmApO1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IGVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUuY29kZSAhPT0gJ05vU3VjaEJ1Y2tldCcpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIC8vIEJ1Y2tldCBkb2Vzbid0IGV4aXN0LiBJZ25vcmluZ1xuICB9XG59XG5cbi8qKlxuICogVGhlIGJ1Y2tldCB3aWxsIG9ubHkgYmUgdGFnZ2VkIGZvciBkZWxldGlvbiBpZiBpdCdzIGJlaW5nIGRlbGV0ZWQgaW4gdGhlIHNhbWVcbiAqIGRlcGxveW1lbnQgYXMgdGhpcyBDdXN0b20gUmVzb3VyY2UuXG4gKlxuICogSWYgdGhlIEN1c3RvbSBSZXNvdXJjZSBpcyBldmVyeSBkZWxldGVkIGJlZm9yZSB0aGUgYnVja2V0LCBpdCBtdXN0IGJlIGJlY2F1c2VcbiAqIGBhdXRvRGVsZXRlT2JqZWN0c2AgaGFzIGJlZW4gc3dpdGNoZWQgdG8gZmFsc2UsIGluIHdoaWNoIGNhc2UgdGhlIHRhZyB3b3VsZCBoYXZlXG4gKiBiZWVuIHJlbW92ZWQgYmVmb3JlIHdlIGdldCB0byB0aGlzIERlbGV0ZSBldmVudC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaXNCdWNrZXRUYWdnZWRGb3JEZWxldGlvbihidWNrZXROYW1lOiBzdHJpbmcpIHtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzMy5nZXRCdWNrZXRUYWdnaW5nKHsgQnVja2V0OiBidWNrZXROYW1lIH0pLnByb21pc2UoKTtcbiAgcmV0dXJuIHJlc3BvbnNlLlRhZ1NldC5zb21lKHRhZyA9PiB0YWcuS2V5ID09PSBBVVRPX0RFTEVURV9PQkpFQ1RTX1RBRyAmJiB0YWcuVmFsdWUgPT09ICd0cnVlJyk7XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-logs/lib/log-retention-provider/index.ts b/packages/@aws-cdk/aws-logs/lib/log-retention-provider/index.ts index d2c14e5a72cc7..b78be3cb5c1ec 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-retention-provider/index.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-retention-provider/index.ts @@ -94,7 +94,7 @@ async function setRetentionPolicy(logGroupName: string, region?: string, options export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context) { try { - console.log(JSON.stringify(event)); + console.log(JSON.stringify({ ...event, ResponseURL: '...' })); // The target log group const logGroupName = event.ResourceProperties.LogGroupName; diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/eval-nodejs-handler/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/eval-nodejs-handler/index.ts index c40aeb340bfbb..a6709a2a580c8 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/eval-nodejs-handler/index.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/eval-nodejs-handler/index.ts @@ -6,7 +6,7 @@ function escapeRegex(x: string) { } export async function handler(event: Event): Promise { - console.log('Event: %j', event); + console.log('Event: %j', { ...event, ResponseURL: '...' }); const expression = Object.entries(event.expressionAttributeValues) .reduce( diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.assets.json index dd5612929a202..e5615405fc9ee 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "6f5cca7a24f1cb419762042b7008d4f5c9497b69121ba2684c0177f4c32d3a13": { + "e15d20e5a4ec4402555cb22eb36b5292a021b60dd1b890e8890cc905e66565b2": { "source": { "path": "aws-sfn-tasks-ecs-ec2-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6f5cca7a24f1cb419762042b7008d4f5c9497b69121ba2684c0177f4c32d3a13.json", + "objectKey": "e15d20e5a4ec4402555cb22eb36b5292a021b60dd1b890e8890cc905e66565b2.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.template.json index 3729ff8ed6b55..60dd1850d30ad 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/aws-sfn-tasks-ecs-ec2-integ.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/manifest.json index cebd1c2990cdb..46b6ea79e739f 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/manifest.json @@ -277,10 +277,7 @@ "/aws-sfn-tasks-ecs-ec2-integ/TaskDef/Resource": [ { "type": "aws:cdk:logicalId", - "data": "TaskDef54694570", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "TaskDef54694570" } ], "/aws-sfn-tasks-ecs-ec2-integ/TaskDef/TheContainer/LogGroup/Resource": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/tree.json index feccf69c3e5f6..52e4aeeeeb62d 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-run-task.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-sfn-tasks-ecs-ec2-integ": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.assets.json index b13d0daf0e472..9e03d83bdbc31 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.assets.json @@ -1,7 +1,7 @@ { - "version": "17.0.0", + "version": "20.0.0", "files": { - "67c01f432ec7bec6f1f2e5fec37bfbfe37abce1b9b19322f2f416ddcd11857b3": { + "b3977eb553bd781cb3268b3a959a9fcc9cfc5da780aa539ad6174eee01825a55": { "source": { "path": "aws-ecs-integ2.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "67c01f432ec7bec6f1f2e5fec37bfbfe37abce1b9b19322f2f416ddcd11857b3.json", + "objectKey": "b3977eb553bd781cb3268b3a959a9fcc9cfc5da780aa539ad6174eee01825a55.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.template.json index 9d3b8bfba1e9a..e4cc55e64d2ed 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/aws-ecs-integ2.template.json @@ -708,7 +708,7 @@ "Type": "AWS::Lambda::Function", "Properties": { "Code": { - "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/manifest.json index 94fc991a9b876..26cf90c150998 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/manifest.json @@ -277,10 +277,7 @@ "/aws-ecs-integ2/TaskDef/Resource": [ { "type": "aws:cdk:logicalId", - "data": "TaskDef54694570", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "TaskDef54694570" } ], "/aws-ecs-integ2/TaskDef/TheContainer/LogGroup/Resource": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/tree.json index 9b270c09c7f9d..1461799efbd88 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/ec2-task.integ.snapshot/tree.json @@ -9,7 +9,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "aws-ecs-integ2": { @@ -1114,7 +1114,7 @@ "aws:cdk:cloudformation:type": "AWS::Lambda::Function", "aws:cdk:cloudformation:props": { "code": { - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" }, "role": { "Fn::GetAtt": [ @@ -1211,7 +1211,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.33" } }, "LifecycleHookDrainHook": { diff --git a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts index 39d406e70c77d..991fefe36297c 100644 --- a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts +++ b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/runtime/index.ts @@ -133,7 +133,7 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent console.log(`Failed to patch AWS SDK: ${e}. Proceeding with the installed copy.`); } - console.log(JSON.stringify(event)); + console.log(JSON.stringify({ ...event, ResponseURL: '...' })); console.log('AWS SDK VERSION: ' + AWS.VERSION); event.ResourceProperties.Create = decodeCall(event.ResourceProperties.Create); diff --git a/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/cfn-response.ts b/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/cfn-response.ts index ec6ec576aeffa..c85d2f5975564 100644 --- a/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/cfn-response.ts +++ b/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/cfn-response.ts @@ -84,7 +84,7 @@ export function safeHandler(block: (event: any) => Promise) { } else { // otherwise, if PhysicalResourceId is not specified, something is // terribly wrong because all other events should have an ID. - log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify({ ...event, ResponseURL: '...' })}`); } } diff --git a/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts b/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts index 9c2d8a4bfc0fc..12a60efa88fc8 100644 --- a/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts +++ b/packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts @@ -24,7 +24,7 @@ export = { * @param cfnRequest The cloudformation custom resource event. */ async function onEvent(cfnRequest: AWSLambda.CloudFormationCustomResourceEvent) { - log('onEventHandler', cfnRequest); + log('onEventHandler', { ...cfnRequest, ResponseURL: '...' }); cfnRequest.ResourceProperties = cfnRequest.ResourceProperties || { }; @@ -102,7 +102,9 @@ async function invokeUserFunction(functionArnEnv: string, payload: any) { // automatically by the JavaScript SDK. const resp = await invokeFunction({ FunctionName: functionArn, - Payload: JSON.stringify(payload), + + // Strip 'ResponseURL' -- the downstream CR doesn't need it and can only log it by accident + Payload: JSON.stringify({ ...payload, ResponseURL: undefined }), }); log('user function response:', resp, typeof(resp)); diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/base.ts b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/base.ts index 829574f80d8eb..d8951a31cfadf 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/base.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/providers/lambda-handler/base.ts @@ -29,7 +29,7 @@ export abstract class CustomResourceHandler { try { - console.log(`Event: ${JSON.stringify(this.event)}`); + console.log(`Event: ${JSON.stringify({ ...this.event, ResponseURL: '...' })}`); const response = await this.processEvent(this.event.ResourceProperties as unknown as Request); console.log(`Event output : ${JSON.stringify(response)}`); await this.respond({ diff --git a/packages/@aws-cdk/triggers/lib/lambda/index.ts b/packages/@aws-cdk/triggers/lib/lambda/index.ts index 7975ac5b56bc0..633b33ada2ad5 100644 --- a/packages/@aws-cdk/triggers/lib/lambda/index.ts +++ b/packages/@aws-cdk/triggers/lib/lambda/index.ts @@ -15,7 +15,7 @@ export const invoke: InvokeFunction = async functionName => { }; export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { - console.log({ event }); + console.log({ ...event, ResponseURL: '...' }); if (event.RequestType === 'Delete') { console.log('not calling trigger on DELETE'); diff --git a/packages/@aws-cdk/triggers/test/triggers.integ.snapshot/asset.6b78a08a66c707ed36509dde1cebf8e7d5244a3b039122c2c00a5137efb845e2/index.js b/packages/@aws-cdk/triggers/test/triggers.integ.snapshot/asset.6b78a08a66c707ed36509dde1cebf8e7d5244a3b039122c2c00a5137efb845e2/index.js index 69518faf7de0e..6ddf10aef5a24 100644 --- a/packages/@aws-cdk/triggers/test/triggers.integ.snapshot/asset.6b78a08a66c707ed36509dde1cebf8e7d5244a3b039122c2c00a5137efb845e2/index.js +++ b/packages/@aws-cdk/triggers/test/triggers.integ.snapshot/asset.6b78a08a66c707ed36509dde1cebf8e7d5244a3b039122c2c00a5137efb845e2/index.js @@ -13,7 +13,6 @@ exports.invoke = async (functionName) => { return invokeResponse; }; async function handler(event) { - var _a; console.log({ event }); if (event.RequestType === 'Delete') { console.log('not calling trigger on DELETE'); @@ -29,7 +28,7 @@ async function handler(event) { } // if the lambda function throws an error, parse the error message and fail if (invokeResponse.FunctionError) { - throw new Error(parseError((_a = invokeResponse.Payload) === null || _a === void 0 ? void 0 : _a.toString())); + throw new Error(parseError(invokeResponse.Payload?.toString())); } } exports.handler = handler; @@ -52,4 +51,4 @@ function parseError(payload) { return payload; } } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0JBQStCOzs7QUFFL0IsNkRBQTZEO0FBQzdELCtCQUErQjtBQUlsQixRQUFBLE1BQU0sR0FBbUIsS0FBSyxFQUFDLFlBQVksRUFBQyxFQUFFO0lBQ3pELE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2hDLE1BQU0sYUFBYSxHQUFHLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxDQUFDO0lBQ3JELE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sY0FBYyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNwRSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztJQUNoQyxPQUFPLGNBQWMsQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFSyxLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtEOztJQUM5RSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUV2QixJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFO1FBQ2xDLE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUM3QyxPQUFPO0tBQ1I7SUFFRCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDO0lBQ3ZELElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7S0FDMUQ7SUFFRCxNQUFNLGNBQWMsR0FBRyxNQUFNLGNBQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUVoRCxJQUFJLGNBQWMsQ0FBQyxVQUFVLEtBQUssR0FBRyxFQUFFO1FBQ3JDLE1BQU0sSUFBSSxLQUFLLENBQUMsMkNBQTJDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0tBQ3pGO0lBRUQsMkVBQTJFO0lBQzNFLElBQUksY0FBYyxDQUFDLGFBQWEsRUFBRTtRQUNoQyxNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsT0FBQyxjQUFjLENBQUMsT0FBTywwQ0FBRSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0tBQ2pFO0FBQ0gsQ0FBQztBQXZCRCwwQkF1QkM7QUFBQSxDQUFDO0FBRUY7O0dBRUc7QUFDSCxTQUFTLFVBQVUsQ0FBQyxPQUEyQjtJQUM3QyxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksQ0FBQyxPQUFPLEVBQUU7UUFBRSxPQUFPLHVCQUF1QixDQUFDO0tBQUU7SUFDakQsSUFBSTtRQUNGLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0UsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7S0FDN0M7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLDBDQUEwQztRQUMxQyxPQUFPLE9BQU8sQ0FBQztLQUNoQjtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcblxuZXhwb3J0IHR5cGUgSW52b2tlRnVuY3Rpb24gPSAoZnVuY3Rpb25OYW1lOiBzdHJpbmcpID0+IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+O1xuXG5leHBvcnQgY29uc3QgaW52b2tlOiBJbnZva2VGdW5jdGlvbiA9IGFzeW5jIGZ1bmN0aW9uTmFtZSA9PiB7XG4gIGNvbnN0IGxhbWJkYSA9IG5ldyBBV1MuTGFtYmRhKCk7XG4gIGNvbnN0IGludm9rZVJlcXVlc3QgPSB7IEZ1bmN0aW9uTmFtZTogZnVuY3Rpb25OYW1lIH07XG4gIGNvbnNvbGUubG9nKHsgaW52b2tlUmVxdWVzdCB9KTtcbiAgY29uc3QgaW52b2tlUmVzcG9uc2UgPSBhd2FpdCBsYW1iZGEuaW52b2tlKGludm9rZVJlcXVlc3QpLnByb21pc2UoKTtcbiAgY29uc29sZS5sb2coeyBpbnZva2VSZXNwb25zZSB9KTtcbiAgcmV0dXJuIGludm9rZVJlc3BvbnNlO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgY29uc29sZS5sb2coeyBldmVudCB9KTtcblxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnKSB7XG4gICAgY29uc29sZS5sb2coJ25vdCBjYWxsaW5nIHRyaWdnZXIgb24gREVMRVRFJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgaGFuZGxlckFybiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5IYW5kbGVyQXJuO1xuICBpZiAoIWhhbmRsZXJBcm4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBcIkhhbmRsZXJBcm5cIiBwcm9wZXJ0eSBpcyByZXF1aXJlZCcpO1xuICB9XG5cbiAgY29uc3QgaW52b2tlUmVzcG9uc2UgPSBhd2FpdCBpbnZva2UoaGFuZGxlckFybik7XG5cbiAgaWYgKGludm9rZVJlc3BvbnNlLlN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVHJpZ2dlciBoYW5kbGVyIGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICR7aW52b2tlUmVzcG9uc2UuU3RhdHVzQ29kZX1gKTtcbiAgfVxuXG4gIC8vIGlmIHRoZSBsYW1iZGEgZnVuY3Rpb24gdGhyb3dzIGFuIGVycm9yLCBwYXJzZSB0aGUgZXJyb3IgbWVzc2FnZSBhbmQgZmFpbFxuICBpZiAoaW52b2tlUmVzcG9uc2UuRnVuY3Rpb25FcnJvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihwYXJzZUVycm9yKGludm9rZVJlc3BvbnNlLlBheWxvYWQ/LnRvU3RyaW5nKCkpKTtcbiAgfVxufTtcblxuLyoqXG4gKiBQYXJzZSB0aGUgZXJyb3IgbWVzc2FnZSBmcm9tIHRoZSBsYW1iZGEgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRXJyb3IocGF5bG9hZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgY29uc29sZS5sb2coYEVycm9yIHBheWxvYWQ6ICR7cGF5bG9hZH1gKTtcbiAgaWYgKCFwYXlsb2FkKSB7IHJldHVybiAndW5rbm93biBoYW5kbGVyIGVycm9yJzsgfVxuICB0cnkge1xuICAgIGNvbnN0IGVycm9yID0gSlNPTi5wYXJzZShwYXlsb2FkKTtcbiAgICBjb25zdCBjb25jYXQgPSBbZXJyb3IuZXJyb3JNZXNzYWdlLCBlcnJvci50cmFjZV0uZmlsdGVyKHggPT4geCkuam9pbignXFxuJyk7XG4gICAgcmV0dXJuIGNvbmNhdC5sZW5ndGggPiAwID8gY29uY2F0IDogcGF5bG9hZDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIGZhbGwgYmFjayB0byBqdXN0IHJldHVybmluZyB0aGUgcGF5bG9hZFxuICAgIHJldHVybiBwYXlsb2FkO1xuICB9XG59XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0JBQStCOzs7QUFFL0IsNkRBQTZEO0FBQzdELCtCQUErQjtBQUlsQixRQUFBLE1BQU0sR0FBbUIsS0FBSyxFQUFDLFlBQVksRUFBQyxFQUFFO0lBQ3pELE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2hDLE1BQU0sYUFBYSxHQUFHLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxDQUFDO0lBQ3JELE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sY0FBYyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNwRSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztJQUNoQyxPQUFPLGNBQWMsQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFSyxLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtEO0lBQzlFLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBRXZCLElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUU7UUFDbEMsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQzdDLE9BQU87S0FDUjtJQUVELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLENBQUM7SUFDdkQsSUFBSSxDQUFDLFVBQVUsRUFBRTtRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztLQUMxRDtJQUVELE1BQU0sY0FBYyxHQUFHLE1BQU0sY0FBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRWhELElBQUksY0FBYyxDQUFDLFVBQVUsS0FBSyxHQUFHLEVBQUU7UUFDckMsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsY0FBYyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7S0FDekY7SUFFRCwyRUFBMkU7SUFDM0UsSUFBSSxjQUFjLENBQUMsYUFBYSxFQUFFO1FBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0tBQ2pFO0FBQ0gsQ0FBQztBQXZCRCwwQkF1QkM7QUFBQSxDQUFDO0FBRUY7O0dBRUc7QUFDSCxTQUFTLFVBQVUsQ0FBQyxPQUEyQjtJQUM3QyxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksQ0FBQyxPQUFPLEVBQUU7UUFBRSxPQUFPLHVCQUF1QixDQUFDO0tBQUU7SUFDakQsSUFBSTtRQUNGLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0UsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7S0FDN0M7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLDBDQUEwQztRQUMxQyxPQUFPLE9BQU8sQ0FBQztLQUNoQjtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcblxuZXhwb3J0IHR5cGUgSW52b2tlRnVuY3Rpb24gPSAoZnVuY3Rpb25OYW1lOiBzdHJpbmcpID0+IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+O1xuXG5leHBvcnQgY29uc3QgaW52b2tlOiBJbnZva2VGdW5jdGlvbiA9IGFzeW5jIGZ1bmN0aW9uTmFtZSA9PiB7XG4gIGNvbnN0IGxhbWJkYSA9IG5ldyBBV1MuTGFtYmRhKCk7XG4gIGNvbnN0IGludm9rZVJlcXVlc3QgPSB7IEZ1bmN0aW9uTmFtZTogZnVuY3Rpb25OYW1lIH07XG4gIGNvbnNvbGUubG9nKHsgaW52b2tlUmVxdWVzdCB9KTtcbiAgY29uc3QgaW52b2tlUmVzcG9uc2UgPSBhd2FpdCBsYW1iZGEuaW52b2tlKGludm9rZVJlcXVlc3QpLnByb21pc2UoKTtcbiAgY29uc29sZS5sb2coeyBpbnZva2VSZXNwb25zZSB9KTtcbiAgcmV0dXJuIGludm9rZVJlc3BvbnNlO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpIHtcbiAgY29uc29sZS5sb2coeyBldmVudCB9KTtcblxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnKSB7XG4gICAgY29uc29sZS5sb2coJ25vdCBjYWxsaW5nIHRyaWdnZXIgb24gREVMRVRFJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgaGFuZGxlckFybiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5IYW5kbGVyQXJuO1xuICBpZiAoIWhhbmRsZXJBcm4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBcIkhhbmRsZXJBcm5cIiBwcm9wZXJ0eSBpcyByZXF1aXJlZCcpO1xuICB9XG5cbiAgY29uc3QgaW52b2tlUmVzcG9uc2UgPSBhd2FpdCBpbnZva2UoaGFuZGxlckFybik7XG5cbiAgaWYgKGludm9rZVJlc3BvbnNlLlN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVHJpZ2dlciBoYW5kbGVyIGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICR7aW52b2tlUmVzcG9uc2UuU3RhdHVzQ29kZX1gKTtcbiAgfVxuXG4gIC8vIGlmIHRoZSBsYW1iZGEgZnVuY3Rpb24gdGhyb3dzIGFuIGVycm9yLCBwYXJzZSB0aGUgZXJyb3IgbWVzc2FnZSBhbmQgZmFpbFxuICBpZiAoaW52b2tlUmVzcG9uc2UuRnVuY3Rpb25FcnJvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihwYXJzZUVycm9yKGludm9rZVJlc3BvbnNlLlBheWxvYWQ/LnRvU3RyaW5nKCkpKTtcbiAgfVxufTtcblxuLyoqXG4gKiBQYXJzZSB0aGUgZXJyb3IgbWVzc2FnZSBmcm9tIHRoZSBsYW1iZGEgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRXJyb3IocGF5bG9hZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgY29uc29sZS5sb2coYEVycm9yIHBheWxvYWQ6ICR7cGF5bG9hZH1gKTtcbiAgaWYgKCFwYXlsb2FkKSB7IHJldHVybiAndW5rbm93biBoYW5kbGVyIGVycm9yJzsgfVxuICB0cnkge1xuICAgIGNvbnN0IGVycm9yID0gSlNPTi5wYXJzZShwYXlsb2FkKTtcbiAgICBjb25zdCBjb25jYXQgPSBbZXJyb3IuZXJyb3JNZXNzYWdlLCBlcnJvci50cmFjZV0uZmlsdGVyKHggPT4geCkuam9pbignXFxuJyk7XG4gICAgcmV0dXJuIGNvbmNhdC5sZW5ndGggPiAwID8gY29uY2F0IDogcGF5bG9hZDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIGZhbGwgYmFjayB0byBqdXN0IHJldHVybmluZyB0aGUgcGF5bG9hZFxuICAgIHJldHVybiBwYXlsb2FkO1xuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/packages/aws-cdk/does-not-exist.json b/packages/aws-cdk/does-not-exist.json index 7541c6da15810..44efb5098e48f 100644 --- a/packages/aws-cdk/does-not-exist.json +++ b/packages/aws-cdk/does-not-exist.json @@ -1 +1 @@ -{"expiration":1654210101399,"notices":[{"title":"Error when building EKS cluster with monocdk import","issueNumber":17061,"overview":"When using monocdk/aws-eks to build a stack containing an EKS cluster, error is thrown about missing lambda-layer-node-proxy-agent/layer/package.json.","components":[{"name":"cli","version":"<1.130.0 >=1.126.0"}],"schemaVersion":"1"}]} +{"expiration":1656407830087,"notices":[{"title":"Error when building EKS cluster with monocdk import","issueNumber":17061,"overview":"When using monocdk/aws-eks to build a stack containing an EKS cluster, error is thrown about missing lambda-layer-node-proxy-agent/layer/package.json.","components":[{"name":"cli","version":"<1.130.0 >=1.126.0"}],"schemaVersion":"1"}]} diff --git a/tools/@aws-cdk/node-bundle/src/api/_attributions.ts b/tools/@aws-cdk/node-bundle/src/api/_attributions.ts index 48eaba16f1957..9e4caf033264f 100644 --- a/tools/@aws-cdk/node-bundle/src/api/_attributions.ts +++ b/tools/@aws-cdk/node-bundle/src/api/_attributions.ts @@ -37,7 +37,7 @@ export interface AttributionsProps { * */ readonly allowedLicenses: string[]; - /** + /** * Dependencies matching this pattern will be excluded from attribution. * * @default - no exclusions. diff --git a/tools/@aws-cdk/node-bundle/src/api/bundle.ts b/tools/@aws-cdk/node-bundle/src/api/bundle.ts index 2e2553373b309..302422075f0ef 100644 --- a/tools/@aws-cdk/node-bundle/src/api/bundle.ts +++ b/tools/@aws-cdk/node-bundle/src/api/bundle.ts @@ -235,11 +235,11 @@ export class Bundle { // to mutate it. const manifest = { ...this.manifest }; - // manifest mutations + // manifest mutations this.removeDependencies(manifest); this.addExternals(manifest); - // write artifacts + // write artifacts this.writeOutputs(target); this.writeResources(target); this.writeManifest(target, manifest);