Python 模拟 AWS SSM

Python mock AWS SSM

我已经编写了一个代码来为我获取 SSM 参数

import boto3
    
client = boto3.client('ssm')
    
def lambda_handler(event, context):
    return client.get_parameter(Name=event["param"], WithDecryption=True)

if __name__ == '__main__':
    print(lambda_handler({"param": "/mypath/password"}, ""))

但是,我无法为其编写测试用例 我已经尝试使用 moto 但出于某种原因,它仍然为我提供了 SSM 商店的实际值

import os

import boto3
from moto import mock_ssm
import pytest

from handler import lambda_handler

@pytest.fixture
def aws_credentials():
    os.environ["AWS_ACCESS_KEY_ID"] = "testing"
    os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
    os.environ["AWS_SECURITY_TOKEN"] = "testing"
    os.environ["AWS_SESSION_TOKEN"] = "testing"

@mock_ssm
def test_ssm():
    ssm = boto3.client('ssm')
    ssm.put_parameter(
        Name="/mypath/password",
        Description="A test parameter",
        Value="this is it!",
        Type="SecureString"
    )
    resp = lambda_handler({"param": "/mypath/password"}, "")
    assert resp["Parameter"]["Value"] == "this is it!"

我是否遗漏了一些无意中听到的东西,我应该怎么做才能让它发挥作用,或者在 python.

中是否有其他模拟 SSM 的方法

当您通过 @mock_ssm 修补 ssm 时,您已经将 handler.py 中的变量 handler.client 实例化为 boto3 客户端的真实实例,因此这不是补丁版本。

解决方案 1:

仅在 lambda 处理程序期间初始化客户端,以便补丁在创建时已经生效。

handler.py

import boto3

# client = boto3.client('ssm')  # Remove this instantiation

def lambda_handler(event, context):
    client = boto3.client('ssm')  # Move it here
    return client.get_parameter(Name=event["param"], WithDecryption=True)

if __name__ == '__main__':
    print(lambda_handler({"param": "/mypath/password"}, ""))

解决方案 2:

只有 import/execute handler.py 补丁生效后的文件。

test_handler.py

...
# from handler import lambda_handler  # Remove this import
...
@mock_ssm
def test_ssm():
    from handler import lambda_handler  # Move it here
    ...
...

解决方案 3

补丁生效后重新加载handler.py。

...
@mock_ssm
def test_ssm():
    from importlib import reload
    import sys
    reload(sys.modules['handler'])
    ...
...

输出

$ pytest -q -rP
============================================================================================ PASSES ============================================================================================
1 passed in 1.35s