Skip to content

Commit 2ceec6c

Browse files
authored
feat(core): Introduced Duration class (#2857)
This can be used to model durations in a user-friendly way, while allowing coercion into the desired/required time unit at the usage site. There is now a default requirement that properties exposed by the APIs and that have a duration-like name (ending in `duration`, `period`, `timeout` or `ttl`) have a type of `@aws-cdk/cdk.Duration` and do not contain a unit suffix (`Days`, `Millis`, `Seconds`, `Sec`, ...). BREAKING CHANGE: Properties throughout the AWS Construct Libraries that represent lengths of time have been re-typed to be `@aws-cdk/cdk.Duration` instead of `number`, and were renamed to exclude any unit indication.
1 parent 4f13e18 commit 2ceec6c

File tree

118 files changed

+820
-492
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+820
-492
lines changed

packages/@aws-cdk/aws-apigateway/lib/stage.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Construct, Resource, Stack } from '@aws-cdk/cdk';
1+
import { Construct, Duration, Resource, Stack } from '@aws-cdk/cdk';
22
import { CfnStage } from './apigateway.generated';
33
import { Deployment } from './deployment';
44
import { IRestApi } from './restapi';
@@ -145,9 +145,9 @@ export interface MethodDeploymentOptions {
145145
* higher the TTL, the longer the response will be cached.
146146
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html
147147
*
148-
* @default 300
148+
* @default Duration.minutes(5)
149149
*/
150-
readonly cacheTtlSeconds?: number;
150+
readonly cacheTtl?: Duration;
151151

152152
/**
153153
* Indicates whether the cached responses are encrypted.
@@ -224,7 +224,7 @@ export class Stage extends Resource {
224224
throttlingBurstLimit: props.throttlingBurstLimit,
225225
throttlingRateLimit: props.throttlingRateLimit,
226226
cachingEnabled: props.cachingEnabled,
227-
cacheTtlSeconds: props.cacheTtlSeconds,
227+
cacheTtl: props.cacheTtl,
228228
cacheDataEncrypted: props.cacheDataEncrypted
229229
};
230230

@@ -256,7 +256,7 @@ export class Stage extends Resource {
256256
return {
257257
httpMethod, resourcePath,
258258
cacheDataEncrypted: options.cacheDataEncrypted,
259-
cacheTtlInSeconds: options.cacheTtlSeconds,
259+
cacheTtlInSeconds: options.cacheTtl && options.cacheTtl.toSeconds(),
260260
cachingEnabled: options.cachingEnabled,
261261
dataTraceEnabled: options.dataTraceEnabled,
262262
loggingLevel: options.loggingLevel,

packages/@aws-cdk/aws-apigateway/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"awslint": {
9393
"exclude": [
9494
"from-method:@aws-cdk/aws-apigateway.Resource",
95+
"duration-prop-type:@aws-cdk/aws-apigateway.QuotaSettings.period",
9596
"from-method:@aws-cdk/aws-apigateway.ApiKey",
9697
"ref-via-interface:@aws-cdk/aws-apigateway.ApiKeyProps.resources",
9798
"props-physical-name:@aws-cdk/aws-apigateway.DeploymentProps",

packages/@aws-cdk/aws-applicationautoscaling/lib/step-scaling-action.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export interface StepScalingActionProps {
3737
* @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_StepScalingPolicyConfiguration.html
3838
* @default No cooldown period
3939
*/
40-
readonly cooldownSec?: number;
40+
readonly cooldown?: cdk.Duration;
4141

4242
/**
4343
* Minimum absolute number to adjust capacity with as result of percentage scaling.
@@ -86,7 +86,7 @@ export class StepScalingAction extends cdk.Construct {
8686
scalingTargetId: props.scalingTarget.scalableTargetId,
8787
stepScalingPolicyConfiguration: {
8888
adjustmentType: props.adjustmentType,
89-
cooldown: props.cooldownSec,
89+
cooldown: props.cooldown && props.cooldown.toSeconds(),
9090
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
9191
metricAggregationType: props.metricAggregationType,
9292
stepAdjustments: cdk.Lazy.anyValue({ produce: () => this.adjustments }),

packages/@aws-cdk/aws-applicationautoscaling/lib/step-scaling-policy.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export interface BasicStepScalingPolicyProps {
3535
* @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_StepScalingPolicyConfiguration.html
3636
* @default No cooldown period
3737
*/
38-
readonly cooldownSec?: number;
38+
readonly cooldown?: cdk.Duration;
3939

4040
/**
4141
* Minimum absolute number to adjust capacity with as result of percentage scaling.
@@ -86,7 +86,7 @@ export class StepScalingPolicy extends cdk.Construct {
8686

8787
this.lowerAction = new StepScalingAction(this, 'LowerPolicy', {
8888
adjustmentType,
89-
cooldownSec: props.cooldownSec,
89+
cooldown: props.cooldown,
9090
metricAggregationType: aggregationTypeFromMetric(props.metric),
9191
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
9292
scalingTarget: props.scalingTarget,
@@ -101,8 +101,9 @@ export class StepScalingPolicy extends cdk.Construct {
101101
}
102102

103103
this.lowerAlarm = new cloudwatch.Alarm(this, 'LowerAlarm', {
104+
// Recommended by AutoScaling
104105
metric: props.metric,
105-
periodSec: 60, // Recommended by AutoScaling
106+
period: cdk.Duration.minutes(1), // Recommended by AutoScaling
106107
alarmDescription: 'Lower threshold scaling alarm',
107108
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
108109
evaluationPeriods: 1,
@@ -116,7 +117,7 @@ export class StepScalingPolicy extends cdk.Construct {
116117

117118
this.upperAction = new StepScalingAction(this, 'UpperPolicy', {
118119
adjustmentType,
119-
cooldownSec: props.cooldownSec,
120+
cooldown: props.cooldown,
120121
metricAggregationType: aggregationTypeFromMetric(props.metric),
121122
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
122123
scalingTarget: props.scalingTarget,
@@ -131,8 +132,9 @@ export class StepScalingPolicy extends cdk.Construct {
131132
}
132133

133134
this.upperAlarm = new cloudwatch.Alarm(this, 'UpperAlarm', {
135+
// Recommended by AutoScaling
134136
metric: props.metric,
135-
periodSec: 60, // Recommended by AutoScaling
137+
period: cdk.Duration.minutes(1), // Recommended by AutoScaling
136138
alarmDescription: 'Upper threshold scaling alarm',
137139
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
138140
evaluationPeriods: 1,

packages/@aws-cdk/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ export interface BaseTargetTrackingProps {
3737
*
3838
* @default - No scale in cooldown.
3939
*/
40-
readonly scaleInCooldownSec?: number;
40+
readonly scaleInCooldown?: cdk.Duration;
4141

4242
/**
4343
* Period after a scale out activity completes before another scale out activity can start.
4444
*
4545
* @default - No scale out cooldown.
4646
*/
47-
readonly scaleOutCooldownSec?: number;
47+
readonly scaleOutCooldown?: cdk.Duration;
4848
}
4949

