Lambdaの特定のエイリアスのみにEventSourceをマッピングするCloudFormationの設定json


以前に、[CodePipeLineを使ってLambdaへの自動デプロイ](https://qiita.com/RyujiKawazoe/items/38411271230f9e112253)という記事を書きました。

私は、それからLambdaに対して本番環境やテスト環境でうまく分けるために以下の設定を考えました。

1. Lambdaに新規のバージョンを作成する
2. 1の新規のバージョンに対して、Aliasを設定する
3. 2で設定したAliasに対してKinesisなどのイベントソースを指定する



どのようなCloudFormationのjsonを記述するか
---

先に結論のjsonをあげると、以下のようになります。

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "sample",
    "Parameters": {
        "LatestS3Bucket": {
            "Type": "String"
        },
        "LatestS3Key": {
            "Type": "String"
        }
    },
    "Resources": {
        "MyLambda": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "FunctionName": "my-function",
                "Code": {
                    "S3Bucket": {
                        "Ref": "LatestS3Bucket"
                    },
                    "S3Key": {
                        "Ref": "LatestS3Key"
                    }
                },
                "Description": "20180330",
                "Handler": "index.handler",
                "Role": "arn:aws:iam::1234567890:role/myrole",
                "Runtime": "nodejs6.10",
                "Environment": {
                    "Variables": {
                        "VAR1": "VAR1",
                        "VAR2": "VAR2"
                    }
                },
                "Timeout": 30,
                "MemorySize": 128
            }
        },
        "EventSource": {
            "Type": "AWS::Lambda::EventSourceMapping",
            "Properties": {
                "BatchSize": 100,
                "Enabled": true,
                "EventSourceArn": "arn:aws:kinesis:ap-northeast-1:01234567890:stream/my-stream",
                "FunctionName": {
                    "Fn::Join": [
                        ":",
                        [
                            {
                                "Fn::GetAtt": [
                                    "MyLambda",
                                    "Arn"
                                ]
                            },
                            "DEV"
                        ]
                    ]
                },
                "StartingPosition": "TRIM_HORIZON"
            }
        },
        "LambdaNewVersion": {
            "Type": "AWS::Lambda::Version",
            "Properties": {
                "FunctionName": {
                    "Ref": "MyLambda"
                }
            }
        },
        "LambdaNewVersionAlias": {
            "Type": "AWS::Lambda::Alias",
            "Properties": {
                "FunctionName": {
                    "Ref": "MyLambda"
                },
                "FunctionVersion": {
                    "Fn::GetAtt": [
                        "LambdaNewVersion",
                        "Version"
                    ]
                },
                "Name": "DEV"
            }
        }
    }
}
```


Lambdaに新規のバージョンを作成するには？
---


下記のような記述をすれば、新規に作成されます。

```
        "LambdaNewVersion": {
            "Type": "AWS::Lambda::Version",
            "Properties": {
                "FunctionName": {
                    "Ref": "MyLambda"
                }
            }
        }
```

上記の設定で一度実行し、version: 1というものができたあと、version: 2がつくりたいのであれば以下のように書き換える必要があります。

```
        "LambdaNewVersion2": {
            "Type": "AWS::Lambda::Version",
            "Properties": {
                "FunctionName": {
                    "Ref": "MyLambda"
                }
            }
        }
```

Aliasを設定するには?
----

これは特に難しいことはなく、下記のように記述します。

```
        "LambdaNewVersionAlias": {
            "Type": "AWS::Lambda::Alias",
            "Properties": {
                "FunctionName": {
                    "Ref": "MyLambda"
                },
                "FunctionVersion": {
                    "Fn::GetAtt": [
                        "LambdaNewVersion",
                        "Version"
                    ]
                },
                "Name": "DEV"
            }
        }
```

これでDEVというAliasが設定されます。

設定したAliasに対してKinesisなどのイベントソースを指定するには？
---

これは下記のような、Aliasの設定がないCloudFormationの書き方だと$LATESTにイベントソースがマッピングされます。

```
        "EventSource": {
            "Type": "AWS::Lambda::EventSourceMapping",
            "Properties": {
                "BatchSize": 100,
                "Enabled": true,
                "EventSourceArn": "arn:aws:kinesis:ap-northeast-1:01234567890:stream/my-stream",
                "FunctionName": {
   						"Ref": "MyLambda"
                },
                "StartingPosition": "TRIM_HORIZON"
            }
        }
        
```

       
これは `arn:aws:lambda:ap-northeast-1:01234567890:function:my-function` にそのまま紐付けてる書き方を意味しているので、Aliasを設定した書き方をするならば `Fn::Join` と `Fn::GetAtt` をうまく使ってあげないといけません。


なので、下記のような書き方となります。

```
"EventSource": {
            "Type": "AWS::Lambda::EventSourceMapping",
            "Properties": {
                "BatchSize": 100,
                "Enabled": true,
                "EventSourceArn": "arn:aws:kinesis:ap-northeast-1:01234567890:stream/my-stream",
                "FunctionName": {
                    "Fn::Join": [
                        ":",
                        [
                            {
                                "Fn::GetAtt": [
                                    "MyLambda",
                                    "Arn"
                                ]
                            },
                            "DEV"
                        ]
                    ]
                },
                "StartingPosition": "TRIM_HORIZON"
            }
        }
```