![](/img/trans.png)
[英]aws-sam-cli Python requirements.txt missing from deployed Lambda when custom template.yaml
[英]Running pytest in AWS SAM doesn't use env vars in template.yaml
我正在用 pytest 測試我的 lambda。 我的 lambda GetDevicesFunction使用來自utils_layer/python
目錄中的共享模塊aurora的方法連接到數據庫。 數據庫連接的參數來自template.yaml 。 當我運行sam build && sam local invoke
時一切正常,但是當我運行pytest時,似乎沒有從我的模板中提取環境變量。 這是預期的還是我錯過了什么?
這是我的項目...
# project structure
├── __init__.py
├── get_devices
│ ├── __init__.py
│ ├── app.py
│ ├── requirements.txt
├── template.yaml
├── tests
│ ├── __init__.py
│ └── unit
│ ├── __init__.py
│ └── test_handler.py
└── utils_layer
├── __init__.py
├── python
│ ├── __init__.py
│ ├── aurora.py
│ ├── pg8000
# template.yaml
Globals:
Function:
Runtime: python3.8
MemorySize: 256
Timeout: 60
Layers:
- !Ref UtilsLayer
Environment:
Variables:
DATABASE_NAME: !FindInMap [ResourcesName, !Ref MyEnvironment, databaseName]
DATABASE_HOST: !FindInMap [ResourcesName, !Ref MyEnvironment, databaseHost]
DATABASE_PORT: !Ref DatabasePort
DATABASE_USER: !FindInMap [ResourcesName, !Ref MyEnvironment, databaseUser]
DATABASE_PASSWORD: !FindInMap [ResourcesName, !Ref MyEnvironment, databasePassword]
ENVIRONMENT: !Ref MyEnvironment
Mappings:
ResourcesName:
dev:
databaseHost: <db_host>
databaseName: <db_name>
databaseUser: <db_user>
databasePassword: <db_password>
Parameters:
MyEnvironment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
Resources:
GetDevicesFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: get_devices/
Handler: app.lambda_handler
Events:
GetDevicesApiEvent:
Type: Api
Properties:
Path: /devices
Method: GET
UtilsLayer:
Type: AWS::Serverless::LayerVersion
Properties:
Description: Utils layer
ContentUri: utils_layer/
CompatibleRuntimes:
- python3.8
RetentionPolicy: Delete
# aurora.py
import pg8000
db_host = os.environ.get('DATABASE_HOST')
db_port = os.environ.get('DATABASE_PORT')
db_name = os.environ.get('DATABASE_NAME')
db_user = os.environ.get('DATABASE_USER')
db_password = os.environ.get('DATABASE_PASSWORD')
def make_conn():
conn = None
try:
conn = pg8000.connect(
database=db_name,
user=db_user,
password=db_password,
host=db_host
)
except Exception as e:
print(f'Connection error: {e}')
return conn
# test_handler.py
import pytest
from get_devices import app
def test_lambda_handler(apigw_event, mocker):
ret = app.lambda_handler(apigw_event, "")
data = ret['body']['data']
assert ret["statusCode"] == 200
assert len(data) > 0
任何有關如何從我的模板中提取環境變量的建議都將不勝感激。
我在conftest.py
中做了這樣的事情:
import os
import yaml
# Read contents from template file. put all parameters out into envs
try:
with open('template.yaml', 'rt') as handle:
# Add constructor to handle !'s
def any_constructor(loader, tag_suffix, node):
if isinstance(node, yaml.MappingNode):
return loader.construct_mapping(node)
if isinstance(node, yaml.SequenceNode):
return loader.construct_sequence(node)
return loader.construct_scalar(node)
# Add constructors
yaml.add_multi_constructor('', any_constructor, Loader=yaml.SafeLoader)
# Load yaml
template = yaml.safe_load(handle)
# Add to env
for param in template['Parameters'].items():
key = param[0]
value = param[1]['Default']
os.environ[key] = value
except yaml.YAMLError as e:
raise ValueError(e)
您可以使用相同的 env.json 來在本地調用 function 。 在這種情況下,我使用一個專門用於測試的名為test.env.json
(從.gitignore
的源代碼控制中排除)與環境參數,格式如下:
{
"GetDevicesFunction": {
"DATABASE_NAME": "dbname",
"DATABASE_HOST": "dbhost",
"DATABASE_PORT": "5432",
"DATABASE_USER": "dbuser",
"DATABASE_PASSWORD": "dbpassword",
"ENVIRONMENT": "?"
}
}
並使用夾具來加載它們:
from . import get_devices
import os
import json
import pytest
ENVIRONMENT_PATH = os.path.join(
os.path.dirname(os.path.abspath(get_devices.__file__)),
"../test.env.json"
)
@pytest.fixture()
def test_environ():
"""Load environment variables to mock"""
data = {}
with open(ENVIRONMENT_PATH) as json_file:
data = json.load(json_file)
for (k, v) in data["GetDevicesFunction"].items():
os.environ[k] = str(v)
return data
def test_lambda_handler(apigw_event, mocker, test_environ):
from get_devices import app
ret = app.lambda_handler(apigw_event, "")
data = ret['body']['data']
assert ret["statusCode"] == 200
assert len(data) > 0
如果您使用了sam build --use-container
,並且您的數據庫是在綁定到默認網絡的 docker 容器中本地啟動的,您還可以使用test.env.json
文件在本地調用 ZC1C425268E17385D14ZA5074F:
sam local invoke GetDevicesFunction --env-vars test.env.json --docker-network docker_default --debug
使用sam build
你可以:
sam local invoke GetDevicesFunction --env-vars test.env.json --debug
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.