5050
/**
@@ -115,13 +115,6 @@ export class TargetTrackingScalingPolicy extends cdk.Construct {
115115
throw new Error(`Exactly one of 'customMetric' or 'predefinedMetric' must be specified.`);
116116
}
117117

118-
if (props.scaleInCooldownSec !== undefined && props.scaleInCooldownSec < 0) {
119-
throw new RangeError(`scaleInCooldown cannot be negative, got: ${props.scaleInCooldownSec}`);
120-
}
121-
if (props.scaleOutCooldownSec !== undefined && props.scaleOutCooldownSec < 0) {
122-
throw new RangeError(`scaleOutCooldown cannot be negative, got: ${props.scaleOutCooldownSec}`);
123-
}
124-
125118
super(scope, id);
126119

127120
const resource = new CfnScalingPolicy(this, 'Resource', {
@@ -135,8 +128,8 @@ export class TargetTrackingScalingPolicy extends cdk.Construct {
135128
predefinedMetricType: props.predefinedMetric,
136129
resourceLabel: props.resourceLabel,
137130
} : undefined,
138-
scaleInCooldown: props.scaleInCooldownSec,
139-
scaleOutCooldown: props.scaleOutCooldownSec,
131+
scaleInCooldown: props.scaleInCooldown && props.scaleInCooldown.toSeconds(),
132+
scaleOutCooldown: props.scaleOutCooldown && props.scaleOutCooldown.toSeconds(),
140133
targetValue: props.targetValue
141134
}
142135
});

packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts

Lines changed: 12 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import elbv2 = require('@aws-cdk/aws-elasticloadbalancingv2');
55
import iam = require('@aws-cdk/aws-iam');
66
import sns = require('@aws-cdk/aws-sns');
77

8-
import { AutoScalingRollingUpdate, Construct, Fn, IResource, Lazy, Resource, Stack, Tag } from '@aws-cdk/cdk';
8+
import { AutoScalingRollingUpdate, Construct, Duration, Fn, IResource, Lazy, Resource, Stack, Tag } from '@aws-cdk/cdk';
99
import { CfnAutoScalingGroup, CfnAutoScalingGroupProps, CfnLaunchConfiguration } from './autoscaling.generated';
1010
import { BasicLifecycleHookProps, LifecycleHook } from './lifecycle-hook';
1111
import { BasicScheduledActionProps, ScheduledAction } from './scheduled-action';
@@ -130,16 +130,16 @@ export interface CommonAutoScalingGroupProps {
130130
*
131131
* The maximum value is 43200 (12 hours).
132132
*
133-
* @default 300 (5 minutes)
133+
* @default Duration.minutes(5)
134134
*/
135-
readonly resourceSignalTimeoutSec?: number;
135+
readonly resourceSignalTimeout?: Duration;
136136

