この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、臼田です。
みなさんLambdaしていますか?
今日はLambdaを導入する為に用意したCloudFormationで、特定のパラメータを指定すると失敗した経緯があり、回避策を吐き出そうと思ってブログにしました。
タイトルで何を言っているかわからない
多分そう思われる方も多いかもしれません。順に説明します。
まず、CloudWatchイベントではルールのスケジュール式の書き方にcron式とrate式がありますが、CloudFormationでは
AWS::Events::Ruleにてどちらも同じくScheduleExpressionとして文字列で指定する必要があります。
ここで問題になるのが、rate式ではrate(5 minutes)
のようにrate(数値 単位)
のフォーマットを取りますが、値が1の場合には単位が単数形になります。
1分間隔の場合にはrate(1 minutes)
ではなくrate(1 minute)
となります。's'がなくなります。英語的には適切な書き方ですが、この仕組はプログラマブルに処理したい時にはやや困ります。
CloudFormationではrate式をただの文字列として指定する必要があるため、数値をパラメータで取る場合で1を取りうる場合にはConditionsで条件関数を利用して判定し、処理を分ける必要があります。
というわけで、書いてみました。
Conditionsでrate式を変えるテンプレートの書き方
今回はLambdaを実行するためのCloudWatchイベントをrate式で作成する事を想定します。
パラメータの指定は以下のようになっています。
Parameters:
INTERVAL:
Description: "Enter the interval of get log cycle.(minutes, Max 180)"
Type: Number
Default: 60
MaxValue: 180
MinValue: 1
1分から最大180分で取ります。cron式で登録しようと思うと、分単位なら0 - 59
までしか取れないので、1時間以上の時間をパラメータから取ろうと思ったら基本こうなると思います。
Conditionsは以下のようになります。
Conditions:
IsSingular: !Equals [ !Ref INTERVAL, 1 ]
IsPlural: !Not [ !Equals [ !Ref INTERVAL, 1 ] ]
INTERVAL
が1
なら単数形にする必要があるので、その成否で取ります。
Conditionsの結果はtrueならリソースを作成する, falseならしないの判断しかできないので、2つのConditionsが必要になります。
実際のリソースでは下記のようにConditionsを設定します。(Lambdaのリソースは省略します)
Resources:
ScheduledRule:
Type: "AWS::Events::Rule"
Condition: IsPlural
Properties:
Description: "ScheduledRule"
ScheduleExpression: !Join [ "", [ "rate(", Ref: INTERVAL, " minutes)" ] ]
State: "ENABLED"
Targets:
- Arn: !GetAtt SampleLambda.Arn
Id: "SampleLambda"
PermissionForEventsToInvokeLambda:
Type: "AWS::Lambda::Permission"
Condition: IsPlural
Properties:
FunctionName:
Ref: "SampleLambda"
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn: !GetAtt ScheduledRule.Arn
# If INTERVAL is 1, set rate to minute (not minute's'!).
ScheduledRuleSingular:
Type: "AWS::Events::Rule"
Condition: IsSingular
Properties:
Description: "ScheduledRule"
ScheduleExpression: !Join [ "", [ "rate(", Ref: INTERVAL, " minute)" ] ]
State: "ENABLED"
Targets:
- Arn: !GetAtt SampleLambda.Arn
Id: "SampleLambda"
PermissionForEventsToInvokeLambdaSingular:
Type: "AWS::Lambda::Permission"
Condition: IsSingular
Properties:
FunctionName:
Ref: "SampleLambda"
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn: !GetAtt ScheduledRuleSingular.Arn
まず、作成するAWS::Events::Rule
リソースが2つになります。そして、必ずどちらかのConditionsを指定します。
そして、Lambdaを実行する権限のリソースがAWS::Events::Rule
を指しているので、こちらも同じようにConditionsを指定して2つ作成します。それぞれ指定するSourceArn
も変わります。
以上でCloudFormationのパラメータでCloudWatchイベントで単数形、複数形両方の値に対応することができます。
おわりに
rate式を利用する時に単位が変わってしまうのはやや使いづらいですが、上記を利用して対応しましょう。
何方かのお役に立てれば幸いです。