0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS SAMでFn::ForEachを使う

0
Posted at

はじめに

AWS SAMにて、AWS CloudFormation Language Extensionsがサポートされるようになったとのことです。

試しに、Lambdaを複数作ってみました。

概要

  • SAM CLI v1.16移行で利用可能
  • 有効化するには、Transformセクションへの定義と、実行時にコマンドライン引数等での宣言が必要
  • やってみた内容は以下
    • ループしてLambdaを3つ作成
    • イテレータで記載内容を変更
    • 引数を利用
    • 一つのループの中で、2つのリソースを作成

参考

やってみた

今回はCloudShell上で行います。

SAM CLI バージョン確認

SAM CLI v1.16未満の場合はバージョンを上げます。

~ $ sam --version
SAM CLI, version 1.156.0

~ $ pip install --upgrade aws-sam-cli

~ $ sam --version
SAM CLI, version 1.161.1

CloudShellの場合、再接続するたびにバージョンが元に戻ります。都度バージョンを挙げてください。

サンプル1:Lambda関数3つを作成

以前の記事を参考にします。

フォルダ構造は以下となります。

sample-sam
│  template.yaml
│
└─function
        function.py
        requirements.txt

3つのファイルは以下になります。

function/function.py
def lambda_handler(event, context):

    print('sample function')
    return {
        'statusCode': 200,
        'body': 'Hello from Lambda!'
    }

function/requirements.txtは0バイトです。

テンプレートでFn::ForEachを使って、3つのLambda関数を作成します。

template.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform:
  - AWS::LanguageExtensions
  - AWS::Serverless-2016-10-31

Resources:
    FunctionRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: "for-lambdafunction-loopsamtest"
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    -   Effect: Allow
                        Principal:
                            Service:
                                - lambda.amazonaws.com
                        Action:
                            - 'sts:AssumeRole'
            Path: '/service-role/'
            ManagedPolicyArns:
                - 'arn:aws:iam::aws:policy/AWSLambdaExecute'

    Fn::ForEach::Functions:
        - Name
        - [Prod, Test, Dev]
        - ${Name}Func:
            Type: AWS::Serverless::Function
            Properties:
                Role: !GetAtt FunctionRole.Arn
                CodeUri: function/
                Handler: function.lambda_handler
                Runtime: python3.13

実行コマンドは以下になります。今回はコマンドにフラグ--language-extensionsを付与します。

sam build --language-extensions
sam validate --language-extensions
sam deploy --guided --language-extensions --capabilities CAPABILITY_NAMED_IAM

以下のような関数が作られました。

sample-sam $ aws lambda list-functions --query "Functions[?contains(FunctionName, 'sam-app-')].[FunctionName, Runtime]" --output table
-------------------------------------------------
|                 ListFunctions                 |
+--------------------------------+--------------+
|  sam-app-DevFunc-EFeQuMQFSEsK  |  python3.13  |
|  sam-app-ProdFunc-blxPm8SQ5bej |  python3.13  |
|  sam-app-TestFunc-5x8M47kYlATi |  python3.13  |
+--------------------------------+--------------+

消すにはsam deleteになります。

サンプル2:CodeUriをループ

CodeUriにイテレータをいれ、環境ごとにコードを分けてみます。それに合わせてディレクトリ構造も変えます。

sample-sam
│  template.yaml
│
└─function
    │  function.py
    │  requirements.txt
    │
    ├─dev
    │      function.py
    │      requirements.txt
    │
    ├─prod
    │      function.py
    │      requirements.txt
    │
    └─test
            function.py
            requirements.txt
template.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform:
  - AWS::LanguageExtensions
  - AWS::Serverless-2016-10-31

Resources:
    FunctionRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: "for-lambdafunction-loopsamtest"
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    -   Effect: Allow
                        Principal:
                            Service:
                                - lambda.amazonaws.com
                        Action:
                            - 'sts:AssumeRole'
            Path: '/service-role/'
            ManagedPolicyArns:
                - 'arn:aws:iam::aws:policy/AWSLambdaExecute'

    Fn::ForEach::Functions:
        - Stage
        - [Prod, Test, Dev]
        - ${Stage}Func:
            Type: AWS::Serverless::Function
            Properties:
                Role: !GetAtt FunctionRole.Arn
                CodeUri: ./function/${Stage}
                Handler: function.lambda_handler
                Runtime: python3.13

サンプル3:引数を使う

カンマ区切りの文字列を指定して、ループを指定してみます。合わせて関数名を定義し、Outputセクションを加えてみます。

