Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
20 changes: 20 additions & 0 deletions docs/providers/aws/events/schedule.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,23 @@ functions:
key1: value1
key2: value2
```

## Schedule Groups

When using the `scheduler` method, you can organize your schedules into logical groups using the `groupName` property. This is useful for managing related schedules together.

```yaml
functions:
foo:
handler: foo.handler
events:
- schedule:
method: scheduler
rate: rate(15 minutes)
groupName: my-schedule-group
name: my-scheduled-event
description: 'Scheduled event with group'
input: '{"key": "value"}'
```

The `groupName` property is only supported with the `scheduler` method and will throw an error if used with the default `eventBus` method.
24 changes: 23 additions & 1 deletion lib/plugins/aws/package/compile/events/schedule.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ class AwsCompileScheduledEvents {
type: 'string',
pattern: '[\\w\\-\\/]+',
},
groupName: {
type: 'string',
minLength: 1,
maxLength: 64,
pattern: '[\\.\\-_A-Za-z0-9]+',
},
},
required: ['rate'],
additionalProperties: false,
Expand Down Expand Up @@ -129,6 +135,7 @@ class AwsCompileScheduledEvents {
let method
let roleArn
let timezone
let groupName

if (typeof event.schedule === 'object') {
ScheduleExpressions = event.schedule.rate
Expand All @@ -143,6 +150,7 @@ class AwsCompileScheduledEvents {
Name = event.schedule.name
timezone = event.schedule.timezone
Description = event.schedule.description
groupName = event.schedule.groupName

const functionLogicalId =
this.provider.naming.getLambdaLogicalId(functionName)
Expand Down Expand Up @@ -196,6 +204,12 @@ class AwsCompileScheduledEvents {
'SCHEDULE_PARAMETER_NOT_SUPPORTED',
)
}
if (groupName && method !== METHOD_SCHEDULER) {
throw new ServerlessError(
'Cannot setup "schedule" event: "groupName" is only supported with "scheduler" mode',
'SCHEDULE_PARAMETER_NOT_SUPPORTED',
)
}
} else {
ScheduleExpressions = [event.schedule]
State = 'ENABLED'
Expand Down Expand Up @@ -223,7 +237,8 @@ class AwsCompileScheduledEvents {
scheduleNumberInFunction,
)

resources[scheduleLogicalId] = {
// Create the schedule resource
const scheduleResource = {
Type: 'AWS::Scheduler::Schedule',
DependsOn: dependsOn,
Properties: {
Expand All @@ -242,6 +257,13 @@ class AwsCompileScheduledEvents {
ScheduleExpressionTimezone: timezone,
},
}

// Add GroupName if specified
if (groupName) {
scheduleResource.Properties.GroupName = groupName
}

resources[scheduleLogicalId] = scheduleResource
} else {
const scheduleLogicalId =
this.provider.naming.getScheduleLogicalId(
Expand Down
50 changes: 50 additions & 0 deletions test/unit/lib/plugins/aws/package/compile/events/schedule.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
],
},
},
{
schedule: {
rate: 'rate(30 minutes)',
method: METHOD_SCHEDULER,
name: 'scheduler-with-group',
description: 'Scheduler with Group',
groupName: 'my-schedule-group',
input: '{"key":"value"}',
},
},
]

;({ scheduleCfResources, iamResource, cfResources } = await run(events))
Expand All @@ -164,6 +174,7 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
expect(scheduleCfResources[7].Type).to.equal('AWS::Events::Rule')
expect(scheduleCfResources[8].Type).to.equal('AWS::Scheduler::Schedule')
expect(scheduleCfResources[9].Type).to.equal('AWS::Scheduler::Schedule')
expect(scheduleCfResources[10].Type).to.equal('AWS::Scheduler::Schedule')
})

it('should respect the given rate expressions', () => {
Expand Down Expand Up @@ -197,6 +208,9 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
expect(scheduleCfResources[9].Properties.ScheduleExpression).to.equal(
'cron(15 10 ? * SAT-SUN *)',
)
expect(scheduleCfResources[10].Properties.ScheduleExpression).to.equal(
'rate(30 minutes)',
)
})

it('should respect the "enabled" variable, defaulting to true', () => {
Expand All @@ -210,6 +224,7 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
expect(scheduleCfResources[7].Properties.State).to.equal('ENABLED')
expect(scheduleCfResources[8].Properties.State).to.equal('ENABLED')
expect(scheduleCfResources[9].Properties.State).to.equal('DISABLED')
expect(scheduleCfResources[10].Properties.State).to.equal('ENABLED')
})

it('should respect the "name" variable', () => {
Expand All @@ -229,6 +244,9 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
'scheduler-scheduled-event',
)
expect(scheduleCfResources[9].Properties.Name).to.be.undefined
expect(scheduleCfResources[10].Properties.Name).to.equal(
'scheduler-with-group',
)
})

it('should respect the "description" variable', () => {
Expand All @@ -250,6 +268,9 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
'Scheduler Scheduled Event',
)
expect(scheduleCfResources[9].Properties.Description).to.be.undefined
expect(scheduleCfResources[10].Properties.Description).to.equal(
'Scheduler with Group',
)
})

it('should respect the "inputPath" variable', () => {
Expand All @@ -272,6 +293,7 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
.undefined
expect(scheduleCfResources[8].Properties.Target.InputPath).to.be.undefined
expect(scheduleCfResources[9].Properties.Target.InputPath).to.be.undefined
expect(scheduleCfResources[10].Properties.Target.InputPath).to.be.undefined
})

it('should respect the "input" variable', () => {
Expand All @@ -293,6 +315,9 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
'{"key":"array"}',
)
expect(scheduleCfResources[9].Properties.Target.Input).to.be.undefined
expect(scheduleCfResources[10].Properties.Target.Input).to.equal(
'{"key":"value"}',
)
})

it('should respect the "inputTransformer" variable', () => {
Expand Down Expand Up @@ -320,6 +345,8 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
.undefined
expect(scheduleCfResources[9].Properties.Target.InputTransformer).to.be
.undefined
expect(scheduleCfResources[10].Properties.Target.InputTransformer).to.be
.undefined
})

it('should pass the roleArn to method:schedule resources', () => {
Expand All @@ -329,6 +356,9 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
expect(scheduleCfResources[9].Properties.Target.RoleArn).to.deep.equal({
'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'],
})
expect(scheduleCfResources[10].Properties.Target.RoleArn).to.deep.equal({
'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'],
})
})

it('should have scheduler policies when there are scheduler schedules', () => {
Expand Down Expand Up @@ -369,6 +399,26 @@ describe('test/unit/lib/plugins/aws/package/compile/events/schedule.test.js', ()
expect(resources).to.have.lengthOf(1)
expect(versionResources).to.have.lengthOf(1)
})

it('should respect the "groupName" variable when using method:scheduler', () => {
expect(scheduleCfResources[10].Properties.GroupName).to.equal('my-schedule-group')
})

it('should throw when passing "groupName" to method:eventBus resources', async () => {
const events = [
{
schedule: {
rate: 'rate(15 minutes)',
method: METHOD_EVENT_BUS,
groupName: 'my-schedule-group',
},
},
]

await expect(run(events))
.to.be.eventually.rejectedWith(ServerlessError)
.and.have.property('code', 'SCHEDULE_PARAMETER_NOT_SUPPORTED')
})
})

it('should throw an error if a "name" variable is specified when defining more than one rate expression', async () => {
Expand Down