EventBridge を使用したスケジューラの例 AWS SDK for .NET - AWS SDK for .NET

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

EventBridge を使用したスケジューラの例 AWS SDK for .NET

次のコード例は、ス EventBridge ケジューラ AWS SDK for .NET で を使用してアクションを実行し、一般的なシナリオを実装する方法を示しています。

アクションはより大きなプログラムからのコードの抜粋であり、コンテキスト内で実行する必要があります。アクションは個々のサービス機能を呼び出す方法を示していますが、コンテキスト内のアクションは、関連するシナリオで確認できます。

「シナリオ」は、1 つのサービス内から、または他の AWS サービスと組み合わせて複数の関数を呼び出し、特定のタスクを実行する方法を示すコード例です。

各例には、完全なソースコードへのリンクが含まれています。このリンクには、コンテキスト内でコードをセットアップして実行する方法の手順が記載されています。

開始方法

次のコード例は、ス EventBridge ケジューラの使用を開始する方法を示しています。

AWS SDK for .NET
注記

については、「」を参照してください GitHub。用例一覧を検索し、AWS コード例リポジトリでの設定と実行の方法を確認してください。

public static class HelloScheduler { static async Task Main(string[] args) { // Use the AWS .NET Core Setup package to set up dependency injection for the EventBridge Scheduler service. // Use your AWS profile name, or leave it blank to use the default profile. using var host = Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => services.AddAWSService<IAmazonScheduler>() ).Build(); // Now the client is available for injection. var schedulerClient = host.Services.GetRequiredService<IAmazonScheduler>(); // You can use await and any of the async methods to get a response, or a paginator to list schedules or groups. var results = new List<ScheduleSummary>(); var paginateSchedules = schedulerClient.Paginators.ListSchedules( new ListSchedulesRequest()); Console.WriteLine( $"Hello AWS Scheduler! Let's list schedules in your account."); // Get the entire list using the paginator. await foreach (var schedule in paginateSchedules.Schedules) { results.Add(schedule); } Console.WriteLine($"\tTotal of {results.Count} schedule(s) available."); results.ForEach(s => Console.WriteLine($"\tSchedule: {s.Name}")); } }
  • API 詳細については、「 リファレンスListSchedules」の「」を参照してください。 AWS SDK for .NET API

アクション

次の例は、CreateSchedule を使用する方法を説明しています。

AWS SDK for .NET
注記

については、「」を参照してください GitHub。用例一覧を検索し、AWS コード例リポジトリでの設定と実行の方法を確認してください。

/// <summary> /// Creates a new schedule in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule.</param> /// <param name="scheduleExpression">The schedule expression that defines when the schedule should run.</param> /// <param name="scheduleGroupName">The name of the schedule group to which the schedule should be added.</param> /// <param name="deleteAfterCompletion">Indicates whether to delete the schedule after completion.</param> /// <param name="useFlexibleTimeWindow">Indicates whether to use a flexible time window for the schedule.</param> /// <param name="targetArn">ARN of the event target.</param> /// <param name="roleArn">Execution Role ARN.</param> /// <returns>True if the schedule was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleAsync( string name, string scheduleExpression, string scheduleGroupName, string targetArn, string roleArn, string input, bool deleteAfterCompletion = false, bool useFlexibleTimeWindow = false) { try { int hoursToRun = 1; int flexibleTimeWindowMinutes = 10; var request = new CreateScheduleRequest { Name = name, ScheduleExpression = scheduleExpression, GroupName = scheduleGroupName, Target = new Target { Arn = targetArn, RoleArn = roleArn, Input = input }, ActionAfterCompletion = deleteAfterCompletion ? ActionAfterCompletion.DELETE : ActionAfterCompletion.NONE, StartDate = DateTime.UtcNow, // Ignored for one-time schedules. EndDate = DateTime.UtcNow .AddHours(hoursToRun) // Ignored for one-time schedules. }; // Allow a flexible time window if the caller specifies it. request.FlexibleTimeWindow = new FlexibleTimeWindow { Mode = useFlexibleTimeWindow ? FlexibleTimeWindowMode.FLEXIBLE : FlexibleTimeWindowMode.OFF, MaximumWindowInMinutes = useFlexibleTimeWindow ? flexibleTimeWindowMinutes : null }; var response = await _amazonScheduler.CreateScheduleAsync(request); Console.WriteLine($"Successfully created schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {response.ScheduleArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"An error occurred while creating schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {ex.Message}"); return false; } }
  • API 詳細については、「 リファレンスCreateSchedule」の「」を参照してください。 AWS SDK for .NET API

次のコード例は、CreateScheduleGroup を使用する方法を示しています。

AWS SDK for .NET
注記

については、「」を参照してください GitHub。用例一覧を検索し、AWS コード例リポジトリでの設定と実行の方法を確認してください。

/// <summary> /// Creates a new schedule group in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group.</param> /// <returns>True if the schedule group was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleGroupAsync(string name) { try { var request = new CreateScheduleGroupRequest { Name = name }; var response = await _amazonScheduler.CreateScheduleGroupAsync(request); Console.WriteLine($"Successfully created schedule group '{name}': {response.ScheduleGroupArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule group '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError( $"An error occurred while creating schedule group '{name}': {ex.Message}"); return false; } }
  • API 詳細については、「 リファレンスCreateScheduleGroup」の「」を参照してください。 AWS SDK for .NET API

次の例は、DeleteSchedule を使用する方法を説明しています。

AWS SDK for .NET
注記

については、「」を参照してください GitHub。用例一覧を検索し、AWS コード例リポジトリでの設定と実行の方法を確認してください。

/// <summary> /// Deletes an existing schedule from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule to delete.</param> /// <param name="groupName">The group name of the schedule to delete.</param> /// <returns>True if the schedule was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleAsync(string name, string groupName) { try { var request = new DeleteScheduleRequest { Name = name, GroupName = groupName }; await _amazonScheduler.DeleteScheduleAsync(request); Console.WriteLine($"Successfully deleted schedule with name '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule with ID '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule with ID '{name}': {ex.Message}"); return false; } }
  • API 詳細については、「 リファレンスDeleteSchedule」の「」を参照してください。 AWS SDK for .NET API

次の例は、DeleteScheduleGroup を使用する方法を説明しています。

AWS SDK for .NET
注記

については、「」を参照してください GitHub。用例一覧を検索し、AWS コード例リポジトリでの設定と実行の方法を確認してください。

/// <summary> /// Deletes an existing schedule group from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group to delete.</param> /// <returns>True if the schedule group was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleGroupAsync(string name) { try { var request = new DeleteScheduleGroupRequest { Name = name }; await _amazonScheduler.DeleteScheduleGroupAsync(request); Console.WriteLine($"Successfully deleted schedule group '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule group '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule group '{name}': {ex.Message}"); return false; } }
  • API 詳細については、「 リファレンスDeleteScheduleGroup」の「」を参照してください。 AWS SDK for .NET API

シナリオ

次のコードサンプルは、以下の操作方法を示しています。