template.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform:
  - AWS::LanguageExtensions
  - AWS::Serverless-2016-10-31

Parameters:
  StageNames:
    Type: CommaDelimitedList
    Default: "Prod, Test, Dev"

Resources:
    FunctionRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: "for-lambdafunction-loopsamtest"
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    -   Effect: Allow
                        Principal:
                            Service:
                                - lambda.amazonaws.com
                        Action:
                            - 'sts:AssumeRole'
            Path: '/service-role/'
            ManagedPolicyArns:
                - 'arn:aws:iam::aws:policy/AWSLambdaExecute'

    Fn::ForEach::Functions:
        - Stage
        - !Ref StageNames
        - ${Stage}Func:
            Type: AWS::Serverless::Function
            Properties:
                FunctionName: !Sub Sample-${Stage}
                Role: !GetAtt FunctionRole.Arn
                CodeUri: ./function/${Stage}
                Handler: function.lambda_handler
                Runtime: python3.13

Outputs:
  Fn::ForEach::FunctionArns:
    - Stage
    - !Ref StageNames
    - ${Stage}FunctionArn:
        Value: !GetAtt
          - !Sub "${Stage}Func"
          - Arn

結果が想定通りになっていることを確認します。

sample-sam $ aws lambda list-functions --query "Functions[?contains(FunctionName, 'Sample-')].[FunctionName, Runtime]" --output table
-------------------------------
|        ListFunctions        |
+--------------+--------------+
|  Sample-Test |  python3.13  |
|  Sample-Dev  |  python3.13  |
|  Sample-Prod |  python3.13  |
+--------------+--------------+

sample-sam $ aws cloudformation describe-stacks   --stack-name sam-app   --query "Stacks[0].Outputs[*].[OutputKey, OutputValue, Description]"   --output table
------------------------------------------------------------------------------------------------
|                                        DescribeStacks                                        |
+-----------------+-------------------------------------------------------------------+--------+
|  DevFunctionArn |  arn:aws:lambda:ap-northeast-1:123456789012:function:Sample-Dev   |  None  |
|  ProdFunctionArn|  arn:aws:lambda:ap-northeast-1:123456789012:function:Sample-Prod  |  None  |
|  TestFunctionArn|  arn:aws:lambda:ap-northeast-1:123456789012:function:Sample-Test  |  None  |
+-----------------+-------------------------------------------------------------------+--------+

サンプル4:ループの中でロググループも作成

いつもLambda関数を作成する際はロググループも作成していますので、同じループの中でロググループも作成してみます。

template.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform:
  - AWS::LanguageExtensions
  - AWS::Serverless-2016-10-31

Parameters:
  StageNames:
    Type: CommaDelimitedList
    Default: "Prod, Test, Dev"

Resources:
    FunctionRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: "for-lambdafunction-loopsamtest"
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    -   Effect: Allow
                        Principal:
                            Service:
                                - lambda.amazonaws.com
                        Action:
                            - 'sts:AssumeRole'
            Path: '/service-role/'
            ManagedPolicyArns:
                - 'arn:aws:iam::aws:policy/AWSLambdaExecute'

    Fn::ForEach::Functions:
        - Stage
        - !Ref StageNames
        - ${Stage}Func:
            Type: AWS::Serverless::Function
            Properties:
                FunctionName: !Sub Sample-${Stage}
                Role: !GetAtt FunctionRole.Arn
                CodeUri: ./function/${Stage}
                Handler: function.lambda_handler
                Runtime: python3.13

          ${Stage}FuncLogGroup:
            Type: AWS::Logs::LogGroup
            Properties:
                LogGroupName: !Sub /aws/lambda/Sample-${Stage}
            RetentionInDays: 3653

Outputs:
  Fn::ForEach::FunctionArns:
    - Stage
    - !Ref StageNames
    - ${Stage}FunctionArn:
        Value: !GetAtt
          - !Sub "${Stage}Func"
          - Arn

作成されていることを確認してみます。

sample-sam $ aws logs describe-log-groups   --log-group-name-prefix "/aws/lambda/Sample"   --query "logGroups[*].[logGroupName]"   --output table
-----------------------------
|     DescribeLogGroups     |
+---------------------------+
|  /aws/lambda/Sample-Dev   |
|  /aws/lambda/Sample-Prod  |
|  /aws/lambda/Sample-Test  |
+---------------------------+

おわりに

今回はAWS SAMで使えるようになったCFnの拡張機能を試してみました。
SAMはLambda関数を作るのに便利なので、この機能が使えるようになり、さらに利便性が向上したと感じました。

この記事がどなたかのお役に立てれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?