AWS Systems Manager Calendarの癖

# AWS Systems Manager Calendar　で何ができるか
+ 実行して良いタイミングかどうかを判定するために参照するもの
+ スケジュールの開始終了時間になったらイベント発行するもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/5ec119d8-7677-ee26-2dcd-01cfaac2b6bc.png)



AWS管理コンソール画面：カレンダーの種類をデフォルトCLOSEDにしたもの![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/c7bd8cae-ce3d-2189-33ec-bdd4831d4ed6.png)

スケジュールイベント時間になったら、カレンダーのステータスがOPEN・CLOSEDに切り替わる
※　１つのカレンダーには、複数のスケジュールイベントが登録できるが、カレンダー状態は一つ（OPENかCLOSED）


# まず用語

![08112655Menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/b441b94a-6ca1-edfd-89ea-f17ef75b027a.png)
”カレンダーの変更”？？？ 作成はどこでやるん？？
![08112559title.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/21dcbcdc-616c-0707-90fc-af1b90ea8e69.png)
”カレンダーを変更”？？？

タイトルは紛らわしい、日本語表記するなら"変更管理カレンダー"とかにしてもらいたいと思う。
ここでは ***SSM Change Calendar*** と表記します

# ***SSM Change Calendar*** リソースの構造 

+ ***SSM Change Calendar*** の実体は、DocumentTypeが"ChangeCalendar"のSSMドキュメント
+ そのSSMドキュメントの中にiCalendar形式(ICSファイル)が入っている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/6cfcfadc-f5bb-171a-9b1d-c54dd28e1a97.png)

## SSMドキュメントの中身

AWS公式サンプル（CloudFormation）で***SSM Change Calendar***を作成してみて、中身確認します
[AWS::SSM::Document - AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-document.html#aws-resource-ssm-document--examples)

```aws ssm get-document --name ChangeCalendar-Hogehoge --document-format TEXT``` で見てみると…

```json
{
    "Name": "ChangeCalendar-Hogehoge",
    "CreatedDate": "2022-09-09T09:22:52.705000+09:00",
    "DocumentVersion": "1",
    "Status": "Active",
    "Content": "BEGIN:VCALENDAR\r\nPRODID:-//AWS//Change Calendar 1.0//EN\r\nVERSION:2.0\r\nX-CALENDAR-TYPE:DEFAULT_OPEN\r\nX-WR-CALDESC:test\r\nBEGIN:VTODO\r\nDTSTAMP:20200320T004207Z\r\nUID:3b5af39a-d0b3-4049-a839-d7bb8af01f92\r\nSUMMARY:Add events to this calendar.\r\nEND:VTODO\r\nEND:VCALENDAR\r\n",
    "DocumentType": "ChangeCalendar",
    "DocumentFormat": "TEXT"
}
```

```Content```の部分がiCalendar形式(ICSファイル)

## iCalendar形式(ICSファイル)部分
整形してみると…
```yaml
BEGIN:VCALENDAR
PRODID:-//AWS//Change Calendar 1.0//EN
VERSION:2.0
X-CALENDAR-TYPE:DEFAULT_OPEN
X-WR-CALDESC:test
BEGIN:VTODO
DTSTAMP:20200320T004207Z
UID:3b5af39a-d0b3-4049-a839-d7bb8af01f92
SUMMARY:Add events to this calendar.
END:VTODO
END:VCALENDAR
```

iCalendar形式については、以下参考にしつつ・・・

[RFC-2445](https://www.rfc-editor.org/rfc/rfc2445)
[icsファイルの仕様について調べてみた](https://qiita.com/inagacky/items/89dd781f7cba15f54048)

---

### ```BEGIN:VCALENDAR``` 

ヘッダーセクション

| キー名 | 設定値 | 内容 |
|:-|:-|:-|
| PRODID |  -//AWS//Change Calendar 1.0//EN | カレンダーアプリケーション？ベンダー名 GoogleとかOutlookとか入るもの |
| VERSION | 2.0  | 2.0固定？ |
| X-CALENDAR-TYPE | DEFAULT_OPEN  | DEFAULT_OPEN か DEFAULT_CLOSED![08112758CalType.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/702203fa-567a-98e4-a6b2-2fe8499a2119.png) |
| X-WR-CALDESC | test  | ？？？必須ではなさそう |

### ```BEGIN:VTODO〜END:VTODO```
<details><summary>VTODOは意味がないと思われるので（ry</summary><div>
VTODOはiCalendar規格の”カレンダーの機能TODO”であり、***SSM Change Calendar*** では意味のないものだと思われる
VTODOのセクションを削って ***SSM Change Calendar*** に登録しようとするとエラーになる
VTODOの代わりにVEVENT（iCalendar規格の”カレンダーの機能スケジュールイベント”）を利用すると正常に登録できる
👉 スケジュールイベント(VEVENT)が０件の状態のカレンダーを作成しようとした時、機能上意味のないVTODOを使ったのだろうと推測
</div></details>

スケジュールイベントは、```VEVENT```セクションで指定する（後述）

### ```END:VCALENDAR```
でおわり

## スケジュールイベントの登録してみる

AWS管理コンソールからスケジュール登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/2c6dc405-762e-d81f-8243-962e5de9f352.png)

スケジュールイベントができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/7de78c32-3e0e-c808-b491-073aeaab9630.png)

確認してみると…
```shell
aws ssm get-document --name ChangeCalendar-Hogehoge --document-format TEXT --query "Content" --output text 
```

```yaml
BEGIN:VCALENDAR
PRODID:-//AWS//Change Calendar 1.0//EN
VERSION:2.0
X-CALENDAR-TYPE:DEFAULT_CLOSED
BEGIN:VEVENT
DTSTAMP:20220910T005141Z
UID:a781bac8-3856-4382-b2af-９９９９
SEQUENCE:0
SUMMARY:Hogehoge
DTSTART;TZID=Asia/Tokyo:20220910T170000
DTEND;TZID=Asia/Tokyo:20220910T180000
END:VEVENT
END:VCALENDAR
```

```VEVENT``` が作成されています

### VEVENTの主要な項目

| キー名 | 設定値 | 内容 |
|:-|:-|:-|
| UID  | a781bac8-3856-43…  | スケジュールイベントのユニークID |
| SUMMARY  | Hogehoge  | 表題のようなもの |
| DTSTART;TZID=Asia/Tokyo | 20220910T170000  |開始日（TZIDでタイムゾーン指定） |
| DTEND;TZID=Asia/Tokyo  | 20220910T180000  |終了日 |



# カレンダーイベントの動作

冒頭の説明通り、２通りの利用方法があるます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/5ec119d8-7677-ee26-2dcd-01cfaac2b6bc.png)


