-
Notifications
You must be signed in to change notification settings - Fork 421
/
Copy pathappconfig.py
138 lines (123 loc) · 5.05 KB
/
appconfig.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""Advanced feature flags utility
!!! abstract "Usage Documentation"
[`Feature Flags`](../../utilities/feature_flags.md)
"""
from __future__ import annotations
import logging
import traceback
from typing import TYPE_CHECKING, Any, cast
from botocore.config import Config
from aws_lambda_powertools.utilities import jmespath_utils
from aws_lambda_powertools.utilities.feature_flags.base import StoreProvider
from aws_lambda_powertools.utilities.feature_flags.exceptions import ConfigurationStoreError, StoreClientError
from aws_lambda_powertools.utilities.parameters import (
AppConfigProvider,
GetParameterError,
TransformParameterError,
)
if TYPE_CHECKING:
import boto3
from botocore.config import Config
from mypy_boto3_appconfigdata import AppConfigDataClient
from aws_lambda_powertools.logging import Logger
class AppConfigStore(StoreProvider):
def __init__(
self,
environment: str,
application: str,
name: str,
max_age: int = 5,
sdk_config: Config | None = None,
envelope: str | None = "",
jmespath_options: dict | None = None,
logger: logging.Logger | Logger | None = None,
boto_config: Config | None = None,
boto3_session: boto3.session.Session | None = None,
boto3_client: AppConfigDataClient | None = None,
):
"""This class fetches JSON schemas from AWS AppConfig
Parameters
----------
environment: str
Appconfig environment, e.g. 'dev/test' etc.
application: str
AppConfig application name, e.g. 'powertools'
name: str
AppConfig configuration name e.g. `my_conf`
max_age: int
cache expiration time in seconds, or how often to call AppConfig to fetch latest configuration
sdk_config: Config | None
Botocore Config object to pass during client initialization
envelope : str | None
JMESPath expression to pluck feature flags data from config
jmespath_options : dict | None
Alternative JMESPath options to be included when filtering expr
logger: A logging object
Used to log messages. If None is supplied, one will be created.
boto_config: botocore.config.Config, optional
Botocore configuration to pass during client initialization
boto3_session : boto3.Session, optional
Boto3 session to use for AWS API communication
boto3_client : AppConfigDataClient, optional
Boto3 AppConfigDataClient Client to use, boto3_session and boto_config will be ignored if both are provided
"""
super().__init__()
self.logger = logger or logging.getLogger(__name__)
self.environment = environment
self.application = application
self.name = name
self.cache_seconds = max_age
self.config = sdk_config or boto_config
self.envelope = envelope
self.jmespath_options = jmespath_options
self._conf_store = AppConfigProvider(
environment=environment,
application=application,
config=sdk_config or boto_config,
boto3_client=boto3_client,
boto3_session=boto3_session,
)
@property
def get_raw_configuration(self) -> dict[str, Any]:
"""Fetch feature schema configuration from AWS AppConfig"""
try:
# parse result conf as JSON, keep in cache for self.max_age seconds
self.logger.debug(
"Fetching configuration from the store",
extra={"param_name": self.name, "max_age": self.cache_seconds},
)
return cast(
dict,
self._conf_store.get(
name=self.name,
transform="json",
max_age=self.cache_seconds,
),
)
except (GetParameterError, TransformParameterError) as exc:
err_msg = traceback.format_exc()
if "AccessDenied" in err_msg:
raise StoreClientError(err_msg) from exc
raise ConfigurationStoreError("Unable to get AWS AppConfig configuration file") from exc
def get_configuration(self) -> dict[str, Any]:
"""Fetch feature schema configuration from AWS AppConfig
If envelope is set, it'll extract and return feature flags from configuration,
otherwise it'll return the entire configuration fetched from AWS AppConfig.
Raises
------
ConfigurationStoreError
Any validation error or AppConfig error that can occur
Returns
-------
dict[str, Any]
parsed JSON dictionary
"""
config = self.get_raw_configuration
if self.envelope:
self.logger.debug("Envelope enabled; extracting data from config", extra={"envelope": self.envelope})
config = jmespath_utils.query(
data=config,
envelope=self.envelope,
jmespath_options=self.jmespath_options,
)
return config