はじめに
こんにちは!ポーラ・オルビスホールディングスのITプロダクト開発チームでエンジニアをしている大野です。
私たちのチームではAPIの開発にAPIGatway + Lambda + pythonのサーバレス環境を構築しています。
ですがローカル開発環境がどうしても欲しく、Lambda pythonのローカル開発環境を作成するために色々と調査したので残そうと思います。
一応、AWSサービスのローカル環境といえばlocalstackが有名ですが、 localstackの無料版はデータの保持ができなかったりと色々使いづらいところもあり、かといってローカル開発におけるコストは抑えたいので、どうにか無料でLambdaのローカル実行環境を作成しようと思います。
私たちのチームのLambdaでは、SSMからDBの接続情報を取得して、そのパラメータを元にDBへの接続を行っています。
そのために、今回はSSMのモックにMockoonを使用してSSMから任意のパラメータを返させようと思います。
対象のコード
今回はpythonとboto3を使ったこんな感じのコードをAWS環境に繋がずにローカルだけで完結させます。
ssm = boto3.client("ssm")
names = [
"/hoge",
"/fuga",
]
ssm_response = ssm.get_parameters(
Names=names,
WithDecryption=True,
)
接続方法
Boto3.clientにはendpoint_urlというオプションパラメータが存在するので、ここにモックサーバのURLを入れましょう。
今回はローカルで Mockoon を起動するので、ローカルに向ければOKです。
ssm = boto3.client("ssm", endpoint_url="http://host.docker.internal:3000")
names = [
"/hoge",
"/fuga"
]
ssm_response = ssm.get_parameters(
Names=names,
WithDecryption=True,
)
ちなみにendpoint_urlにNoneを入れれば何も指定していないものと同義になるので、既存のソースコードを変更したくない場合は環境変数等で出し分けてあげると良いかと思います。
これを実行するとモックサーバに対してこんなPOSTリクエストが飛びます。
Request URL: /
Method: POST
Accept-encoding: identity
Amz-sdk-invocation-id: e6a365b7-d832-4ab5-8ea5-1093d3fabc13
Amz-sdk-request: attempt=1
Authorization: 省略
Content-length: 53
Content-type: application/x-amz-json-1.1
Host: host.docker.internal:3000
User-agent: Boto3/1.34.137 md/Botocore#1.34.137 ua/2.0 os/linux#6.6.65-0-virt md/arch#aarch64 lang/python#3.12.8 md/pyimpl#CPython exec-env/AWS_Lambda_python3.12 cfg/retry-mode#legacy Botocore/1.34.137
X-amz-date: 20250417T034829Z
X-amz-security-token: test
X-amz-target: AmazonSSM.GetParameters
Body: {"Names": ["/hoge", "/fuga"], "WithDecryption": true}
内容としてはパス/ に対してPOSTリクエストをしているだけのようです。
Mockoon
今回はモックサーバに Mockoon を使用します。
Mockoonはモックサーバを簡単に作れるアプリです。インストールとか使い方はきっと他にいっぱい記事あるはず…
今回のケースだとモックサーバであればなんでも良いですが、そこまで高機能である必要がないこと、チームで設定を共有できるようにしたく採用しました。
公式はこちら: https://mockoon.com/
Mockoon のレスポンスを定義しましょう。
今回はSSMの代わりとして使うので Mockoon のレスポンスの定義はこんな感じで対応しました。
パス: /
レスポンスボディ:
{
"Parameters": [
{
"Name": "/hoge",
"Type": "string",
"Value": "hogehoge",
"Version": {{faker 'number.int' max=99999}},
"Selector": "/hoge",
"SourceResult": "",
"LastModifiedDate": "2025/02/18",
"ARN": "",
"DataType": ""
},
{
"Name": "/fuga",
"Type": "string",
"Value": "fugafuga",
"Version": {{faker 'number.int' max=99999}},
"Selector": "/fuga",
"SourceResult": "",
"LastModifiedDate": "2025/02/18",
"ARN": "",
"DataType": ""
}]
こんな感じ。
Mockoonはヘッダ等によっても出しわけできると思うのですが、今回は特に分岐等不要なので一旦こんな感じで定義してます。
実行
前述したコードを実行してみます。
ssm = boto3.client("ssm", endpoint_url="http://host.docker.internal:3000")
names = [
"/hoge",
"/fuga",
]
ssm_response = ssm.get_parameters(
Names=names,
WithDecryption=True,
)
print(ssm_response)
{'Parameters': [{'Name': '/hoge', 'Type': 'string', 'Value': 'hogehoge', 'Version': 55833, 'Selector': '/hoge', 'SourceResult': '', 'LastModifiedDate': datetime.datetime(2025, 2, 18, 0, 0), 'ARN': '', 'DataType': ''}, {'Name': '/fuga', 'Type': 'string', 'Value': 'fugafuga', 'Version': 54236, 'Selector': '/fuga', 'SourceResult': '', 'LastModifiedDate': datetime.datetime(2025, 2, 18, 0, 0), 'ARN': '', 'DataType': ''}], 'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'application/json; charset=utf-8', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS', 'access-control-allow-headers': 'Content-Type, Origin, Accept, Authorization, Content-Length, X-Requested-With', 'content-length': '552', 'date': 'Thu, 17 Apr 2025 06:01:48 GMT', 'connection': 'keep-alive', 'keep-alive': 'timeout=5'}, 'RetryAttempts': 0}}
取れました!
あとは後続のパラメータ取得処理に合わせてレスポンスを修正すればOKかと思います。
まとめ
今回はmockoonを使ってSSMのレスポンスをモックにしてみました。
Mockoonは難しいこと考えなくてもモックサーバが簡単に作れて非常に偉いですね!これ以外の用途でも全然使えそう。
あと、調べるとbotoは全体的にendpoint_urlでの接続先がきちんと用意されているみたいなので、同じ形でssm以外もmockできそうでローカル開発が捗りそうです!
これをもとに、次はDBへの接続を行ってみようと思います。