## ①　バッチやパイプラインで、今実行して良いのか確認する

AWS管理コンソールの***SSM Change Calendar***の説明タブにも記載されてますが

+ AWS CLIで確認するなら```get-calendar-state```で確認する

```shell:AWS CLI
aws ssm get-calendar-state --calendar-names arn:aws:ssm:ap-northeast-1:hogehoge --region ap-northeast-1
```

```json:戻り値
{
    "State": "CLOSED",
    "AtTime": "2022-09-09T23:18:35Z"
}
```


+ SSM Automationのステップに入れるのなら```GetCalendarState```で確認する

```yaml:Automation use
- name: checkChangeCalendarOpen
action: aws:assertAwsResourceProperty # Asserts an event state for Change Calendar
onFailure: step:closedCalendar # If Change Calendar state is CLOSED branch to "closedCalendar" step
timeoutSeconds: 600
inputs:
Service: ssm
Api: GetCalendarState
CalendarNames: ## List of calendars to check the status.
- arn:aws:ssm:ap-northeast-1:hogehoge
PropertySelector: "$.State" # Returns OPEN / CLOSED as state
DesiredValues:
- OPEN
nextStep: openCalendar # if Change Calendar state is OPEN “openCalendar” step is executed.
```


## ②　カレンダーの状態が変わったらお知らせする

***注意!!!***
時間になったらお知らせする訳ではないです。
時間になったらカレンダーのステータスがOPENかCLOSEDに変わるので、その時点で通知されます
例：カレンダーがOPEN中に、他のスケジュールイベントの時間が来てもOPENにしようとしても、すでにOPENなので、ステータス変更にはならない

~~スケジュールイベントの開始日時・終了日時~~ **カレンダーの状態変更時**に、イベントが発生する


```json: 通知されるイベント内容
{
  "version": "0",
  "id": "33ac1ac8-315a-4994-55a0-c980b543f766",
  "detail-type": "Calendar State Change",
  "source": "aws.ssm",
  "account": "123456789012",
  "time": "2020-09-17T18:10:00Z",
  "region": "us-east-1",
  "resources": ["arn:aws:ssm:us-east-1:123456789012:document/CWEDemo"],
  "detail": {
    "state": "OPEN",
    "atTime": "2020-09-17T18:10:00Z",
    "event": "CWEDemo"
  }
}
```

+ ```detail.state``` に OPEN / CLOSEDが設定される
+ ```detail.event``` に イベント表題・ ```VEVENTのSUMMARY``` が設定される


このイベントをEventBridgeで捕捉して、Lambda実行・CodePipeline実行・SSMオートメーション実行などなどができるます




# 構築方法

