Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.8k views
in Technique[技术] by (71.8m points)

aws lambda - Why local AWS API calls fail with SSL validation

There are a lot of resources out there for using pytest, Moto, and botocore Stubber to write unit tests.

I believe I have set things up correctly, but I keep getting SSL validation errors, which mean that my AWS API calls are not being prevented from trying to contact the actual AWS service.

Here is my project structure:

- my_lambda_name
    -> lambda_function.py
- test
    -> test_my_lambda_name.py
    -> conftest.py
- layers
    -> shared_layer
        -> python
           -> clients.py

inside the clients.py file:

import boto3
ssm_clt = boto3.client('ssm', region_name='us-east-2')

here are the contents of the conftest.py file:

import pytest
from botocore.stub import Stubber, ANY
import clients

@pytest.fixture(autouse=True)
def ssm_stub():
    with Stubber(clients.ssm_clt) as stubber:
        yield stubber

inside of my lambda_function.py:

import setup

# get parameter dict from ssm
param_dict = setup.get_parameter_dict()

inside of setup.py file:

import json
from clients import ssm_clt

def get_parameter_dict():
    param_dict = {}
    ssm_resp = ssm_clt.get_parameters_by_path(
        Path=f'/{os.environ["teamName"]}/{os.environ["environment"]}/string_here',
        Recursive=True
    )

    for parameter in ssm_resp["Parameters"]:
        param_dict.update(json.loads(parameter["Value"]))

    log.log_function_results(func_frame_obj, "success")
    return param_dict

and finally, here is the test I'm trying to run inside of test_my_lambda_name.py: import pytest import os
from my_lambda_name import lambda_function

good_event_input = {"my_key": "my_value"}

def test_lambda_handler(ssm_stub):
    ssm_stub.add_response(
        'get_parameters_by_path',
        expected_params={'Path': 'my/path/to/param', 'Recursive': 'True'},
        service_response={
            'Parameters': [
                {
                    'Name': 'my/path/to/param/here',
                    'Type': 'String',
                    'Value': 'my string value',
                },
            ],
        },
    )

    result = lambda_function.lambda_handler(good_event_input, 'my_string')

    assert result is None

When I run pytest, it seems to find the correct lambda python file to run and does indeed call get_parameter_dict() because I see it in the logs, but then it fails with this error:

botocore.exceptions.SSLError: SSL validation failed for https://ssm.us-east-2.amazonaws.com/ [Errno 2] No such file or directory

So this makes me think that it is trying to go outside and not mock the response locally. But why?

EDIT:

So I think what is happening is when the get_parameters_by_path() is being called within lambda_function.py it not using the Stubber, but the real client. I've read a bit that I could patch this with mock?

I might have multiple AWS calls in some of my tests so I don't want to have to patch each API call, could I just do something like this?

good_event_input = {"my_key": "my_value"}

@patch('boto3.client')
def test_lambda_handler(ssm_stub):
    ssm_stub.add_response(
        'get_parameters_by_path',
        expected_params={'Path': 'my/path/to/param', 'Recursive': 'True'},
        service_response={
            'Parameters': [
                {
                    'Name': 'my/path/to/param/here',
                    'Type': 'String',
                    'Value': 'my string value',
                },
            ],
        },
    )

    result = lambda_function.lambda_handler(good_event_input, 'my_string')

    assert result is None

Is it possible to patch all boto3 clients created that are used in one test?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神解答

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...