-
Notifications
You must be signed in to change notification settings - Fork 501
Add [ScheduleEvent] annotation attribute and source generator support #2323
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "Projects": [ | ||
| { | ||
| "Name": "Amazon.Lambda.Annotations", | ||
| "Type": "Minor", | ||
| "ChangelogMessages": [ | ||
| "Added [ScheduleEvent] annotation attribute for declaratively configuring schedule-triggered Lambda functions with support for rate and cron expressions, description, input, and enabled state." | ||
| ] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| using Amazon.Lambda.Annotations.Schedule; | ||
| using Microsoft.CodeAnalysis; | ||
| using System; | ||
|
|
||
| namespace Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes | ||
| { | ||
| /// <summary> | ||
| /// Builder for <see cref="ScheduleEventAttribute"/>. | ||
| /// </summary> | ||
| public class ScheduleEventAttributeBuilder | ||
| { | ||
| public static ScheduleEventAttribute Build(AttributeData att) | ||
| { | ||
| if (att.ConstructorArguments.Length != 1) | ||
| { | ||
| throw new NotSupportedException($"{TypeFullNames.ScheduleEventAttribute} must have constructor with 1 argument."); | ||
| } | ||
| var schedule = att.ConstructorArguments[0].Value as string; | ||
| var data = new ScheduleEventAttribute(schedule); | ||
|
|
||
| foreach (var pair in att.NamedArguments) | ||
| { | ||
| if (pair.Key == nameof(data.ResourceName) && pair.Value.Value is string resourceName) | ||
| { | ||
| data.ResourceName = resourceName; | ||
| } | ||
| else if (pair.Key == nameof(data.Description) && pair.Value.Value is string description) | ||
| { | ||
| data.Description = description; | ||
| } | ||
| else if (pair.Key == nameof(data.Input) && pair.Value.Value is string input) | ||
| { | ||
| data.Input = input; | ||
| } | ||
| else if (pair.Key == nameof(data.Enabled) && pair.Value.Value is bool enabled) | ||
| { | ||
| data.Enabled = enabled; | ||
| } | ||
| } | ||
|
|
||
| return data; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text.RegularExpressions; | ||
|
|
||
| namespace Amazon.Lambda.Annotations.Schedule | ||
| { | ||
| /// <summary> | ||
| /// This attribute defines the Schedule event source configuration for a Lambda function. | ||
| /// </summary> | ||
| [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] | ||
| public class ScheduleEventAttribute : Attribute | ||
| { | ||
| private static readonly Regex _resourceNameRegex = new Regex("^[a-zA-Z0-9]+$"); | ||
|
|
||
| /// <summary> | ||
| /// The schedule expression. Supports rate and cron expressions. | ||
| /// Examples: "rate(5 minutes)", "cron(0 12 * * ? *)" | ||
| /// </summary> | ||
| public string Schedule { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// The CloudFormation resource name for the schedule event. | ||
| /// </summary> | ||
| public string ResourceName | ||
| { | ||
| get | ||
| { | ||
| if (IsResourceNameSet) | ||
| { | ||
| return resourceName; | ||
| } | ||
| // Generate a default resource name from the schedule expression | ||
| var sanitized = string.Join(string.Empty, (Schedule ?? string.Empty).Where(char.IsLetterOrDigit)); | ||
| return sanitized.Length > 0 ? sanitized : "ScheduleEvent"; | ||
| } | ||
| set => resourceName = value; | ||
| } | ||
|
|
||
| private string resourceName { get; set; } = null; | ||
| internal bool IsResourceNameSet => resourceName != null; | ||
|
|
||
| /// <summary> | ||
| /// A description for the schedule rule. | ||
| /// </summary> | ||
| public string Description { get; set; } = null; | ||
| internal bool IsDescriptionSet => Description != null; | ||
|
|
||
| /// <summary> | ||
| /// A JSON string to pass as input to the Lambda function. | ||
| /// </summary> | ||
| public string Input { get; set; } = null; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feature suggestion: I doubt too many people want to put large JSON documents in this attribute. You could make the logic look to see if this is a file path, relative or absolute, and if it is read the file and put that in the template. If you do think this is worth adding be sure the comment block for Input calls out this can be a file path.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ill add this in a follow up PR |
||
| internal bool IsInputSet => Input != null; | ||
|
|
||
| /// <summary> | ||
| /// If set to false, the event source mapping will be disabled. Default value is true. | ||
|
GarrettBeatty marked this conversation as resolved.
|
||
| /// </summary> | ||
| public bool Enabled | ||
| { | ||
| get => enabled.GetValueOrDefault(true); | ||
| set => enabled = value; | ||
| } | ||
| private bool? enabled { get; set; } | ||
| internal bool IsEnabledSet => enabled.HasValue; | ||
|
|
||
|
GarrettBeatty marked this conversation as resolved.
|
||
| /// <summary> | ||
| /// Creates an instance of the <see cref="ScheduleEventAttribute"/> class. | ||
| /// </summary> | ||
| /// <param name="schedule"><see cref="Schedule"/> property</param> | ||
| public ScheduleEventAttribute(string schedule) | ||
| { | ||
| Schedule = schedule; | ||
| } | ||
|
|
||
| internal List<string> Validate() | ||
| { | ||
| var validationErrors = new List<string>(); | ||
|
|
||
| if (string.IsNullOrEmpty(Schedule)) | ||
| { | ||
| validationErrors.Add($"{nameof(ScheduleEventAttribute.Schedule)} must not be null or empty"); | ||
| } | ||
| else if (!Schedule.StartsWith("rate(") && !Schedule.StartsWith("cron(")) | ||
| { | ||
| validationErrors.Add($"{nameof(ScheduleEventAttribute.Schedule)} = {Schedule}. It must start with 'rate(' or 'cron('"); | ||
| } | ||
|
|
||
| if (IsResourceNameSet && !_resourceNameRegex.IsMatch(ResourceName)) | ||
| { | ||
| validationErrors.Add($"{nameof(ScheduleEventAttribute.ResourceName)} = {ResourceName}. It must only contain alphanumeric characters and must not be an empty string"); | ||
| } | ||
|
|
||
| return validationErrors; | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.