  • 必要なリソースを使用して AWS CloudFormation スタックをデプロイします。

  • ス EventBridge ケジューラのスケジュールグループを作成します。

  • 柔軟な時間枠で 1 回限りのス EventBridge ケジューラスケジュールを作成します。

  • 指定されたレートで定期的なス EventBridge ケジューラスケジュールを作成します。

  • EventBridge スケジュールとスケジュールグループを削除します。

  • リソースをクリーンアップし、スタックを削除します。

AWS SDK for .NET
注記

については、「」を参照してください GitHub。用例一覧を検索し、AWS コード例リポジトリでの設定と実行の方法を確認してください。

ワークフローを実行します。

using System.Text.RegularExpressions; using Amazon.CloudFormation; using Amazon.CloudFormation.Model; using Amazon.Scheduler; using Amazon.Scheduler.Model; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Logging.Debug; using SchedulerActions; using Exception = System.Exception; namespace SchedulerScenario; public class SchedulerWorkflow { /* Before running this .NET code example, set up your development environment, including your credentials. This .NET code example performs the following tasks for the Amazon EventBridge Scheduler workflow: 1. Prepare the Application: - Prompt the user for an email address to use for the subscription for the SNS topic subscription. - Prompt the user for a name for the Cloud Formation stack. - Deploy the Cloud Formation template in resources/cfn_template.yaml for resource creation. - Store the outputs of the stack into variables for use in the workflow. - Create a schedule group for all workflow schedules. 2. Create one-time Schedule: - Create a one-time schedule to send an initial event. - Use a Flexible Time Window and set the schedule to delete after completion. - Wait for the user to receive the event email from SNS. 3. Create a time-based schedule: - Prompt the user for how many X times per Y hours a recurring event should be scheduled. - Create the scheduled event for X times per hour for Y hours. - Wait for the user to receive the event email from SNS. - Delete the schedule when the user is finished. 4. Clean up: - Prompt the user for y/n answer if they want to destroy the stack and clean up all resources. - Delete the schedule group. - Destroy the Cloud Formation stack and wait until the stack has been removed. */ public static ILogger<SchedulerWorkflow> _logger = null!; public static SchedulerWrapper _schedulerWrapper = null!; public static IAmazonCloudFormation _amazonCloudFormation = null!; private static string _roleArn = null!; private static string _snsTopicArn = null!; public static bool _interactive = true; private static string _stackName = "default-scheduler-workflow-stack-name"; private static string _scheduleGroupName = "workflow-schedules-group"; private static string _stackResourcePath = "../../../../../../workflows/eventbridge_scheduler/resources/cfn_template.yaml"; public static async Task Main(string[] args) { using var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddFilter("System", LogLevel.Debug) .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace)) .ConfigureServices((_, services) => services.AddAWSService<IAmazonScheduler>() .AddAWSService<IAmazonCloudFormation>() .AddTransient<SchedulerWrapper>() ) .Build(); if (_interactive) { _logger = LoggerFactory.Create(builder => { builder.AddConsole(); }) .CreateLogger<SchedulerWorkflow>(); _schedulerWrapper = host.Services.GetRequiredService<SchedulerWrapper>(); _amazonCloudFormation = host.Services.GetRequiredService<IAmazonCloudFormation>(); } Console.WriteLine(new string('-', 80)); Console.WriteLine("Welcome to the Amazon EventBridge Scheduler Workflow."); Console.WriteLine(new string('-', 80)); try { Console.WriteLine(new string('-', 80)); var prepareSuccess = await PrepareApplication(); Console.WriteLine(new string('-', 80)); if (prepareSuccess) { Console.WriteLine(new string('-', 80)); await CreateOneTimeSchedule(); Console.WriteLine(new string('-', 80)); Console.WriteLine(new string('-', 80)); await CreateRecurringSchedule(); Console.WriteLine(new string('-', 80)); } Console.WriteLine(new string('-', 80)); await Cleanup(); Console.WriteLine(new string('-', 80)); } catch (Exception ex) { _logger.LogError(ex, "There was a problem with the workflow, initiating cleanup..."); _interactive = false; await Cleanup(); } Console.WriteLine("Amazon EventBridge Scheduler workflow completed."); } /// <summary> /// Prepares the application by creating the necessary resources. /// </summary> /// <returns>True if the application was prepared successfully.</returns> public static async Task<bool> PrepareApplication() { Console.WriteLine("Preparing the application..."); try { // Prompt the user for an email address to use for the subscription. Console.WriteLine("\nThis example creates resources in a CloudFormation stack, including an SNS topic" + "\nthat will be subscribed to the EventBridge Scheduler events. " + "\n\nYou will need to confirm the subscription in order to receive event emails. "); var emailAddress = PromptUserForEmail(); // Prompt the user for a name for the CloudFormation stack _stackName = PromptUserForStackName(); // Deploy the CloudFormation stack var deploySuccess = await DeployCloudFormationStack(_stackName, emailAddress); if (deploySuccess) { // Create a schedule group for all workflow schedules await _schedulerWrapper.CreateScheduleGroupAsync(_scheduleGroupName); Console.WriteLine("Application preparation complete."); return true; } } catch (Exception ex) { _logger.LogError(ex, "An error occurred while preparing the application."); } Console.WriteLine("Application preparation failed."); return false; } /// <summary> /// Deploys the CloudFormation stack with the necessary resources. /// </summary> /// <param name="stackName">The name of the CloudFormation stack.</param> /// <param name="email">The email to use for the subscription.</param> /// <returns>True if the stack was deployed successfully.</returns> private static async Task<bool> DeployCloudFormationStack(string stackName, string email) { Console.WriteLine($"\nDeploying CloudFormation stack: {stackName}"); try { var request = new CreateStackRequest { StackName = stackName, TemplateBody = await File.ReadAllTextAsync(_stackResourcePath), Capabilities = { Capability.CAPABILITY_NAMED_IAM } }; // If an email is provided, set the parameter. if (!string.IsNullOrWhiteSpace(email)) { request.Parameters = new List<Parameter>() { new() { ParameterKey = "email", ParameterValue = email } }; } var response = await _amazonCloudFormation.CreateStackAsync(request); if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) { Console.WriteLine($"CloudFormation stack creation started: {stackName}"); // Wait for the stack to be in CREATE_COMPLETE state bool stackCreated = await WaitForStackCompletion(response.StackId); if (stackCreated) { // Retrieve the output values var success = await GetStackOutputs(response.StackId); return success; } else { _logger.LogError($"CloudFormation stack creation failed: {stackName}"); return false; } } else { _logger.LogError($"Failed to create CloudFormation stack: {stackName}"); return false; } } catch (AlreadyExistsException) { _logger.LogWarning($"CloudFormation stack '{stackName}' already exists. Please provide a unique name."); var newStackName = PromptUserForStackName(); return await DeployCloudFormationStack(newStackName, email); } catch (Exception ex) { _logger.LogError(ex, $"An error occurred while deploying the CloudFormation stack: {stackName}"); return false; } } /// <summary> /// Waits for the CloudFormation stack to be in the CREATE_COMPLETE state. /// </summary> /// <param name="client">The CloudFormation client.</param> /// <param name="stackId">The ID of the CloudFormation stack.</param> /// <returns>True if the stack was created successfully.</returns> private static async Task<bool> WaitForStackCompletion(string stackId) { int retryCount = 0; const int maxRetries = 10; const int retryDelay = 30000; // 30 seconds. while (retryCount < maxRetries) { var describeStacksRequest = new DescribeStacksRequest { StackName = stackId }; var describeStacksResponse = await _amazonCloudFormation.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count > 0) { if (describeStacksResponse.Stacks[0].StackStatus == StackStatus.CREATE_COMPLETE) { Console.WriteLine("CloudFormation stack creation complete."); return true; } if (describeStacksResponse.Stacks[0].StackStatus == StackStatus.CREATE_FAILED || describeStacksResponse.Stacks[0].StackStatus == StackStatus.ROLLBACK_COMPLETE) { Console.WriteLine("CloudFormation stack creation failed."); return false; } } Console.WriteLine("Waiting for CloudFormation stack creation to complete..."); await Task.Delay(retryDelay); retryCount++; } _logger.LogError("Timed out waiting for CloudFormation stack creation to complete."); return false; } /// <summary> /// Retrieves the output values from the CloudFormation stack. /// </summary> /// <param name="stackId">The ID of the CloudFormation stack.</param> private static async Task<bool> GetStackOutputs(string stackId) { try { var describeStacksRequest = new DescribeStacksRequest { StackName = stackId }; var describeStacksResponse = await _amazonCloudFormation.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count > 0) { var stack = describeStacksResponse.Stacks[0]; _roleArn = GetStackOutputValue(stack, "RoleARN"); _snsTopicArn = GetStackOutputValue(stack, "SNStopicARN"); return true; } else { _logger.LogError($"No stack found for stack outputs: {stackId}"); return false; } } catch (Exception ex) { _logger.LogError( ex, $"Failed to retrieve CloudFormation stack outputs: {stackId}"); return false; } } /// <summary> /// Get an output value by key from a CloudFormation stack. /// </summary> /// <param name="stack">The CloudFormation stack.</param> /// <param name="outputKey">The key of the output.</param> /// <returns>The value as a string.</returns> private static string GetStackOutputValue(Stack stack, string outputKey) { var output = stack.Outputs.First(o => o.OutputKey == outputKey); var outputValue = output.OutputValue; Console.WriteLine($"Stack output {outputKey}: {outputValue}"); return outputValue; } /// <summary> /// Creates a one-time schedule to send an initial event. /// </summary> /// <returns>True if the one-time schedule was created successfully.</returns> public static async Task<bool> CreateOneTimeSchedule() { var scheduleName = PromptUserForResourceName("Enter a name for the one-time schedule:"); Console.WriteLine($"Creating a one-time schedule named '{scheduleName}' " + $"\nto send an initial event in 1 minute with a flexible time window..."); try { // Create a one-time schedule with a flexible time // window set to delete after completion. // You may also set a timezone instead of using UTC. var scheduledTime = DateTime.UtcNow.AddMinutes(1).ToString("s"); var createSuccess = await _schedulerWrapper.CreateScheduleAsync( scheduleName, $"at({scheduledTime})", _scheduleGroupName, _snsTopicArn, _roleArn, $"One time scheduled event test from schedule {scheduleName}.", true, useFlexibleTimeWindow: true); Console.WriteLine($"Subscription email will receive an email from this event."); Console.WriteLine($"You must confirm your subscription to receive event emails."); Console.WriteLine($"One-time schedule '{scheduleName}' created successfully."); return createSuccess; } catch (ResourceNotFoundException ex) { _logger.LogError(ex, $"The target with ARN '{_snsTopicArn}' was not found."); return false; } catch (Exception ex) { _logger.LogError(ex, $"An error occurred while creating the one-time schedule '{scheduleName}'."); return false; } } /// <summary> /// Create a recurring schedule to send events at a specified rate in minutes. /// </summary> /// <returns>True if the recurring schedule was created successfully.</returns> public static async Task<bool> CreateRecurringSchedule() { Console.WriteLine("Creating a recurring schedule to send events for one hour..."); try { // Prompt the user for a schedule name. var scheduleName = PromptUserForResourceName("Enter a name for the recurring schedule: "); // Prompt the user for the schedule rate (in minutes). var scheduleRateInMinutes = PromptUserForInteger("Enter the desired schedule rate (in minutes): "); // Create the recurring schedule. var createSuccess = await _schedulerWrapper.CreateScheduleAsync( scheduleName, $"rate({scheduleRateInMinutes} minutes)", _scheduleGroupName, _snsTopicArn, _roleArn, $"Recurrent event test from schedule {scheduleName}."); Console.WriteLine($"Subscription email will receive an email from this event."); Console.WriteLine($"You must confirm your subscription to receive event emails."); // Delete the schedule when the user is finished. if (!_interactive || GetYesNoResponse($"Are you ready to delete the '{scheduleName}' schedule? (y/n)")) { await _schedulerWrapper.DeleteScheduleAsync(scheduleName, _scheduleGroupName); } return createSuccess; } catch (ResourceNotFoundException ex) { _logger.LogError(ex, $"The target with ARN '{_snsTopicArn}' was not found."); return false; } catch (Exception ex) { _logger.LogError(ex, "An error occurred while creating the recurring schedule."); return false; } } /// <summary> /// Cleans up the resources created during the workflow. /// </summary> /// <returns>True if the cleanup was successful.</returns> public static async Task<bool> Cleanup() { // Prompt the user to confirm cleanup. var cleanup = !_interactive || GetYesNoResponse( "Do you want to delete all resources created by this workflow? (y/n) "); if (cleanup) { try { // Delete the schedule group. var groupDeleteSuccess = await _schedulerWrapper.DeleteScheduleGroupAsync(_scheduleGroupName); // Destroy the CloudFormation stack and wait for it to be removed. var stackDeleteSuccess = await DeleteCloudFormationStack(_stackName, false); return groupDeleteSuccess && stackDeleteSuccess; } catch (Exception ex) { _logger.LogError(ex, "An error occurred while cleaning up the resources."); return false; } } _logger.LogInformation("EventBridge Scheduler workflow is complete."); return true; } /// <summary> /// Delete the resources in the stack and wait for confirmation. /// </summary> /// <param name="stackName">The name of the stack.</param> /// <param name="forceDelete">True to force delete the stack.</param> /// <returns>True if successful.</returns> private static async Task<bool> DeleteCloudFormationStack(string stackName, bool forceDelete) { var request = new DeleteStackRequest { StackName = stackName, }; if (forceDelete) { request.DeletionMode = DeletionMode.FORCE_DELETE_STACK; } await _amazonCloudFormation.DeleteStackAsync(request); Console.WriteLine($"CloudFormation stack '{_stackName}' is being deleted. This may take a few minutes."); bool stackDeleted = await WaitForStackDeletion(_stackName, forceDelete); if (stackDeleted) { Console.WriteLine($"CloudFormation stack '{_stackName}' has been deleted."); return true; } else { _logger.LogError($"Failed to delete CloudFormation stack '{_stackName}'."); return false; } } /// <summary> /// Wait for the stack to be deleted. /// </summary> /// <param name="stackName">The name of the stack.</param> /// <param name="forceDelete">True to force delete the stack.</param> /// <returns>True if successful.</returns> private static async Task<bool> WaitForStackDeletion(string stackName, bool forceDelete) { int retryCount = 0; const int maxRetries = 10; const int retryDelay = 30000; // 30 seconds while (retryCount < maxRetries) { var describeStacksRequest = new DescribeStacksRequest { StackName = stackName }; try { var describeStacksResponse = await _amazonCloudFormation.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count == 0 || describeStacksResponse.Stacks[0].StackStatus == StackStatus.DELETE_COMPLETE) { return true; } if (!forceDelete && describeStacksResponse.Stacks[0].StackStatus == StackStatus.DELETE_FAILED) { // Try one time to force delete. return await DeleteCloudFormationStack(stackName, true); } } catch (AmazonCloudFormationException ex) when (ex.ErrorCode == "ValidationError") { // Stack does not exist, so it has been successfully deleted. return true; } Console.WriteLine($"Waiting for CloudFormation stack '{stackName}' to be deleted..."); await Task.Delay(retryDelay); retryCount++; } _logger.LogError($"Timed out waiting for CloudFormation stack '{stackName}' to be deleted."); return false; } /// <summary> /// Helper method to get a yes or no response from the user. /// </summary> /// <param name="question">The question string to print on the console.</param> /// <returns>True if the user responds with a yes.</returns> private static bool GetYesNoResponse(string question) { Console.WriteLine(question); var ynResponse = Console.ReadLine(); var response = ynResponse != null && ynResponse.Equals("y", StringComparison.InvariantCultureIgnoreCase); return response; } /// <summary> /// Prompt the user for a valid email address. /// </summary> /// <returns>The valid email address.</returns> private static string PromptUserForEmail() { if (_interactive) { Console.WriteLine("Enter an email address to use for event subscriptions: "); string email = Console.ReadLine()!; if (!IsValidEmail(email)) { Console.WriteLine("Invalid email address. Please try again."); return PromptUserForEmail(); } return email; } // Used when running without user prompts. return ""; } /// <summary> /// Prompt the user for a non-empty stack name. /// </summary> /// <returns>The valid stack name</returns> private static string PromptUserForStackName() { Console.WriteLine("Enter a name for the AWS Cloud Formation Stack: "); if (_interactive) { string stackName = Console.ReadLine()!; var regex = "[a-zA-Z][-a-zA-Z0-9]|arn:[-a-zA-Z0-9:/._+]"; if (!Regex.IsMatch(stackName, regex)) { Console.WriteLine( $"Invalid stack name. Please use a name that matches the pattern {regex}."); return PromptUserForStackName(); } return stackName; } // Used when running without user prompts. return _stackName; } /// <summary> /// Prompt the user for a non-empty resource name. /// </summary> /// <returns>The valid stack name</returns> private static string PromptUserForResourceName(string prompt) { if (_interactive) { Console.WriteLine(prompt); string resourceName = Console.ReadLine()!; var regex = "[0-9a-zA-Z-_.]+"; if (!Regex.IsMatch(resourceName, regex)) { Console.WriteLine($"Invalid resource name. Please use a name that matches the pattern {regex}."); return PromptUserForResourceName(prompt); } return resourceName!; } // Used when running without user prompts. return "resource-" + Guid.NewGuid(); } /// <summary> /// Prompt the user for a non-empty resource name. /// </summary> /// <returns>The valid stack name</returns> private static int PromptUserForInteger(string prompt) { if (_interactive) { Console.WriteLine(prompt); string stringResponse = Console.ReadLine()!; if (string.IsNullOrWhiteSpace(stringResponse) || !Int32.TryParse(stringResponse, out var intResponse)) { Console.WriteLine($"Invalid integer. "); return PromptUserForInteger(prompt); } return intResponse!; } // Used when running without user prompts. return 1; } /// <summary> /// Use System Mail to check for a valid email address. /// </summary> /// <param name="email">The string to verify.</param> /// <returns>True if a valid email address.</returns> private static bool IsValidEmail(string email) { try { var mailAddress = new System.Net.Mail.MailAddress(email); return mailAddress.Address == email; } catch { // Invalid emails will cause an exception, return false. return false; } } }

サービスオペレーションのラッパー。

using Amazon.Scheduler; using Amazon.Scheduler.Model; using Microsoft.Extensions.Logging; namespace SchedulerActions; /// <summary> /// Wrapper class for Amazon EventBridge Scheduler operations. /// </summary> public class SchedulerWrapper { private readonly IAmazonScheduler _amazonScheduler; private readonly ILogger<SchedulerWrapper> _logger; /// <summary> /// Constructor for the SchedulerWrapper class. /// </summary> /// <param name="amazonScheduler">The injected EventBridge Scheduler client.</param> /// <param name="logger">The injected logger.</param> public SchedulerWrapper(IAmazonScheduler amazonScheduler, ILogger<SchedulerWrapper> logger) { _amazonScheduler = amazonScheduler; _logger = logger; } /// <summary> /// Creates a new schedule in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule.</param> /// <param name="scheduleExpression">The schedule expression that defines when the schedule should run.</param> /// <param name="scheduleGroupName">The name of the schedule group to which the schedule should be added.</param> /// <param name="deleteAfterCompletion">Indicates whether to delete the schedule after completion.</param> /// <param name="useFlexibleTimeWindow">Indicates whether to use a flexible time window for the schedule.</param> /// <param name="targetArn">ARN of the event target.</param> /// <param name="roleArn">Execution Role ARN.</param> /// <returns>True if the schedule was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleAsync( string name, string scheduleExpression, string scheduleGroupName, string targetArn, string roleArn, string input, bool deleteAfterCompletion = false, bool useFlexibleTimeWindow = false) { try { int hoursToRun = 1; int flexibleTimeWindowMinutes = 10; var request = new CreateScheduleRequest { Name = name, ScheduleExpression = scheduleExpression, GroupName = scheduleGroupName, Target = new Target { Arn = targetArn, RoleArn = roleArn, Input = input }, ActionAfterCompletion = deleteAfterCompletion ? ActionAfterCompletion.DELETE : ActionAfterCompletion.NONE, StartDate = DateTime.UtcNow, // Ignored for one-time schedules. EndDate = DateTime.UtcNow .AddHours(hoursToRun) // Ignored for one-time schedules. }; // Allow a flexible time window if the caller specifies it. request.FlexibleTimeWindow = new FlexibleTimeWindow { Mode = useFlexibleTimeWindow ? FlexibleTimeWindowMode.FLEXIBLE : FlexibleTimeWindowMode.OFF, MaximumWindowInMinutes = useFlexibleTimeWindow ? flexibleTimeWindowMinutes : null }; var response = await _amazonScheduler.CreateScheduleAsync(request); Console.WriteLine($"Successfully created schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {response.ScheduleArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"An error occurred while creating schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {ex.Message}"); return false; } } /// <summary> /// Creates a new schedule group in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group.</param> /// <returns>True if the schedule group was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleGroupAsync(string name) { try { var request = new CreateScheduleGroupRequest { Name = name }; var response = await _amazonScheduler.CreateScheduleGroupAsync(request); Console.WriteLine($"Successfully created schedule group '{name}': {response.ScheduleGroupArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule group '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError( $"An error occurred while creating schedule group '{name}': {ex.Message}"); return false; } } /// <summary> /// Deletes an existing schedule from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule to delete.</param> /// <param name="groupName">The group name of the schedule to delete.</param> /// <returns>True if the schedule was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleAsync(string name, string groupName) { try { var request = new DeleteScheduleRequest { Name = name, GroupName = groupName }; await _amazonScheduler.DeleteScheduleAsync(request); Console.WriteLine($"Successfully deleted schedule with name '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule with ID '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule with ID '{name}': {ex.Message}"); return false; } } /// <summary> /// Deletes an existing schedule group from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group to delete.</param> /// <returns>True if the schedule group was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleGroupAsync(string name) { try { var request = new DeleteScheduleGroupRequest { Name = name }; await _amazonScheduler.DeleteScheduleGroupAsync(request); Console.WriteLine($"Successfully deleted schedule group '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule group '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule group '{name}': {ex.Message}"); return false; } } }