137137
/**
138138
* Default scaling cooldown for this AutoScalingGroup
139139
*
140-
* @default 300 (5 minutes)
140+
* @default Duration.minutes(5)
141141
*/
142-
readonly cooldownSeconds?: number;
142+
readonly cooldown?: Duration;
143143

144144
/**
145145
* Whether instances in the Auto Scaling Group should have public
@@ -364,10 +364,6 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements
364364
constructor(scope: Construct, id: string, props: AutoScalingGroupProps) {
365365
super(scope, id);
366366

367-
if (props.cooldownSeconds !== undefined && props.cooldownSeconds < 0) {
368-
throw new RangeError(`cooldownSeconds cannot be negative, got: ${props.cooldownSeconds}`);
369-
}
370-
371367
this.securityGroup = new ec2.SecurityGroup(this, 'InstanceSecurityGroup', {
372368
vpc: props.vpc,
373369
allowAllOutbound: props.allowAllOutbound !== false
@@ -415,7 +411,7 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements
415411

416412
const { subnetIds } = props.vpc.selectSubnets(props.vpcSubnets);
417413
const asgProps: CfnAutoScalingGroupProps = {
418-
cooldown: props.cooldownSeconds !== undefined ? `${props.cooldownSeconds}` : undefined,
414+
cooldown: props.cooldown !== undefined ? props.cooldown.toSeconds().toString() : undefined,
419415
minSize: minCapacity.toString(),
420416
maxSize: maxCapacity.toString(),
421417
desiredCapacity: desiredCapacity.toString(),
@@ -542,12 +538,12 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements
542538
};
543539
}
544540

545-
if (props.resourceSignalCount !== undefined || props.resourceSignalTimeoutSec !== undefined) {
541+
if (props.resourceSignalCount !== undefined || props.resourceSignalTimeout !== undefined) {
546542
this.autoScalingGroup.options.creationPolicy = {
547543
...this.autoScalingGroup.options.creationPolicy,
548544
resourceSignal: {
549545
count: props.resourceSignalCount,
550-
timeout: props.resourceSignalTimeoutSec !== undefined ? renderIsoDuration(props.resourceSignalTimeoutSec) : undefined,
546+
timeout: props.resourceSignalTimeout,
551547
}
552548
};
553549
}
@@ -621,9 +617,9 @@ export interface RollingUpdateConfiguration {
621617
* PT#H#M#S, where each # is the number of hours, minutes, and seconds,
622618
* respectively). The maximum PauseTime is one hour (PT1H).
623619
*
624-
* @default 300 if the waitOnResourceSignals property is true, otherwise 0
620+
* @default Duration.minutes(5) if the waitOnResourceSignals property is true, otherwise 0
625621
*/
626-
readonly pauseTimeSec?: number;
622+
readonly pauseTime?: Duration;
627623

