サービス開発部兼ドラクエ部のくればやしです。
青柳総本家さんのスライムまんじゅうが評判でオンラインショップで買おうとしたのですが、毎日1分程度で売り切れてしまってなかなか買えませんでした。 が!週末になんと注文することができました。到着が楽しみです😀
はじめに
AWS LambdaのLambda関数のCloudFormationのリソースは AWS::Lambda::Function ですが、AWS SAMでLambda関数をデプロイする場合は基本的に AWS::Serverless::Function リソースとしてデプロイすると思います。
AWS::Serverless::Function を用いることで、Lambda関数に紐づくイベントソースやIAMロールをまとめてその中に定義出来ることに加え、Lambdaのソースコードをローカルパスの指定でデプロイできたりと、記述と運用が非常に簡単になるメリットがあります。
既存のAWSリソースをCloudFormation(SAM)で管理する場合、大きく以下の2つの方法が選択肢となります。
- SAMでデプロイし直す
- 既存のリソースをSAMにインポートする
どちらを採用するかはプロジェクトの要件次第だと思いますが、本記事では「2. 既存のリソースをSAMにインポートする」が採用された場合に、既存のLambda関数をAWS::Serverless::Function としてインポートする方法を解説します。
インポートの方法
要点
- マネジメントコンソールではなく、AWS CLIからインポートする
- 既存リソースと論理IDとの紐づけのファイルには
AWS::Lambda::Functionを記載する
詳細
まず、既存のリソースに合わせた AWS::Serverless::Function のあるSAM用のテンプレートファイルを準備します。
通常の手順でインポートを進めようとする場合、マネジメントコンソールから 既存のリソースを使用(リソースをインポート) を選択することとなると思います。

ところが、そのままインポートを進めようとすると、以下のように Resource Type [AWS::Serverless::Functions] are not supported for import エラーが表示されます。

以下記事に記載されているように AWS::Serverless::関連のリソースをインポートするには AWS CLI でしかインポートしないようなので、AWS CLIでインポート作業を進めるようにします。
トランスフォームを使用するテンプレートのエラーを解決するには、AWS CloudFormation コンソールの代わりに AWS コマンドラインインターフェイス (AWS CLI) を使用してください。AWS CLI では、create-change-set CloudFormation コマンド用にインポートされたリソースを明示的に提供する必要があります。
AWS CLIの create-change-set を使うこととなりますが、実行時に既存リソースとテンプレートの論理IDとの紐づけのJSONファイルが必要なので、準備します。
例えば、以下のように AWS::Serverless::Function リソースとして準備して、コマンドを実行すると、
[ { "ResourceType": "AWS::Serverless::Function", "LogicalResourceId":"xxxxxx", "ResourceIdentifier": { "FunctionName":xxxxx" } }, { "ResourceType": "AWS::IAM::Role", "LogicalResourceId": "xxxxx", "ResourceIdentifier": { "RoleName": "xxxxx" } } ]
aws cloudformation create-change-set --stack-name xxxxx --change-set-name xxxx --change-set-type IMPORT --template-body file://xxxxxx.yaml --resources-to-import file://xxxxxxx.json --capabilities CAPABILITY_NAMED_IAM --region us-east-1
変更セットの作成には成功します、しかし、変更セットのステータスは FAILED となり、以下のエラーとなります。
ResourceTypes [AWS::Serverless::Function] are not supported for Import

これを回避するにはテンプレートファイルには AWS::Serverless::Function を定義しますが、リソースの紐づけのファイルの方は AWS::Lambda::Functions として定義しておく必要があります。
[ { "ResourceType": "AWS::Lambda::Function", "LogicalResourceId":"xxxxx", "ResourceIdentifier": { "FunctionName":"xxxx" } }, { "ResourceType": "AWS::IAM::Role", "LogicalResourceId": "xxxx", "ResourceIdentifier": { "RoleName": "xxxxx" } } ]
おわりに
今回、既存のLambda関数をAWS::Serverless::Function としてインポートする方法を解説しました。どなたかの一助になれば幸いです。
参考
紅林輝(くればやしあきら)(サービス開発部) 記事一覧
サービス開発部所属。2015年にサーバーワークスにJOIN。クラウドインテグレーション部を経て、現在はCloud Automatorの開発に従事。ドラクエ部。推しナンバーはⅤ、推しモンスターはクックルー。