AWS Systems Manager Change Calendarに祝日や営業時間を設定してアプリケーションから利用する
みなさん、こんにちは!
福岡オフィスの青柳です。
今回は「AWS Systems Manager」の機能の一つである「Change Calendar」の便利な使い方を紹介したいと思います。
Systems Manager Change Calendarとは
Systems Manager Change Calendarとは、Systems Manager上で定義・管理できる「カレンダー」です。(そのまんまですね)
Change Calendarには、次のような利用の場面があります。
Systems Managerでカレンダーを利用する
Change Calendarを使うことで、Systems Managerの「Automation」や「Run Command」をスケジュールに従って実行することができます。
また、Systems Managerの「Change Manager」で変更を適用する際に、Change Calendarを使って「重要なバッチ処理が行われる時間帯」や「負荷が集中する時間帯」などを設定することにより、これらの時間帯を避けて適用を実施するという使い方もあります。
EventBridgeでカレンダーを利用する
Change Calendarは、Systems Manager以外のAWSサービスでも利用することができます。
例えば、Amazon EventBridgeのイベントソースとしてChange Calendarを指定することができます。
これにより、Change Calendarのカレンダーに定義されたスケジュールに従って、EventBridgeを介して様々な処理へ連係することができます。
例として、スケジュールに従って「Amazon WorkSpaces」の設定を切り替える仕組みを作ってみました。
Change Calendarからのイベントを検知するようにEventBridgeを設定する方法や、EventBridgeからLambda関数を呼び出して処理を行う方法について解説していますので、参考にしてください。
AWS APIを使って様々なAWSサービスからカレンダーを利用する
Change Calendarには、定義したカレンダーにおいて「特定の日時」が「稼働日 (稼働時間帯)」なのか「非稼働日 (非稼働時間帯)」なのかを判定する「GetCalendarState」というAPIが用意されています。
このAPIを使うことで、Systems ManagerやEventBridgeの他にも、様々なAWSサービスからChange Calendarを利用することができます。
例として、下記のブログ記事では、AWS Step FunctionsからChange CalendarのAPIを使ってスケジュール処理を行う手法を紹介しています。
今回のブログ記事では、この「AWS APIを使ってChange Calendarを利用する」の応用として、AWS APIがベースとなっている「AWS CLI」や「AWS SDK」を使ってChange Calendarを利用する方法をご紹介したいと思います。
その前に、まずは準備から行っていきましょう。
Change Calendarの「カレンダー」を作成する
Change Calendarの利用を開始する際には、まず「カレンダー」を作成します。
カレンダーを作成する際、以下の2種類の属性のいずれかを指定します。
- デフォルトが「OPEN」のカレンダー
- デフォルトが「CLOSED」のカレンダー
「OPEN」「CLOSED」って何だ?と思われるかもしれませんが、とりあえず、
- OPEN: 「営業日・営業時間帯」「稼働日・稼働時間帯」
- CLOSED: 「休業日・営業時間外」「非稼働日・停止時間帯」
と読み替えておいてください。
もう少しイメージし易いように、具体的な例を挙げて説明します。
例1) デフォルトが「OPEN」のカレンダーを使って「国民の祝日」を定義する
まず、新しいカレンダーを作成して「デフォルトで開く」(DEFAULT_OPEN
) を選択します。
作成したカレンダー上に、「祝日」を「イベント」として設定していきます。
※ 「祝日」は終日のものですので、上図のように「5月3日」を設定する際には「05/03 00:00:00 ~ 05/04 00:00:00」と指定する必要があります。
これを繰り返すことで、「祝日」の情報が定義されたカレンダーを作成します。
このカレンダーは、イベントが定義されていない日は「営業日」つまり「OPEN」であり、イベントが定義されている日は「休業日」つまり「CLOSED」となります。(とりあえず「土日」の存在は忘れてください)
このように、原則は「営業日 (営業時間帯)」であるが、特定の日付・時間帯を「休業日 (営業時間外)」にしたい場合に、「DEFAULT_OPEN」のカレンダーを使います。
~~~
なお、ここでは説明のために祝日を一つずつ手動で登録していますが、これだと大変ですので、「Google Calendar」など既存のカレンダーからインポートする方法をお勧めします。
例2) デフォルトが「CLOSED」のカレンダーを使って「営業時間帯」を定義する
新しいカレンダーを作成して、今度は「デフォルトで閉じる」(DEFAULT_CLOSED
) を選択します。
作成したカレンダー上に、「営業時間帯」を「イベント」として設定していきます。
上図のように、毎日・毎週・毎月・・・と繰り返されるイベントを定義することもできます。(ここでは「毎週」「月・火・水・木・金曜日」の「9:00~18:00」という設定を行いました)
※ 繰り返しイベントの開始日である5月2日にイベントが重複して登録されていますが、そういう仕様であるようです。動作には影響ないので無視してください。
このカレンダーは、イベントが定義されていない時間帯は「営業時間外」つまり「CLOSED」であり、イベントが定義されている時間帯は「営業時間帯」つまり「OPEN」となります。
このように、原則は「休業日 (営業時間外)」であるが、特定の日付・時間帯を「営業日 (営業時間帯)」にしたい場合に、「DEFAULT_CLOSED」のカレンダーを使います。
AWS CLIを使ってカレンダーの動作を確認する
作成したカレンダーが「営業日」「休業日」や「営業時間帯」「営業時間外」を意図した通りに制御できるのか、確認したいと思います。
実際にSystems ManagerのAutomationでChange Calendarを使ったりせずとも、AWS CLIを使って確認することができます。
カレンダーを使った「営業日」「休業日」の判定を行う
「国民の祝日」を定義したカレンダーを使って、指定した日付が「営業日」なのか「休業日」なのかを判定してみます。
$ aws ssm get-calendar-state \ --calendar-names "arn:aws:ssm:ap-northeast-1:123456789012:document/japan-national-holidays-calendar" \ --at-time "2022-05-01T00:00:00+09:00"
このコマンドによって、カレンダー「japan-national-holidays-calendar」を使って、指定した日時「2022-05-01 00:00:00」(日本時間) が「OPEN」であるのか「CLOSED」であるのかを判定させています。
(注意: 日時の指定は、厳密な「ISO 8601」の書式に準拠している必要があります)
以下のように結果が出力されたと思います。
{ "State": "OPEN", "AtTime": "2022-04-30T15:00:00Z", "NextTransitionTime": "2022-05-02T15:00:00Z" }
2022年5月1日は祝日ではありませんので「OPEN」が返ってきました。(結果に表示されている"AtTime"
はUTC時間なので気を付けてください)
では、コマンドに与える「日時」を変えてみると、どうでしょう?
$ aws ssm get-calendar-state \ --calendar-names "arn:aws:ssm:ap-northeast-1:123456789012:document/japan-national-holidays-calendar" \ --at-time "2022-05-03T00:00:00+09:00"
今度は、以下のように結果が出力されたと思います。
{ "State": "CLOSED", "AtTime": "2022-05-02T15:00:00Z", "NextTransitionTime": "2022-05-05T15:00:00Z" }
2022年5月3日は祝日ですので「CLOSED」が返ってきました。
複数のカレンダーを組み合わせて利用する
複数のカレンダーを組み合わせて「OPEN」「CLOSED」の判定を行うことができます。
例えば、上の例で作成した「祝日」カレンダーと「営業時間帯」カレンダーを組み合わせてみます。
$ aws ssm get-calendar-state \ --calendar-names "arn:aws:ssm:ap-northeast-1:123456789012:document/japan-national-holidays-calendar" \ "arn:aws:ssm:ap-northeast-1:123456789012:document/business-hours-calendar" \ --at-time "2022-05-02T06:00:00+09:00"
{ "State": "CLOSED", "AtTime": "2022-05-01T21:00:00Z", "NextTransitionTime": "2022-05-02T00:00:00Z" }
2022年5月2日は平日ですが、「06:00」は営業時間外ですので「CLOSED」が返ってきます。
続いて、同じ日付で「13:00」を指定してみます。
$ aws ssm get-calendar-state \ --calendar-names "arn:aws:ssm:ap-northeast-1:123456789012:document/japan-national-holidays-calendar" \ "arn:aws:ssm:ap-northeast-1:123456789012:document/business-hours-calendar" \ --at-time "2022-05-02T13:00:00+09:00"
{ "State": "OPEN", "AtTime": "2022-05-02T04:00:00Z", "NextTransitionTime": "2022-05-02T09:00:00Z" }
「13:00」は営業時間帯ですので、「OPEN」が返ってきます。
では、これではどうでしょう?
$ aws ssm get-calendar-state \ --calendar-names "arn:aws:ssm:ap-northeast-1:123456789012:document/japan-national-holidays-calendar" \ "arn:aws:ssm:ap-northeast-1:123456789012:document/business-hours-calendar" \ --at-time "2022-05-03T13:00:00+09:00"
{ "State": "CLOSED", "AtTime": "2022-05-03T04:00:00Z", "NextTransitionTime": "2022-05-06T00:00:00Z" }
「2022年5月3日」は祝日ですので、13:00を指定していても「CLOSED」が返ってきます。
このように、複数のカレンダーを指定して「OPEN」「CLOSED」の判定を行うことができます。
なお、複数のカレンダーを指定した場合の判定基準は、以下のようになっています。
- 全てのカレンダーにおいて「OPEN」と判定できる場合 → 結果は「OPEN」となる
- どれか一つのカレンダーでも「CLOSED」と判定された場合 → 結果は「CLOSED」となる
複数のカレンダーを使うことで、例えば「国民の祝日」カレンダーと「特別休業日 (年末年始など)」カレンダーを組み合わせて営業日の判定を行ったりすることができます。
なお、判定のメカニズムの仕様上、例えば「国民の祝日は原則として休業日であるが、ゴールデンウィークは『かき入れ時』なので臨時営業日とする」といった判定は、上記の手法では実現することができません。
その場合には、会社特有の「営業日カレンダー」(あるいは「休業日カレンダー」) を用意して、祝日や臨時営業日を反映することになります。
AWS SDKを使ってアプリケーションからカレンダーを利用する
AWS CLIに続いて、「AWS SDK」を使ったChange Calendarの利用を試してみます。
今回は、Lambda関数でAWS SDK for Pythonを使ったサンプルを作成することにします。
まず、Lambda関数がChange Calendarへアクセスできるように、IAMロール (Lambda実行ロール) を用意します。
以下のIAMポリシーを作成して、Lambda実行ロールへアタッチします。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetCalendarState" ], "Resource": "*" } ] }
Lambda関数を作成して、コードを記述します。
AWS SDK for Python (Boto3) の「SSM.Client」クラスの「get_calendar_state」メソッドを使います。
SSM — Boto3 Docs 1.21.46 documentation
client = boto3.client('ssm') response = client.get_calendar_state( CalendarNames=[ '<カレンダーの名前またはARN>', '<カレンダーの名前またはARN>', ・・・ ], AtTime='<判定対象の日付時刻 (省略時は現在時刻を使う)>' )
パラメーターの指定方法はAWS CLIの時と似ています。
パラメーター | 説明 |
---|---|
CalendarNames |
参照するカレンダーを名前またはARNで指定します。 複数の指定が可能ですが、省略はできません。 |
AtTime |
判定対象の日付時刻をISO 8601形式で指定します。 省略時は現在時刻を指定したことになります。 |
なお、AWS CLIではカレンダーの指定は「ARN」で行う必要がありましたが、AWS SDK for Pythonでは「名前」「ARN」のいずれでも指定可能です。
サンプルコードは以下のようになりました。
import boto3 def lambda_handler(event, context): client = boto3.client('ssm') # イベントデータからパラメーターを取得 param_calendars = event.get('calendars') param_datetime = event.get('datetime', '') print('Parameter "calendars":', param_calendars) print('Parameter "datetime":', param_datetime) # パラメーター"datetime"の指定有無によってパラメーターの数を変える if param_datetime != '': # SSM Change Calendarを使って、指定したカレンダーにおける指定した日時の「状態」を取得する response = client.get_calendar_state( CalendarNames=param_calendars, AtTime=param_datetime ) print('Response from SSM Change Calendar:', response) else: # SSM Change Calendarを使って、指定したカレンダーにおける現在時刻の「状態」を取得する response = client.get_calendar_state( CalendarNames=param_calendars ) print('Response from SSM Change Calendar:', response) return response
Lambda関数をテストしてみます。
次のようなイベントデータを設定して、Lambda関数を実行します。
{ "calendars": [ "japan-national-holidays-calendar" ], "datetime": "2022-05-01T00:00:00+09:00" }
結果は以下のようになりました。
{ "State": "OPEN", "AtTime": "2022-04-30T15:00:00Z", "NextTransitionTime": "2022-05-02T15:00:00Z", "ResponseMetadata": { "RequestId": "41f5f93a-d7de-4e24-bcc8-9674b94a9c65", "HTTPStatusCode": 200, "HTTPHeaders": { "server": "Server", "date": "Sun, 24 Apr 2022 08:17:55 GMT", "content-type": "application/x-amz-json-1.1", "content-length": "92", "connection": "keep-alive", "x-amzn-requestid": "41f5f93a-d7de-4e24-bcc8-9674b94a9c65" }, "RetryAttempts": 0 } }
他にもいくつかテストデータを用意してみます。
テストデータ2: 日時を指定しないパターン
{ "calendars": [ "japan-national-holidays-calendar" ] }
テストデータ3: 複数のカレンダーを指定したパターン
{ "calendars": [ "japan-national-holidays-calendar", "business-hours-calendar" ], "datetime": "2022-05-01T00:00:00+09:00" }
実行結果は示しませんので、実際に試してみてください。
おわりに
今回は、Systems Manager Change Calendarのカレンダーを作成して、AWS CLIやAWS SDKから利用する方法について紹介しました。
AWS SDKのサンプルは「Python」「Lambda」を使いましたが、他のプログラム言語やプラットフォームでも同様にして利用できると思います。
Change Calendarをアプリケーションから利用する利点として、以下のようなことが考えられます。
- Systems Managerの「Automation」「Run Command」などで使用するカレンダーと同じものをアプリケーションも利用することで、管理が一元的できる。
- 独自にデータベースなどを使ってカレンダーを構築しなくても、AWS標準の機能によって実現することができる。
- 手動ではあるがGoogle Calendarなどからカレンダーのインポートが行えるため、「祝日カレンダー」などが手間をかけずに利用できる。
もちろん、アプリケーションが利用するカレンダーとしてどの方法を用いるのかについては、他にもいろいろな観点があると思います。
今回の手法を選択肢の一つとして考えて頂ければと思います。