[アップデート]AWS SAM CLIでAWS環境上のAmazon SQS及びAmazon Kinesis Data Streamsにメッセージが送信できるようになりました

2023.11.16

初めに

昨日AWS SAM CLIのv1.102.0がリリースされました。

今回のアップデートでremote invokeコマンドがさらに拡張され、AWS SAM CLIで実際のAWS環境上(リモート上)のAmazon SQS及びAmazon Kinesis Data Streamsに対してメッセージがが送信できるようになりました。

これにより実際の環境上でメッセージングサービスを統合したより統合的なテストの実行までSAM CLIで行えるようになります。リモート実行のみでローカルモックは未追加となりますのでご注意ください。

なお本機能と直接関係はありませんが同バージョンにてStep Functionsのリモート実行の機能も追加されています。
そちらの紹介もしておりますのでご興味のある方はご一読いただければ幸いです。

試してみる

テンプレート

HelloWorldのテンプレートを拡張してSQS及びKinesis Data StreamsをトリガーにLambda関数が起動するようにしておきます。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Timeout: 10
    MemorySize: 128

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.11
      Architectures:
        - x86_64
      Events:
        MySQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt MyQueue.Arn
            BatchSize: 10
        Stream:
          Type: Kinesis
          Properties:
            Stream: !GetAtt MyStream.Arn
            BatchSize: 100
            StartingPosition: LATEST
  MyStream:
    Type: AWS::Kinesis::Stream
    Properties:
      ShardCount: 1
  MyQueue:
    Type: AWS::SQS::Queue

Pythonのコードもeventをログに出力するように変更しておきます。

import json
def lambda_handler(event, context):
    print(event)
    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": event,
        }),
    }

メッセージを送信

Amazon Kinesis Data StreamおよびAmazon SQSにメッセージを送信するコマンドはLambda関数の実行と同じでsam remote invokeで実行のために特殊なオプションは不要です。
共通オプションですがリソース名の指定、送信するイベント(送信するメッセージ)の指定は必要です。
(一応イベントの指定は任意で未指定の場合は空のメッセージ({})が送信されるようです)

各コマンドの出力自体はPut処理のAPIのレスポンス相当の値となります。

# Kinesisに対して送信
$sam remote invoke MyStream -e '{"message": "Im from Kinesis!"}'
Putting record to Kinesis data stream MyStream
{
  "ShardId": "shardId-000000000000",
  "SequenceNumber": "49646473482378681820749604207903098696795963466314678274"
}%
# SQSに対して送信
$ sam remote invoke MyQueue -e '{"message": "Im from SQS!"}'
Sending message to SQS queue MyQueue
{
  "MD5OfMessageBody": "3fdb4f19e276fe58f703a3bcabdd86ff",
  "MessageId": "53c1c604-9878-40e7-87ba-62e399c73082"
}

Lambda関数の実行結果はCloudWatch Logs上に確認しに行きます。

print(event)の結果はそれぞれ以下のようになっていました(見やすいように整形しています)。

MyStream結果

{
  'Records': [
    {
      'kinesis': {
        'kinesisSchemaVersion': '1.0',
        'partitionKey': '03e7f39b-06f7-43da-8ae4-0f436e83cf86',
        'sequenceNumber': '49646473482378681820749604207903098696795963466314678274',
        'data': 'eyJtZXNzYWdlIjogIkltIGZyb20gS2luZXNpcyEifQ==',
        'approximateArrivalTimestamp': 1700101391.108
      },
      'eventSource': 'aws:kinesis',
      'eventVersion': '1.0',
      'eventID': 'shardId-000000000000:49646473482378681820749604207903098696795963466314678274',
      'eventName': 'aws:kinesis:record',
      'invokeIdentityArn': 'arn:aws:iam::xxxxx:role/sam-app-queue-HelloWorldFunctionRole-xxxxx',
      'awsRegion': 'ap-northeast-1',
      'eventSourceARN': 'arn:aws:kinesis:ap-northeast-1:xxxxx:stream/sam-app-queue-MyStream-xxxxx'
    }
  ]
}

