0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWS日記19 (CloudWatch Events)

Last updated at Posted at 2020-10-14

はじめに

今回は AWS CloudWatch Events を試します。
スケジュールをcron式で設定し、Lambda関数を実行するページを作成します。
[Lambda関数・SAMテンプレート]
(https://github.com/tanaka-takurou/serverless-application-cron-page-go)

準備

AWS SAM の準備をします

[AWS CloudWatch Eventsの資料]
AWS CloudWatch Events

AWS SAM テンプレート作成

AWS SAM テンプレートで API-Gateway , Lambda, CloudWatch Eventsの設定をします。

[参考資料]
AWS SAM テンプレートを作成する

template.yml
template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless Application Cron

Parameters:
  ApplicationName:
    Type: String
    Default: 'ServerlessApplicationCron'
  CronEventRuleName:
    Type: String
    Default: 'CronEventRule'
  CronMainFunctionName:
    Type: String
    Default: 'CronMainFunction'
  FrontPageApiStageName:
    Type: String
    Default: 'ProdStage'

Metadata:
  AWS::ServerlessRepo::Application:
    Name: Serverless-Application-Cron
    Description: 'This application is test for CloudWatch Events.'
    Author: tanaka-takurou
    SpdxLicenseId: MIT
    LicenseUrl: LICENSE.txt
    ReadmeUrl: README.md
    Labels: ['ServerlessRepo']
    HomePageUrl: https://github.com/tanaka-takurou/serverless-application-cron-page-go
    SemanticVersion: 0.0.1
    SourceCodeUrl: https://github.com/tanaka-takurou/serverless-application-cron-page-go

Resources:
  FrontPageApi:
    Type: AWS::Serverless::Api
    Properties:
      EndpointConfiguration: REGIONAL
      StageName: !Ref FrontPageApiStageName
  FrontPageFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: bin/
      Handler: main
      MemorySize: 256
      Runtime: go1.x
      Description: 'Cron Front Function'
      Events:
        FrontPageApi:
          Type: Api
          Properties:
            Path: '/'
            Method: get
            RestApiId: !Ref FrontPageApi
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          API_PATH: !Join [ '', [ '/', !Ref FrontPageApiStageName, '/api'] ]
  MainFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Ref CronMainFunctionName
      CodeUri: api/bin/
      Handler: main
      MemorySize: 256
      Runtime: go1.x
      Description: 'Cron API Function'
      Policies:
      - Statement:
        - Effect: 'Allow'
          Action:
            - 'logs:CreateLogGroup'
            - 'logs:CreateLogStream'
            - 'logs:PutLogEvents'
          Resource: '*'
        - Effect: 'Allow'
          Action:
            - 'lambda:*'
            - 'events:DescribeRule'
            - 'events:PutRule'
          Resource: '*'
      Environment:
        Variables:
          LAST_EVENT: ""
          EVENT_NAME: !Ref CronEventRuleName
          FUNCTION_NAME: !Ref CronMainFunctionName
          REGION: !Ref 'AWS::Region'
      Events:
        FrontPageApi:
          Type: Api
          Properties:
            Path: '/api'
            Method: post
            RestApiId: !Ref FrontPageApi
  CronApiPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref MainFunction
      Principal: apigateway.amazonaws.com
  CronEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Ref CronEventRuleName
      Description: CronRule
      ScheduleExpression: 'cron(0 12 * * ? *)'
      State: 'ENABLED'
      Targets:
        - Arn: !GetAtt MainFunction.Arn
          Id: TargetCronFunction
  PermissionForEventsToInvokeLambda:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MainFunction
      Action: 'lambda:InvokeFunction'
      Principal: 'events.amazonaws.com'
      SourceArn: !GetAtt CronEventRule.Arn

Outputs:
  APIURI:
    Value: !Join [ '', [ 'https://', !Ref FrontPageApi, '.execute-api.',!Ref 'AWS::Region','.amazonaws.com/',!Ref FrontPageApiStageName,'/'] ]

CloudWatch Eventsの設定は以下の部分

  CronEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Ref CronEventRuleName
      Description: CronRule
      ScheduleExpression: 'cron(0 12 * * ? *)'
      State: 'ENABLED'
      Targets:
        - Arn: !GetAtt MainFunction.Arn
          Id: TargetCronFunction
  PermissionForEventsToInvokeLambda:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MainFunction
      Action: 'lambda:InvokeFunction'
      Principal: 'events.amazonaws.com'
      SourceArn: !GetAtt CronEventRule.Arn

Lambda関数作成

※ Lambda関数は aws-lambda-go を利用し、CloudWatch Events周りの処理は aws-sdk-go-v2 を利用しました。
AWS SDK for Go API Reference V2

ルールを追加・更新するには PutRule を使う

func putRule(ctx context.Context, minute string, hour string, day string, month string, year string) error {
	var m_ int
	var h_ int
	var d_ int
	var o_ int
	var y_ int
	m_, _ = strconv.Atoi(minute)
	h_, _ = strconv.Atoi(hour)
	d_, _ = strconv.Atoi(day)
	o_, _ = strconv.Atoi(month)
	y_, _ = strconv.Atoi(year)
	if m_ < 0 {
		m_ = 0
	}
	sm := strconv.Itoa(m_)
	if h_ < 0 {
		h_ = 0
	}
	sh := strconv.Itoa(h_)
	sd := "*"
	if d_ > 0 {
		sd = strconv.Itoa(d_)
	}
	so := "*"
	if o_ > 0 {
		so = strconv.Itoa(o_)
	}
	sy := "*"
	if y_ >= 1970 {
		sy = strconv.Itoa(y_)
	}
	if cloudwatcheventsClient == nil {
		cloudwatcheventsClient = getCloudwatcheventsClient()
	}
	params := &cloudwatchevents.PutRuleInput{
		Name: aws.String(os.Getenv("EVENT_NAME")),
		ScheduleExpression: aws.String("cron(" + sm + " " + sh + " " + sd + " " + so + " ? " + sy + ")"),
	}
	res, err := cloudwatcheventsClient.PutRule(ctx, params)
	if err != nil {
		log.Print(err)
		return err
	}
	log.Printf("%+v\n", res)
	return nil
}

ルールの内容を取得するには DescribeRule を使う

func describeRule(ctx context.Context)(string, error) {
	if cloudwatcheventsClient == nil {
		cloudwatcheventsClient = getCloudwatcheventsClient()
	}
	params := &cloudwatchevents.DescribeRuleInput{
		Name: aws.String(os.Getenv("EVENT_NAME")),
	}
	res, err := cloudwatcheventsClient.DescribeRule(ctx, params)
	if err != nil {
		log.Print(err)
		return "", err
	}
	return stringValue(res.ScheduleExpression), nil
}

終わりに

cron式で指定するタイムゾーンはUTCのため、時差を考慮する必要があります。
Lambda関数以外も CloudWatch Eventから実行できるため、今後試していこうと思います。

参考資料
[Amazon CloudWatch Events で cron 式を使う場合は時差に気をつける](https://qiita.com/niwasawa/items/6e0b191d6aa21213c7ec) [CloudWatch Eventについての整理・備忘録](https://qiita.com/RyoMa_0923/items/61b67e12fb8aebd08241) [CloudFormationでCloudWatch EventsとLambdaを構築](https://qiita.com/tomoki_s/items/d23cd5eca26f7d778b73) [ルールのスケジュール式](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?