From 869412535f564d5b36cf7cc5356aa38a381d02f1 Mon Sep 17 00:00:00 2001 From: Robert Djurasaj Date: Thu, 15 Feb 2024 11:04:31 -0700 Subject: [PATCH] feat(applicationautoscaling): timezone for ScheduledAction (#29116) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #22645 Closes #27754 Spiritual successor of #27052 Somewhat related to #21181 but that might be another PR down the road. @pahud :hand: Please review. I'm not particularly fond of how `aws-autoscaling` module ([here](https://github.com/aws/aws-cdk/blob/256cca4017a80f8643c5f5a5999a2ce0383eebf0/packages/aws-cdk-lib/aws-autoscaling/lib/scheduled-action.ts#L21)) is not using `cdk.TimeZone` class, hence why used it in this PR instead. I think we should we change `aws-autoscaling` implementation to do the same? It would be a breaking change... and most likely a brand new PR. LMK what you think. ✌️ Also, I may be slightly OCD but I kinda like better `timezone` vs `timeZone`, but I went with latter one to follow what `aws-autoscaling` did. cc-ing @kaizencc for his input too 🙌 ... possibly related to #27105 ### Reason for this change Timezones have been supported in `AWS::ApplicationAutoScaling::ScalableTarget ScheduledAction` for a while now. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationautoscaling-scalabletarget-scheduledaction.html#cfn-applicationautoscaling-scalabletarget-scheduledaction-timezone ### Description of changes Just added the support for `timezones` in `scalableTarget.scaleOnSchedule` ### Description of how you validated changes Added unit tests for this feature. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-applicationautoscaling/README.md | 7 ++-- .../lib/scalable-target.ts | 11 ++++++- .../test/scalable-target.test.ts | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk-lib/aws-applicationautoscaling/README.md b/packages/aws-cdk-lib/aws-applicationautoscaling/README.md index 6bc05ee9882f2..b52ef8ad4b1d7 100644 --- a/packages/aws-cdk-lib/aws-applicationautoscaling/README.md +++ b/packages/aws-cdk-lib/aws-applicationautoscaling/README.md @@ -177,6 +177,7 @@ The following example scales the fleet out in the morning, and lets natural scaling take over at night: ```ts +import { TimeZone } from 'aws-cdk-lib'; declare const resource: SomeScalableResource; const capacity = resource.autoScaleCapacity({ @@ -187,11 +188,13 @@ const capacity = resource.autoScaleCapacity({ capacity.scaleOnSchedule('PrescaleInTheMorning', { schedule: appscaling.Schedule.cron({ hour: '8', minute: '0' }), minCapacity: 20, + timeZone: TimeZone.AMERICA_DENVER, }); capacity.scaleOnSchedule('AllowDownscalingAtNight', { schedule: appscaling.Schedule.cron({ hour: '20', minute: '0' }), - minCapacity: 1 + minCapacity: 1, + timeZone: TimeZone.AMERICA_DENVER, }); ``` @@ -205,7 +208,7 @@ import * as lambda from 'aws-cdk-lib/aws-lambda'; declare const code: lambda.Code; const handler = new lambda.Function(this, 'MyFunction', { - runtime: lambda.Runtime.PYTHON_3_7, + runtime: lambda.Runtime.PYTHON_3_12, handler: 'index.handler', code, diff --git a/packages/aws-cdk-lib/aws-applicationautoscaling/lib/scalable-target.ts b/packages/aws-cdk-lib/aws-applicationautoscaling/lib/scalable-target.ts index fc806c27ac185..fe6fe8f31443e 100644 --- a/packages/aws-cdk-lib/aws-applicationautoscaling/lib/scalable-target.ts +++ b/packages/aws-cdk-lib/aws-applicationautoscaling/lib/scalable-target.ts @@ -4,7 +4,7 @@ import { Schedule } from './schedule'; import { BasicStepScalingPolicyProps, StepScalingPolicy } from './step-scaling-policy'; import { BasicTargetTrackingScalingPolicyProps, TargetTrackingScalingPolicy } from './target-tracking-scaling-policy'; import * as iam from '../../aws-iam'; -import { IResource, Lazy, Resource, withResolved } from '../../core'; +import { IResource, Lazy, Resource, TimeZone, withResolved } from '../../core'; export interface IScalableTarget extends IResource { /** @@ -161,6 +161,7 @@ export class ScalableTarget extends Resource implements IScalableTarget { maxCapacity: action.maxCapacity, minCapacity: action.minCapacity, }, + timezone: action.timeZone?.timezoneName, }); } @@ -225,6 +226,14 @@ export interface ScalingSchedule { * @default No new maximum capacity */ readonly maxCapacity?: number; + + /** + * The time zone used when referring to the date and time of a scheduled action, + * when the scheduled action uses an at or cron expression. + * + * @default - UTC + */ + readonly timeZone?: TimeZone; } /** diff --git a/packages/aws-cdk-lib/aws-applicationautoscaling/test/scalable-target.test.ts b/packages/aws-cdk-lib/aws-applicationautoscaling/test/scalable-target.test.ts index e6837fe329938..c5ac0cd4c5e8b 100644 --- a/packages/aws-cdk-lib/aws-applicationautoscaling/test/scalable-target.test.ts +++ b/packages/aws-cdk-lib/aws-applicationautoscaling/test/scalable-target.test.ts @@ -79,6 +79,38 @@ describe('scalable target', () => { }); }); + test('set timzone in scaleOnSchedule()', () => { + // GIVEN + const stack = new cdk.Stack(); + const target = createScalableTarget(stack); + + // WHEN + target.scaleOnSchedule('ScaleUp', { + schedule: appscaling.Schedule.cron({ + hour: '8', + day: '1', + }), + maxCapacity: 50, + minCapacity: 1, + timeZone: cdk.TimeZone.AMERICA_DENVER, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { + ScheduledActions: [ + { + ScalableTargetAction: { + MaxCapacity: 50, + MinCapacity: 1, + }, + Schedule: 'cron(* 8 1 * ? *)', + ScheduledActionName: 'ScaleUp', + Timezone: 'America/Denver', + }, + ], + }); + }); + test('scheduled scaling shows warning when minute is not defined in cron', () => { // GIVEN const stack = new cdk.Stack();