この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
みなさん、こんにちは!
福岡オフィスの青柳です。
今回は「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などからカレンダーのインポートが行えるため、「祝日カレンダー」などが手間をかけずに利用できる。
もちろん、アプリケーションが利用するカレンダーとしてどの方法を用いるのかについては、他にもいろいろな観点があると思います。
今回の手法を選択肢の一つとして考えて頂ければと思います。