Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(scheduler-alpha): deprecate Group in favour of ScheduleGroup #33678

Merged
merged 7 commits into from
Mar 5, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add schedule group
  • Loading branch information
gracelu0 committed Mar 3, 2025
commit 4522d5fdcfeea71c41c5e92d6ec4004aac00bbb8
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-scheduler-alpha/lib/group.ts
Original file line number Diff line number Diff line change
@@ -290,6 +290,7 @@ abstract class GroupBase extends Resource implements IGroup {
}
/**
* @resource AWS::Scheduler::ScheduleGroup
* @deprecated Use `ScheduleGroup` instead.
*/
export class Group extends GroupBase {
/**
@@ -298,6 +299,7 @@ export class Group extends GroupBase {
* @param scope construct scope
* @param id construct id
* @param groupArn the ARN of the group to import (e.g. `arn:aws:scheduler:region:account-id:schedule-group/group-name`)
* @deprecated use `ScheduleGroup.fromScheduleGroupArn()` instead
*/
public static fromGroupArn(scope: Construct, id: string, groupArn: string): IGroup {
const arnComponents = Stack.of(scope).splitArn(groupArn, ArnFormat.SLASH_RESOURCE_NAME);
363 changes: 363 additions & 0 deletions packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-group.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import * as iam from 'aws-cdk-lib/aws-iam';
import { CfnScheduleGroup } from 'aws-cdk-lib/aws-scheduler';
import { Arn, ArnFormat, Aws, IResource, Names, RemovalPolicy, Resource, Stack } from 'aws-cdk-lib/core';
import { addConstructMetadata } from 'aws-cdk-lib/core/lib/metadata-resource';
import { Construct } from 'constructs';

export interface ScheduleGroupProps {
/**
* The name of the schedule group.
*
* Up to 64 letters (uppercase and lowercase), numbers, hyphens, underscores and dots are allowed.
*
* @default - A unique name will be generated
*/
readonly scheduleGroupName?: string;

/**
* The removal policy for the group. If the group is removed also all schedules are removed.
*
* @default RemovalPolicy.RETAIN
*/
readonly removalPolicy?: RemovalPolicy;
}

export interface IScheduleGroup extends IResource {
/**
* The name of the schedule group
*
* @attribute
*/
readonly scheduleGroupName: string;

/**
* The arn of the schedule group
*
* @attribute
*/
readonly scheduleGroupArn: string;

/**
* Return the given named metric for this group schedules
*
* @default - sum over 5 minutes
*/
metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for the number of invocations that were throttled because it exceeds your service quotas.
*
* @see https://docs.aws.amazon.com/scheduler/latest/UserGuide/scheduler-quotas.html
*
* @default - sum over 5 minutes
*/
metricThrottled(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for all invocation attempts.
*
* @default - sum over 5 minutes
*/
metricAttempts(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Emitted when the target returns an exception after EventBridge Scheduler calls the target API.
*
* @default - sum over 5 minutes
*/
metricTargetErrors(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for invocation failures due to API throttling by the target.
*
* @default - sum over 5 minutes
*/
metricTargetThrottled(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for dropped invocations when EventBridge Scheduler stops attempting to invoke the target after a schedule's retry policy has been exhausted.
*
* @default - sum over 5 minutes
*/
metricDropped(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for invocations delivered to the DLQ
*
* @default - sum over 5 minutes
*/
metricSentToDLQ(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for failed invocations that also failed to deliver to DLQ.
*
* @default - sum over 5 minutes
*/
metricFailedToBeSentToDLQ(errorCode?: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Metric for delivery of failed invocations to DLQ when the payload of the event sent to the DLQ exceeds the maximum size allowed by Amazon SQS.
*
* @default - sum over 5 minutes
*/
metricSentToDLQTruncated(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Grant the indicated permissions on this group to the given principal
*/
grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant;
/**
* Grant list and get schedule permissions for schedules in this group to the given principal
*/
grantReadSchedules(identity: iam.IGrantable): iam.Grant;
/**
* Grant create and update schedule permissions for schedules in this group to the given principal
*/
grantWriteSchedules(identity: iam.IGrantable): iam.Grant;
/**
* Grant delete schedule permission for schedules in this group to the given principal
*/
grantDeleteSchedules(identity: iam.IGrantable): iam.Grant;
}

abstract class ScheduleGroupBase extends Resource implements IScheduleGroup {
/**
* The name of the schedule group
*
* @attribute
*/
public abstract readonly scheduleGroupName: string;

/**
* The arn of the schedule group
*
* @attribute
*/
public abstract readonly scheduleGroupArn: string;

/**
* Return the given named metric for this schedule group
*
* @default - sum over 5 minutes
*/
public metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return new cloudwatch.Metric({
namespace: 'AWS/Scheduler',
metricName,
dimensionsMap: { ScheduleGroup: this.scheduleGroupName },
statistic: 'sum',
...props,
}).attachTo(this);
}

/**
* Metric for the number of invocations that were throttled because it exceeds your service quotas.
*
* @see https://docs.aws.amazon.com/scheduler/latest/UserGuide/scheduler-quotas.html
*
* @default - sum over 5 minutes
*/
public metricThrottled(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('InvocationThrottleCount', props);
}

/**
* Metric for all invocation attempts.
*
* @default - sum over 5 minutes
*/
public metricAttempts(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('InvocationAttemptCount', props);
}

/**
* Emitted when the target returns an exception after EventBridge Scheduler calls the target API.
*
* @default - sum over 5 minutes
*/
public metricTargetErrors(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('TargetErrorCount', props);
}

/**
* Metric for invocation failures due to API throttling by the target.
*
* @default - sum over 5 minutes
*/
public metricTargetThrottled(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('TargetErrorThrottledCount', props);
}

/**
* Metric for dropped invocations when EventBridge Scheduler stops attempting to invoke the target after a schedule's retry policy has been exhausted.
*
* @default - sum over 5 minutes
*/
public metricDropped(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('InvocationDroppedCount', props);
}

/**
* Metric for invocations delivered to the DLQ
*
* @default - sum over 5 minutes
*/
public metricSentToDLQ(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('InvocationsSentToDeadLetterCount', props);
}

/**
* Metric for failed invocations that also failed to deliver to DLQ.
*
* @default - sum over 5 minutes
*/
public metricFailedToBeSentToDLQ(errorCode?: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric {
if (errorCode) {
return this.metric(`InvocationsFailedToBeSentToDeadLetterCount_${errorCode}`, props);
}

return this.metric('InvocationsFailedToBeSentToDeadLetterCount', props);
}

/**
* Metric for delivery of failed invocations to DLQ when the payload of the event sent to the DLQ exceeds the maximum size allowed by Amazon SQS.
*
* @default - sum over 5 minutes
*/
public metricSentToDLQTruncated(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('InvocationsSentToDeadLetterCount_Truncated_MessageSizeExceeded', props);
}

/**
* Grant the indicated permissions on this schedule group to the given principal
*/
public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
return iam.Grant.addToPrincipal({
grantee,
actions,
resourceArns: [this.scheduleGroupArn],
scope: this,
});
}

private arnForScheduleInGroup(scheduleName: string): string {
return Arn.format({
region: this.env.region,
account: this.env.account,
partition: Aws.PARTITION,
service: 'scheduler',
resource: 'schedule',
resourceName: this.scheduleGroupName + '/' + scheduleName,
});
}

/**
* Grant list and get schedule permissions for schedules in this group to the given principal
*/
public grantReadSchedules(identity: iam.IGrantable) {
return iam.Grant.addToPrincipal({
grantee: identity,
actions: ['scheduler:GetSchedule', 'scheduler:ListSchedules'],
resourceArns: [this.arnForScheduleInGroup('*')],
scope: this,
});
}

/**
* Grant create and update schedule permissions for schedules in this group to the given principal
*/
public grantWriteSchedules(identity: iam.IGrantable): iam.Grant {
return iam.Grant.addToPrincipal({
grantee: identity,
actions: ['scheduler:CreateSchedule', 'scheduler:UpdateSchedule'],
resourceArns: [this.arnForScheduleInGroup('*')],
scope: this,
});
}

/**
* Grant delete schedule permission for schedules in this group to the given principal
*/
public grantDeleteSchedules(identity: iam.IGrantable): iam.Grant {
return iam.Grant.addToPrincipal({
grantee: identity,
actions: ['scheduler:DeleteSchedule'],
resourceArns: [this.arnForScheduleInGroup('*')],
scope: this,
});
}
}
/**
* @resource AWS::Scheduler::ScheduleGroup
*/
export class ScheduleGroup extends ScheduleGroupBase {
/**
* Import an external schedule group by ARN.
*
* @param scope construct scope
* @param id construct id
* @param scheduleGroupArn the ARN of the schedule group to import (e.g. `arn:aws:scheduler:region:account-id:schedule-group/group-name`)
*/
public static fromScheduleGroupArn(scope: Construct, id: string, scheduleGroupArn: string): IScheduleGroup {
const arnComponents = Stack.of(scope).splitArn(scheduleGroupArn, ArnFormat.SLASH_RESOURCE_NAME);
const scheduleGroupName = arnComponents.resourceName!;
class Import extends ScheduleGroupBase {
scheduleGroupName = scheduleGroupName;
scheduleGroupArn = scheduleGroupArn;
}
return new Import(scope, id);
}

/**
* Import a default schedule group.
*
* @param scope construct scope
* @param id construct id
*/
public static fromDefaultGroup(scope: Construct, id: string): IScheduleGroup {
return ScheduleGroup.fromScheduleGroupName(scope, id, 'default');
}

/**
* Import an existing schedule group with a given name.
*
* @param scope construct scope
* @param id construct id
* @param scheduleGroupName the name of the existing schedule group to import
*/
public static fromScheduleGroupName(scope: Construct, id: string, scheduleGroupName: string): IScheduleGroup {
const groupArn = Stack.of(scope).formatArn({
service: 'scheduler',
resource: 'schedule-group',
resourceName: scheduleGroupName,
});
return ScheduleGroup.fromScheduleGroupArn(scope, id, groupArn);
}

public readonly scheduleGroupName: string;
public readonly scheduleGroupArn: string;

public constructor(scope: Construct, id: string, props: ScheduleGroupProps) {
super(scope, id);
// Enhanced CDK Analytics Telemetry
addConstructMetadata(this, props);

this.scheduleGroupName = props.scheduleGroupName ?? Names.uniqueResourceName(this, {
maxLength: 64,
separator: '-',
});

const resource = new CfnScheduleGroup(this, 'Resource', {
name: this.scheduleGroupName,
});

resource.applyRemovalPolicy(props.removalPolicy);

this.scheduleGroupArn = this.getResourceArnAttribute(resource.attrArn, {
service: 'scheduler',
resource: 'schedule-group',
resourceName: this.scheduleGroupName,
});
}
}