MyQueue結果

{
  'Records': [
    {
      'messageId': '53c1c604-9878-40e7-87ba-62e399c73082',
      'receiptHandle': 'AQEBiWUTKRPyB55eFWXHz+dpksq6KEMs2vlE3bbMBpaI/1zSZ2CSKRjdRYoz4sgATLN30GoQlTlhqUJ3q7DWFkHLjWlPOC2TpTMP7G/zmQXi3hpEdMJDFk+ZQoq8/PQP/Hf7EjRuGSFpX3++QTvwDOG5sPufv9aWAPpDePSiLBZY12U4LkbTQGk2hXhLoz+J0uLMEjr6N02sci+/RW7biwAreA6x2iT8mT+rr2KvyqlrUJBrit77gmaB07P5M2QKyiH4HdxiJ29xCKCRdqsnPhQD7AGldrYa4BfzTKp6+5Hp3Dwvl6svZaXWWCbg8F5xngiAbEl7IXD5e4ulN1CpgBQmZpc5zVjFka7c6oSNcqHnRzt1F/L37QGu6Wr+T8xqmefawsQ5VbBVj/f5zLF06BPAbz9grpi44pydjKEyYQw9A6n+CyUQbvtYOOmPfv0CuyOj',
      'body': '{"message": "Im from SQS!"}',
      'attributes': {
        'ApproximateReceiveCount': '1',
        'SentTimestamp': '1700101395692',
        'SenderId': 'AIDAYGB7QZAX2LERES3Y5',
        'ApproximateFirstReceiveTimestamp': '1700101395698'
      },
      'messageAttributes': {},
      'md5OfBody': '3fdb4f19e276fe58f703a3bcabdd86ff',
      'eventSource': 'aws:sqs',
      'eventSourceARN': 'arn:aws:sqs:ap-northeast-1:xxxxxx:sam-app-queue-MyQueue-xxxxx',
      'awsRegion': 'ap-northeast-1'
    }
  ]
}

実行可能なリソースが増えてこれまでLambda関数+キューのみのサービスで逐一指定が必要になり都度指定が冗長になるのでは?と思ったのですが、リソース名が未指定でテンプレート上にLambda関数が1つの場合は他にSQS等remote invokeで実行可能なリソースが含まれていても暗黙的にLambda関数が利用されるという点は変わりないようです。

% sam remote invoke
Invoking Lambda Function HelloWorldFunction
START RequestId: 0229bf30-3b24-458c-9a59-14a6c30e32ab Version: $LATEST
END RequestId: 0229bf30-3b24-458c-9a59-14a6c30e32ab
REPORT RequestId: 0229bf30-3b24-458c-9a59-14a6c30e32ab	Duration: 1.71 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 40 MB
{"statusCode": 200, "body": "{\"message\": {}}"}%

終わりに

今回のアップデートで実際の環境のメッセージングサービスに対してメッセージが直接送信できるようになり、より統合的なテストやリカバリ対応といったこともSAMでできるようになりました。

先のStep Functionsも含めインターフェースをSAM CLIコマンド一つ、しかもAWS CLIのようにリソース毎に異なるコマンドを意識して指定する必要がなくsam remote invoke {{リソース名}}共通で自動判別してリソースに応じた処理をしてくれるため操作もしやすくかなり良いのでは?というのが個人的な印象です。

実行時にリソース種別が不要ということは誤った指定をしてしまう可能性は高まりますので、テンプレートのリソース名でしっかりサービス種別が判別できるようにはしておきましょう。

余談

実はこちらの機能も先に執筆したStep Functionsと同様に以前から機能自体は実装されてはいたもののCLIのインターフェース側に開放されていない機能でした。
(コメントや実装を見る限り統合テストはあるがユニットテストがなかった為控えてたようです)

以降で修正が入っている部分もあるかと思いますが大枠の実装を確認する場合はv1.99.0のリリースもご参照ください。