+ AWS管理コンソール
+ CloudFormation
+ AWS CLI


## AWS管理コンソールで作成

![09083342Create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/0335ecf3-c416-94e8-7cae-a500cff42395.png)

## CloudFormationで作成

[AWS::SSM::Document - AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-document.html#aws-resource-ssm-document--examples)

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  ExampleChangeCalendarDocument:
    Type: 'AWS::SSM::Document'
    Properties:
      Content: |
        BEGIN:VCALENDAR
        PRODID:-//AWS//Change Calendar 1.0//EN
        VERSION:2.0
        X-CALENDAR-TYPE:DEFAULT_OPEN
        X-WR-CALDESC:test
        BEGIN:VTODO
        DTSTAMP:20200320T004207Z
        UID:3b5af39a-d0b3-4049-a839-d7bb8af01f92
        SUMMARY:Add events to this calendar.
        END:VTODO
        END:VCALENDAR
      DocumentType: ChangeCalendar
      DocumentFormat: TEXT
```

前述の通り、```VTODO```は意味なさそうですが、スケジュールが空のカレンダーが作成されます

## AWS CLIで作成

[create-document](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ssm/create-document.html)

```shell:create-document
aws ssm create-document --name CalendarMei \
--document-type ChangeCalendar \
--document-format TEXT \
--content file://sample.ics
```

```yaml:sample.ics
BEGIN:VCALENDAR
PRODID:-//AWS//Change Calendar 1.0//EN
VERSION:2.0
X-CALENDAR-TYPE:DEFAULT_OPEN
X-WR-CALDESC:test
BEGIN:VTODO
DTSTAMP:20200320T004207Z
UID:3b5af39a-d0b3-4049-a839-d7bb8af01f92
SUMMARY:Add events to this calendar.
END:VTODO
END:VCALENDAR
```


# カレンダー更新方法

+ AWS管理コンソール
+ CloudFormation
+ AWS CLI

## AWS管理コンソールで更新

### 個別作成
ポチポチ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/2c6dc405-762e-d81f-8243-962e5de9f352.png)


### Google・Outlook・iCloudカレンダーからインポート

カレンダーの編集→Import　Calendar　でファイル投入

![08112758Modify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/0b8787f3-8120-8f30-1159-c3da3e91fddb.png)

<details><summary>←展開）ちなみに、こんな感じのICSファイル</summary><div>

```yaml
BEGIN:VCALENDAR
PRODID:-//Google Inc
VERSION:2.0
X-WR-CALNAME:gSSMCalendar
BEGIN:VEVENT
DTSTART:20220911T230000Z
DTEND:20220912T020000Z
UID:hoge001
SUMMARY:test1
END:VEVENT
BEGIN:VEVENT
DTSTART:20220912T230000Z
DTEND:20220913T020000Z
UID:hoge002
SUMMARY:test1
END:VEVENT
END:VCALENDAR
```
</div></details>

Googleからダウンロードしたファイルのインポート
インポート単位で管理できるため、まとめて削除できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/4966bd1f-4868-b916-7224-1411c16b0e89.png)


## CloudFormationで更新

SSMドキュメントをCloudFormationのStack更新すると、”作成削除”される様子。。。


## AWS CLIで更新
[update-document](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ssm/update-document.html)

```shell:update-document
aws ssm update-document --name CalendarMei \
--document-version '$LATEST' \
--content file://sampleupdate.ics
```

```yaml:sampleupdate.ics
BEGIN:VCALENDAR
PRODID:-//AWS//Change Calendar 1.0//EN
VERSION:2.0
X-WR-CALNAME:gSSMCalendar
X-CALENDAR-TYPE:DEFAULT_CLOSED
BEGIN:VEVENT
DTSTART:20220911T230000Z
DTEND:20220912T020000Z
UID:hoge001
SUMMARY:test1
END:VEVENT
BEGIN:VEVENT
DTSTART:20220912T230000Z
DTEND:20220913T020000Z
UID:hoge002
SUMMARY:test1
END:VEVENT
END:VCALENDAR
```

***注意!!!***
ちなみに
GoogleカレンダーからエクスポートしたICSファイルを使うと、👇こんなエラーになります。
（管理コンソールから投入するとOKなんですが・・）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/68b2ce47-8b97-d69c-c80c-daa2d19e7125.png)

原因はこれです
```PRODID:-//Google Inc//Google Calendar 70.9054//EN```
AWS以外で作ったカレンダーは入れたらダメだそうです
👇
```PRODID:-//AWS//Change Calendar 1.0//EN```
こう直して、もう一度update-documentを流すと直ります

# まとめ
本番利用する前に、きっちり運用方法を固めてテストしてから運用に乗せた方が良さそうですね