628624
/**
629625
* Specifies whether the Auto Scaling group waits on signals from new instances during an update.
@@ -667,14 +663,14 @@ export enum ScalingProcess {
667663
*/
668664
function renderRollingUpdateConfig(config: RollingUpdateConfiguration = {}): AutoScalingRollingUpdate {
669665
const waitOnResourceSignals = config.minSuccessfulInstancesPercent !== undefined ? true : false;
670-
const pauseTimeSec = config.pauseTimeSec !== undefined ? config.pauseTimeSec : (waitOnResourceSignals ? 300 : 0);
666+
const pauseTime = config.pauseTime || (waitOnResourceSignals ? Duration.minutes(5) : Duration.seconds(0));
671667

672668
return {
673669
maxBatchSize: config.maxBatchSize,
674670
minInstancesInService: config.minInstancesInService,
675671
minSuccessfulInstancesPercent: validatePercentage(config.minSuccessfulInstancesPercent),
676672
waitOnResourceSignals,
677-
pauseTime: renderIsoDuration(pauseTimeSec),
673+
pauseTime: pauseTime && pauseTime.toISOString(),
678674
suspendProcesses: config.suspendProcesses !== undefined ? config.suspendProcesses :
679675
// Recommended list of processes to suspend from here:
680676
// https://aws.amazon.com/premiumsupport/knowledge-center/auto-scaling-group-rolling-updates/
@@ -683,31 +679,6 @@ function renderRollingUpdateConfig(config: RollingUpdateConfiguration = {}): Aut
683679
};
684680
}
685681

