|
| 1 | +--- |
| 2 | +title: Environment Variables |
| 3 | +description: Environment Variables |
| 4 | +--- |
| 5 | +Environment Variables decorator is a simple parser for environment variables that run at the start of the handler invocation. |
| 6 | + |
| 7 | +{: style="height:50%;width:20%"} |
| 8 | + |
| 9 | +## Key features |
| 10 | +* A defined [Pydantic](https://pydantic-docs.helpmanual.io/){:target="_blank" rel="noopener"} schema for all required environment variables |
| 11 | +* A decorator that parses and validates environment variables, value constraints included |
| 12 | +* Global getter for parsed & valid schema dataclass with all environment variables |
| 13 | + |
| 14 | + |
| 15 | + |
| 16 | +The best practice for handling environment variables is to validate & parse them according to a predefined schema as soon as the AWS Lambda function is triggered. |
| 17 | + |
| 18 | +In case of misconfiguration, a validation exception is raised with all the relevant exception details. |
| 19 | + |
| 20 | + |
| 21 | +## Blog Reference |
| 22 | +Read more about the importance of validating environment variables and how this utility works. Click [**HERE**](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-3-business-domain-observability){:target="_blank" rel="noopener"} |
| 23 | + |
| 24 | + |
| 25 | +## Schema Definition |
| 26 | + |
| 27 | +You need to define all your environment variables in a Pydantic schema class that extend Pydantic's BaseModel class. |
| 28 | + |
| 29 | +For example: |
| 30 | +=== "schemas/env_vars.py" |
| 31 | + |
| 32 | + ```python hl_lines="5" |
| 33 | + from typing import Literal |
| 34 | + |
| 35 | + from pydantic import BaseModel, HttpUrl, constr |
| 36 | + |
| 37 | + class MyHandlerEnvVars(BaseModel): |
| 38 | + REST_API: HttpUrl |
| 39 | + ROLE_ARN: constr(min_length=20, max_length=2048) |
| 40 | + POWERTOOLS_SERVICE_NAME: constr(min_length=1) |
| 41 | + LOG_LEVEL: Literal['DEBUG', 'INFO', 'ERROR', 'CRITICAL', 'WARNING', 'EXCEPTION'] |
| 42 | + |
| 43 | + ``` |
| 44 | + |
| 45 | +All Pydantic schemas extend Pydantic’s ‘BaseModel’ class, turning them into a dataclass. |
| 46 | + |
| 47 | +The schema defines four environment variables: ‘LOG_LEVEL,’ ‘POWERTOOLS_SERVICE_NAME,’ ‘ROLE_ARN,’ and ‘REST_API.’ |
| 48 | + |
| 49 | +This schema makes sure that: |
| 50 | + |
| 51 | +- ‘LOG_LEVEL’ is one of the strings in the Literal list. |
| 52 | +- ‘ROLE_ARN’ exists and is between 20 and 2048 characters long, as defined here. |
| 53 | +- ‘REST_API’ is a valid HTTP URL. |
| 54 | +- ‘POWERTOOLS_SERVICE_NAME’ is a non-empty string. |
| 55 | + |
| 56 | +Read [here](https://pydantic-docs.helpmanual.io/usage/models/){:target="_blank" rel="noopener"} about Pydantic Model capabilities. |
| 57 | + |
| 58 | +## Decorator Usage |
| 59 | +The decorator 'init_environment_variables' is defined under the utility folder **service.utils.env_vars_parser.py** and imported in the handler. |
| 60 | + |
| 61 | +The decorator requires a **model** parameter, which in this example is the name of the schema class we defined above. |
| 62 | + |
| 63 | +=== "handlers/my_handler.py" |
| 64 | + |
| 65 | + ```python hl_lines="11" |
| 66 | + import json |
| 67 | + from http import HTTPStatus |
| 68 | + from typing import Any, Dict |
| 69 | + |
| 70 | + from aws_lambda_powertools.utilities.typing import LambdaContext |
| 71 | + |
| 72 | + from service.handlers.schemas.env_vars import MyHandlerEnvVars |
| 73 | + from service.handlers.utils.env_vars_parser import init_environment_variables |
| 74 | + |
| 75 | + |
| 76 | + @init_environment_variables(model=MyHandlerEnvVars) |
| 77 | + def my_handler(event: Dict[str, Any], context: LambdaContext) -> Dict[str, Any]: |
| 78 | + return {'statusCode': HTTPStatus.OK, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps({'message': 'success'})} |
| 79 | + ``` |
| 80 | + |
| 81 | +## Global Getter Usage |
| 82 | +The getter function 'get_environment_variables' is defined under the utility folder **service.utils.env_vars_parser.py** and imported in the handler. |
| 83 | + |
| 84 | +The getter function returns a parsed and validated global instance of the environment variables Pydantic schema class. |
| 85 | + |
| 86 | +It can be used *anywhere* in the function code, not just the handler. |
| 87 | + |
| 88 | +=== "handlers/my_handler.py" |
| 89 | + |
| 90 | + ```python hl_lines="13" |
| 91 | + import json |
| 92 | + from http import HTTPStatus |
| 93 | + from typing import Any, Dict |
| 94 | + |
| 95 | + from aws_lambda_powertools.utilities.typing import LambdaContext |
| 96 | + |
| 97 | + from service.handlers.schemas.env_vars import MyHandlerEnvVars |
| 98 | + from service.handlers.utils.env_vars_parser import get_environment_variables, init_environment_variables |
| 99 | + |
| 100 | + |
| 101 | + @init_environment_variables(model=MyHandlerEnvVars) |
| 102 | + def my_handler(event: Dict[str, Any], context: LambdaContext) -> Dict[str, Any]: |
| 103 | + env_vars: MyHandlerEnvVars = get_environment_variables() |
| 104 | + return {'statusCode': HTTPStatus.OK, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps({'message': 'success'})} |
| 105 | + ``` |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | +## More Details |
| 110 | + |
| 111 | +Read [here](https://pydantic-docs.helpmanual.io/usage/types/){:target="_blank" rel="noopener"} about Pydantic field types. |
| 112 | + |
| 113 | +Read [here](https://pydantic-docs.helpmanual.io/usage/validators/){:target="_blank" rel="noopener"} about custom validators and advanced value constraints. |
0 commit comments