686-
/**
687-
* Render a number of seconds to a PTnX string.
688-
*/
689-
function renderIsoDuration(seconds: number): string {
690-
const ret: string[] = [];
691-
692-
if (seconds === 0) {
693-
return 'PT0S';
694-
}
695-
696-
if (seconds >= 3600) {
697-
ret.push(`${Math.floor(seconds / 3600)}H`);
698-
seconds %= 3600;
699-
}
700-
if (seconds >= 60) {
701-
ret.push(`${Math.floor(seconds / 60)}M`);
702-
seconds %= 60;
703-
}
704-
if (seconds > 0) {
705-
ret.push(`${seconds}S`);
706-
}
707-
708-
return 'PT' + ret.join('');
709-
}
710-
711682
function validatePercentage(x?: number): number | undefined {
712683
if (x === undefined || (0 <= x && x <= 100)) { return x; }
713684
throw new Error(`Expected: a percentage 0..100, got: ${x}`);

packages/@aws-cdk/aws-autoscaling/lib/lifecycle-hook.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import iam = require('@aws-cdk/aws-iam');
2-
import { Construct, IResource, PhysicalName, Resource } from '@aws-cdk/cdk';
2+
import { Construct, Duration, IResource, PhysicalName, Resource } from '@aws-cdk/cdk';
33
import { IAutoScalingGroup } from './auto-scaling-group';
44
import { CfnLifecycleHook } from './autoscaling.generated';
55
import { ILifecycleHookTarget } from './lifecycle-hook-target';
@@ -29,7 +29,7 @@ export interface BasicLifecycleHookProps {
2929
*
3030
* @default - No heartbeat timeout.
3131
*/
32-
readonly heartbeatTimeoutSec?: number;
32+
readonly heartbeatTimeout?: Duration;
3333

3434
/**
3535
* The state of the Amazon EC2 instance to which you want to attach the lifecycle hook.
@@ -105,7 +105,7 @@ export class LifecycleHook extends Resource implements ILifecycleHook {
105105
const resource = new CfnLifecycleHook(this, 'Resource', {
106106
autoScalingGroupName: props.autoScalingGroup.autoScalingGroupName,
107107
defaultResult: props.defaultResult,
108-
heartbeatTimeout: props.heartbeatTimeoutSec,
108+
heartbeatTimeout: props.heartbeatTimeout && props.heartbeatTimeout.toSeconds(),
109109
lifecycleHookName: this.physicalName.value,
110110
lifecycleTransition: props.lifecycleTransition,
111111
notificationMetadata: props.notificationMetadata,

packages/@aws-cdk/aws-autoscaling/lib/step-scaling-action.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ export interface StepScalingActionProps {
1616
*
1717
* @default The default cooldown configured on the AutoScalingGroup
1818
*/
19-
readonly cooldownSeconds?: number;
19+
readonly cooldown?: cdk.Duration;
2020

2121
/**
2222
* Estimated time until a newly launched instance can send metrics to CloudWatch.
2323
*
2424
* @default Same as the cooldown
2525
*/
26-
readonly estimatedInstanceWarmupSeconds?: number;
26+
readonly estimatedInstanceWarmup?: cdk.Duration;
2727

2828
/**
2929
* How the adjustment numbers are interpreted
@@ -73,8 +73,8 @@ export class StepScalingAction extends cdk.Construct {
7373
const resource = new CfnScalingPolicy(this, 'Resource', {
7474
policyType: 'StepScaling',
7575
autoScalingGroupName: props.autoScalingGroup.autoScalingGroupName,
76-
cooldown: props.cooldownSeconds !== undefined ? `${props.cooldownSeconds}` : undefined,
77-
estimatedInstanceWarmup: props.estimatedInstanceWarmupSeconds,
76+
cooldown: props.cooldown && props.cooldown.toSeconds().toString(),
77+
estimatedInstanceWarmup: props.estimatedInstanceWarmup && props.estimatedInstanceWarmup.toSeconds(),
7878
adjustmentType: props.adjustmentType,
7979
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
8080
metricAggregationType: props.metricAggregationType,

packages/@aws-cdk/aws-autoscaling/lib/step-scaling-policy.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ export interface BasicStepScalingPolicyProps {
2929
*
3030
* @default Default cooldown period on your AutoScalingGroup
3131
*/
32-
readonly cooldownSeconds?: number;
32+
readonly cooldown?: cdk.Duration;
3333

3434
/**
3535
* Estimated time until a newly launched instance can send metrics to CloudWatch.
3636
*
3737
* @default Same as the cooldown
3838
*/
39-
readonly estimatedInstanceWarmupSeconds?: number;
39+
readonly estimatedInstanceWarmup?: cdk.Duration;
4040

4141
/**
4242
* Minimum absolute number to adjust capacity with as result of percentage scaling.
@@ -87,7 +87,7 @@ export class StepScalingPolicy extends cdk.Construct {
8787

8888
this.lowerAction = new StepScalingAction(this, 'LowerPolicy', {
8989
adjustmentType: props.adjustmentType,
90-
cooldownSeconds: props.cooldownSeconds,
90+
cooldown: props.cooldown,
9191
metricAggregationType: aggregationTypeFromMetric(props.metric),
9292
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
9393
autoScalingGroup: props.autoScalingGroup,
@@ -102,8 +102,9 @@ export class StepScalingPolicy extends cdk.Construct {
102102
}
103103

104104
this.lowerAlarm = new cloudwatch.Alarm(this, 'LowerAlarm', {
105+
// Recommended by AutoScaling
105106
metric: props.metric,
106-
periodSec: 60, // Recommended by AutoScaling
107+
period: cdk.Duration.minutes(1), // Recommended by AutoScaling
107108
alarmDescription: 'Lower threshold scaling alarm',
108109
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
109110
evaluationPeriods: 1,
@@ -117,7 +118,7 @@ export class StepScalingPolicy extends cdk.Construct {
117118

118119
this.upperAction = new StepScalingAction(this, 'UpperPolicy', {
119120
adjustmentType: props.adjustmentType,
120-
cooldownSeconds: props.cooldownSeconds,
121+
cooldown: props.cooldown,
121122
metricAggregationType: aggregationTypeFromMetric(props.metric),
122123
minAdjustmentMagnitude: props.minAdjustmentMagnitude,
123124
autoScalingGroup: props.autoScalingGroup,
@@ -134,7 +135,7 @@ export class StepScalingPolicy extends cdk.Construct {
134135
this.upperAlarm = new cloudwatch.Alarm(this, 'UpperAlarm', {
135136
// Recommended by AutoScaling
136137
metric: props.metric,
137-
periodSec: 60, // Recommended by AutoScaling
138+
period: cdk.Duration.minutes(1), // Recommended by AutoScaling
138139
alarmDescription: 'Upper threshold scaling alarm',
139140
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
140141
evaluationPeriods: 1,

0 commit comments

Comments
 (0)