aws-advanced-python-wrapper 1.1.0__tar.gz → 1.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/PKG-INFO +4 -2
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/README.md +3 -1
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/aurora_connection_tracker_plugin.py +4 -5
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/driver_dialect_codes.py +0 -1
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/driver_info.py +1 -1
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/host_list_provider.py +6 -3
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/mysql_driver_dialect.py +12 -2
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/sql_alchemy_connection_provider.py +4 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/rdsutils.py +129 -75
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/pyproject.toml +1 -1
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/CONTRIBUTING.md +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/LICENSE +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/__init__.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/aurora_initial_connection_strategy_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/aws_secrets_manager_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/connect_time_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/connection_provider.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/credentials_provider_factory.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/database_dialect.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/default_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/developer_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/driver_configuration_profiles.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/driver_dialect.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/driver_dialect_manager.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/errors.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/exception_handling.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/execute_time_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/failover_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/failover_result.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/fastest_response_strategy_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/federated_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/host_availability.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/host_monitoring_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/host_selector.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/hostinfo.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/iam_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/okta_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/pep249.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/pg_driver_dialect.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/plugin_service.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/read_write_splitting_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/reader_failover_handler.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/resources/aws_advanced_python_wrapper_messages.properties +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/sqlalchemy_driver_dialect.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/stale_dns_plugin.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/states/__init__.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/states/session_state.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/states/session_state_service.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/__init__.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/atomic.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/cache_map.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/concurrent.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/decorators.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/failover_mode.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/iam_utils.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/log.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/messages.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/mysql_exception_handler.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/notifications.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/pg_exception_handler.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/properties.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/rds_url_type.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/saml_utils.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/sliding_expiration_cache.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/telemetry/default_telemetry_factory.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/telemetry/null_telemetry.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/telemetry/open_telemetry.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/telemetry/telemetry.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/telemetry/xray_telemetry.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/utils/utils.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/wrapper.py +0 -0
- {aws_advanced_python_wrapper-1.1.0 → aws_advanced_python_wrapper-1.1.1}/aws_advanced_python_wrapper/writer_failover_handler.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: aws-advanced-python-wrapper
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Amazon Web Services (AWS) Advanced Python Wrapper
|
|
5
5
|
Home-page: https://github.com/awslabs/aws-advanced-python-wrapper
|
|
6
6
|
License: Apache-2.0
|
|
@@ -257,12 +257,14 @@ This `aws-advanced-python-wrapper` is being tested against the following Communi
|
|
|
257
257
|
|
|
258
258
|
| Database | Versions |
|
|
259
259
|
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
260
|
-
| MySQL | 8.
|
|
260
|
+
| MySQL | 8.4.0 |
|
|
261
261
|
| PostgreSQL | 16.2 |
|
|
262
262
|
| Aurora MySQL | - LTS version, see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.Versions.html#AuroraMySQL.Updates.LTS) for more details. <br><br> - Latest release, as shown on [this page](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.30Updates.html). |
|
|
263
263
|
| Aurora PostgreSQL | - LTS version, see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Updates.LTS.html) for more details. <br><br> - Latest release, as shown on [this page](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/AuroraPostgreSQL.Updates.html).) |
|
|
264
264
|
|
|
265
265
|
The `aws-advanced-python-wrapper` is compatible with MySQL 5.7 and MySQL 8.0 as per MySQL Connector/Python.
|
|
266
|
+
> [!WARNING]\
|
|
267
|
+
> Due to recent internal changes with the `v9.0.0` MySQL Connector/Python driver in regards to connection handling, the AWS Advanced Python Wrapper is not recommended for usage with `v9.0.0`. The AWS Advanced Python Wrapper will be updated in the future for `v9.0.0` compatibility with the community driver.
|
|
266
268
|
|
|
267
269
|
## License
|
|
268
270
|
|
|
@@ -222,12 +222,14 @@ This `aws-advanced-python-wrapper` is being tested against the following Communi
|
|
|
222
222
|
|
|
223
223
|
| Database | Versions |
|
|
224
224
|
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
225
|
-
| MySQL | 8.
|
|
225
|
+
| MySQL | 8.4.0 |
|
|
226
226
|
| PostgreSQL | 16.2 |
|
|
227
227
|
| Aurora MySQL | - LTS version, see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.Versions.html#AuroraMySQL.Updates.LTS) for more details. <br><br> - Latest release, as shown on [this page](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.30Updates.html). |
|
|
228
228
|
| Aurora PostgreSQL | - LTS version, see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Updates.LTS.html) for more details. <br><br> - Latest release, as shown on [this page](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/AuroraPostgreSQL.Updates.html).) |
|
|
229
229
|
|
|
230
230
|
The `aws-advanced-python-wrapper` is compatible with MySQL 5.7 and MySQL 8.0 as per MySQL Connector/Python.
|
|
231
|
+
> [!WARNING]\
|
|
232
|
+
> Due to recent internal changes with the `v9.0.0` MySQL Connector/Python driver in regards to connection handling, the AWS Advanced Python Wrapper is not recommended for usage with `v9.0.0`. The AWS Advanced Python Wrapper will be updated in the future for `v9.0.0` compatibility with the community driver.
|
|
231
233
|
|
|
232
234
|
## License
|
|
233
235
|
|
|
@@ -50,13 +50,12 @@ class OpenedConnectionTracker:
|
|
|
50
50
|
"""
|
|
51
51
|
|
|
52
52
|
aliases: FrozenSet[str] = host_info.as_aliases()
|
|
53
|
-
host: str = host_info.as_alias()
|
|
54
53
|
|
|
55
|
-
if self._rds_utils.is_rds_instance(host):
|
|
56
|
-
self._track_connection(
|
|
54
|
+
if self._rds_utils.is_rds_instance(host_info.host):
|
|
55
|
+
self._track_connection(host_info.as_alias(), conn)
|
|
57
56
|
return
|
|
58
57
|
|
|
59
|
-
instance_endpoint: Optional[str] = next((alias for alias in aliases if self._rds_utils.is_rds_instance(alias)),
|
|
58
|
+
instance_endpoint: Optional[str] = next((alias for alias in aliases if self._rds_utils.is_rds_instance(self._rds_utils.remove_port(alias))),
|
|
60
59
|
None)
|
|
61
60
|
if not instance_endpoint:
|
|
62
61
|
logger.debug("OpenedConnectionTracker.UnableToPopulateOpenedConnectionSet")
|
|
@@ -82,7 +81,7 @@ class OpenedConnectionTracker:
|
|
|
82
81
|
return
|
|
83
82
|
|
|
84
83
|
for instance in host:
|
|
85
|
-
if instance is not None and self._rds_utils.is_rds_instance(instance):
|
|
84
|
+
if instance is not None and self._rds_utils.is_rds_instance(self._rds_utils.remove_port(instance)):
|
|
86
85
|
instance_endpoint = instance
|
|
87
86
|
break
|
|
88
87
|
|
|
@@ -199,6 +199,8 @@ class RdsHostListProvider(DynamicHostListProvider, HostListProvider):
|
|
|
199
199
|
else:
|
|
200
200
|
self._cluster_instance_template = HostInfo(
|
|
201
201
|
host=self._rds_utils.get_rds_instance_host_pattern(self._initial_host_info.host),
|
|
202
|
+
host_id=self._initial_host_info.host_id,
|
|
203
|
+
port=self._initial_host_info.port,
|
|
202
204
|
host_availability_strategy=host_availability_strategy)
|
|
203
205
|
self._validate_host_pattern(self._cluster_instance_template.host)
|
|
204
206
|
|
|
@@ -216,14 +218,15 @@ class RdsHostListProvider(DynamicHostListProvider, HostListProvider):
|
|
|
216
218
|
self._cluster_id = cluster_id_suggestion.cluster_id
|
|
217
219
|
self._is_primary_cluster_id = cluster_id_suggestion.is_primary_cluster_id
|
|
218
220
|
else:
|
|
219
|
-
cluster_url = self._rds_utils.get_rds_cluster_host_url(self._initial_host_info.
|
|
221
|
+
cluster_url = self._rds_utils.get_rds_cluster_host_url(self._initial_host_info.host)
|
|
220
222
|
if cluster_url is not None:
|
|
221
|
-
self._cluster_id = cluster_url
|
|
223
|
+
self._cluster_id = f"{cluster_url}:{self._cluster_instance_template.port}" \
|
|
224
|
+
if self._cluster_instance_template.is_port_specified() else cluster_url
|
|
222
225
|
self._is_primary_cluster_id = True
|
|
223
226
|
self._is_primary_cluster_id_cache.put(self._cluster_id, True,
|
|
224
227
|
self._suggested_cluster_id_refresh_ns)
|
|
225
228
|
|
|
226
|
-
|
|
229
|
+
self._is_initialized = True
|
|
227
230
|
|
|
228
231
|
def _validate_host_pattern(self, host: str):
|
|
229
232
|
if not self._rds_utils.is_dns_pattern_valid(host):
|
|
@@ -131,8 +131,18 @@ class MySQLDriverDialect(DriverDialect):
|
|
|
131
131
|
|
|
132
132
|
if isinstance(obj, CMySQLCursor):
|
|
133
133
|
try:
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
conn = None
|
|
135
|
+
|
|
136
|
+
if hasattr(obj, '_cnx'):
|
|
137
|
+
conn = obj._cnx
|
|
138
|
+
elif hasattr(obj, '_connection'):
|
|
139
|
+
conn = obj._connection
|
|
140
|
+
if conn is None:
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
if isinstance(conn, CMySQLConnection) or isinstance(conn, MySQLConnection):
|
|
144
|
+
return conn
|
|
145
|
+
|
|
136
146
|
except ReferenceError:
|
|
137
147
|
return None
|
|
138
148
|
|
|
@@ -57,10 +57,12 @@ class SqlAlchemyPooledConnectionProvider(ConnectionProvider, CanReleaseResources
|
|
|
57
57
|
self,
|
|
58
58
|
pool_configurator: Optional[Callable] = None,
|
|
59
59
|
pool_mapping: Optional[Callable] = None,
|
|
60
|
+
accept_url_func: Optional[Callable] = None,
|
|
60
61
|
pool_expiration_check_ns: int = -1,
|
|
61
62
|
pool_cleanup_interval_ns: int = -1):
|
|
62
63
|
self._pool_configurator = pool_configurator
|
|
63
64
|
self._pool_mapping = pool_mapping
|
|
65
|
+
self._accept_url_func = accept_url_func
|
|
64
66
|
|
|
65
67
|
if pool_expiration_check_ns > -1:
|
|
66
68
|
SqlAlchemyPooledConnectionProvider._POOL_EXPIRATION_CHECK_NS = pool_expiration_check_ns
|
|
@@ -80,6 +82,8 @@ class SqlAlchemyPooledConnectionProvider(ConnectionProvider, CanReleaseResources
|
|
|
80
82
|
return self._database_pools.keys()
|
|
81
83
|
|
|
82
84
|
def accepts_host_info(self, host_info: HostInfo, props: Properties) -> bool:
|
|
85
|
+
if self._accept_url_func:
|
|
86
|
+
return self._accept_url_func(host_info, props)
|
|
83
87
|
url_type = SqlAlchemyPooledConnectionProvider._rds_utils.identify_rds_type(host_info.host)
|
|
84
88
|
return RdsUrlType.RDS_INSTANCE == url_type
|
|
85
89
|
|
|
@@ -12,8 +12,10 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
16
|
-
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from re import Match, search, sub
|
|
18
|
+
from typing import Dict, Optional
|
|
17
19
|
|
|
18
20
|
from aws_advanced_python_wrapper.utils.rds_url_type import RdsUrlType
|
|
19
21
|
|
|
@@ -58,78 +60,101 @@ class RdsUtils:
|
|
|
58
60
|
Example: test-postgres-instance-1.123456789012.rds.cn-northwest-1.amazonaws.com.cn
|
|
59
61
|
"""
|
|
60
62
|
|
|
61
|
-
AURORA_DNS_PATTERN = r"(?P<instance>.+)\." \
|
|
62
|
-
r"(?P<dns>proxy-|cluster-|cluster-ro-|cluster-custom-)?" \
|
|
63
|
+
AURORA_DNS_PATTERN = r"^(?P<instance>.+)\." \
|
|
64
|
+
r"(?P<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|limitless-)?" \
|
|
63
65
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
64
|
-
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn$
|
|
65
|
-
AURORA_INSTANCE_PATTERN = r"(?P<instance>.+)\." \
|
|
66
|
+
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn)$"
|
|
67
|
+
AURORA_INSTANCE_PATTERN = r"^(?P<instance>.+)\." \
|
|
66
68
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
67
|
-
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn$
|
|
68
|
-
AURORA_CLUSTER_PATTERN = r"(?P<instance>.+)\." \
|
|
69
|
+
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn)$"
|
|
70
|
+
AURORA_CLUSTER_PATTERN = r"^(?P<instance>.+)\." \
|
|
69
71
|
r"(?P<dns>cluster-|cluster-ro-)+" \
|
|
70
72
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
71
|
-
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn$
|
|
72
|
-
AURORA_CUSTOM_CLUSTER_PATTERN = r"(?P<instance>.+)\." \
|
|
73
|
+
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn)$"
|
|
74
|
+
AURORA_CUSTOM_CLUSTER_PATTERN = r"^(?P<instance>.+)\." \
|
|
73
75
|
r"(?P<dns>cluster-custom-)+" \
|
|
74
76
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
75
|
-
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn$
|
|
76
|
-
AURORA_PROXY_DNS_PATTERN = r"(?P<instance>.+)\." \
|
|
77
|
+
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com)(?!\.cn)$"
|
|
78
|
+
AURORA_PROXY_DNS_PATTERN = r"^(?P<instance>.+)\." \
|
|
77
79
|
r"(?P<dns>proxy-)+" \
|
|
78
80
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
79
|
-
r"(?P<region>[a-zA-Z0-9\\-]+)\.rds\.amazonaws\.com)(?!\.cn$
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
r"(?P<region>[a-zA-Z0-9\\-]+)\.rds\.amazonaws\.com)(?!\.cn)$"
|
|
82
|
+
AURORA_OLD_CHINA_DNS_PATTERN = r"^(?P<instance>.+)\." \
|
|
83
|
+
r"(?P<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|limitless-)?" \
|
|
84
|
+
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
85
|
+
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com\.cn)$"
|
|
86
|
+
AURORA_CHINA_DNS_PATTERN = r"^(?P<instance>.+)\." \
|
|
87
|
+
r"(?P<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|limitless-)?" \
|
|
82
88
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
83
|
-
r"(?P<region>[a-zA-Z0-9\-]+)\.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
r"rds\.(?P<region>[a-zA-Z0-9\-]+)\.amazonaws\.com\.cn)$"
|
|
90
|
+
AURORA_OLD_CHINA_CLUSTER_PATTERN = r"^(?P<instance>.+)\." \
|
|
91
|
+
r"(?P<dns>cluster-|cluster-ro-)+" \
|
|
92
|
+
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
93
|
+
r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com\.cn)$"
|
|
94
|
+
AURORA_CHINA_CLUSTER_PATTERN = r"^(?P<instance>.+)\." \
|
|
88
95
|
r"(?P<dns>cluster-|cluster-ro-)+" \
|
|
89
96
|
r"(?P<domain>[a-zA-Z0-9]+\." \
|
|
90
|
-
r"(?P<region>[a-zA-Z0-9\-]+)\.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
r"rds\.(?P<region>[a-zA-Z0-9\-]+)\.amazonaws\.com\.cn)$"
|
|
98
|
+
AURORA_GOV_DNS_PATTERN = r"^(?P<instance>.+)\." \
|
|
99
|
+
r"(?P<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|limitless-)?" \
|
|
100
|
+
r"(?P<domain>[a-zA-Z0-9]+\.rds\.(?P<region>[a-zA-Z0-9\-]+)" \
|
|
101
|
+
r"\.(amazonaws\.com|c2s\.ic\.gov|sc2s\.sgov\.gov))$"
|
|
102
|
+
AURORA_GOV_CLUSTER_PATTERN = r"^(?P<instance>.+)\." \
|
|
103
|
+
r"(?P<dns>cluster-|cluster-ro-)+" \
|
|
104
|
+
r"(?P<domain>[a-zA-Z0-9]+\.rds\.(?P<region>[a-zA-Z0-9\-]+)" \
|
|
105
|
+
r"\.(amazonaws\.com|c2s\.ic\.gov|sc2s\.sgov\.gov))$"
|
|
106
|
+
ELB_PATTERN = r"^(?<instance>.+)\.elb\.((?<region>[a-zA-Z0-9\-]+)\.amazonaws\.com)$"
|
|
99
107
|
|
|
100
108
|
IP_V4 = r"^(([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){1}" \
|
|
101
|
-
r"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])
|
|
102
|
-
IP_V6 = r"^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}
|
|
103
|
-
IP_V6_COMPRESSED = r"^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)::(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)
|
|
109
|
+
r"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
|
|
110
|
+
IP_V6 = r"^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}"
|
|
111
|
+
IP_V6_COMPRESSED = r"^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)::(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)"
|
|
104
112
|
|
|
105
113
|
DNS_GROUP = "dns"
|
|
106
114
|
DOMAIN_GROUP = "domain"
|
|
107
115
|
INSTANCE_GROUP = "instance"
|
|
108
116
|
REGION_GROUP = "region"
|
|
109
117
|
|
|
118
|
+
CACHE_DNS_PATTERNS: Dict[str, Match[str]] = {}
|
|
119
|
+
CACHE_PATTERNS: Dict[str, str] = {}
|
|
120
|
+
|
|
110
121
|
def is_rds_cluster_dns(self, host: str) -> bool:
|
|
111
|
-
|
|
122
|
+
dns_group = self._get_dns_group(host)
|
|
123
|
+
return dns_group is not None and dns_group.casefold() in ["cluster-", "cluster-ro-"]
|
|
112
124
|
|
|
113
125
|
def is_rds_custom_cluster_dns(self, host: str) -> bool:
|
|
114
|
-
|
|
126
|
+
dns_group = self._get_dns_group(host)
|
|
127
|
+
return dns_group is not None and dns_group.casefold() == "cluster-custom-"
|
|
115
128
|
|
|
116
129
|
def is_rds_dns(self, host: str) -> bool:
|
|
117
|
-
|
|
130
|
+
if not host or not host.strip():
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
pattern = self._find(host, [RdsUtils.AURORA_DNS_PATTERN,
|
|
134
|
+
RdsUtils.AURORA_CHINA_DNS_PATTERN,
|
|
135
|
+
RdsUtils.AURORA_OLD_CHINA_DNS_PATTERN,
|
|
136
|
+
RdsUtils.AURORA_GOV_DNS_PATTERN])
|
|
137
|
+
group = self._get_regex_group(pattern, RdsUtils.DNS_GROUP)
|
|
138
|
+
|
|
139
|
+
if group:
|
|
140
|
+
RdsUtils.CACHE_PATTERNS[host] = group
|
|
141
|
+
|
|
142
|
+
return pattern is not None
|
|
118
143
|
|
|
119
144
|
def is_rds_instance(self, host: str) -> bool:
|
|
120
|
-
return
|
|
121
|
-
and self.is_rds_dns(host))
|
|
145
|
+
return self._get_dns_group(host) is None and self.is_rds_dns(host)
|
|
122
146
|
|
|
123
147
|
def is_rds_proxy_dns(self, host: str) -> bool:
|
|
124
|
-
|
|
148
|
+
dns_group = self._get_dns_group(host)
|
|
149
|
+
return dns_group is not None and dns_group.casefold() == "proxy-"
|
|
125
150
|
|
|
126
151
|
def get_rds_instance_host_pattern(self, host: str) -> str:
|
|
127
152
|
if not host or not host.strip():
|
|
128
153
|
return "?"
|
|
129
154
|
|
|
130
|
-
match = self.
|
|
155
|
+
match = self._get_group(host, RdsUtils.DOMAIN_GROUP)
|
|
131
156
|
if match:
|
|
132
|
-
return f"?.{match
|
|
157
|
+
return f"?.{match}"
|
|
133
158
|
|
|
134
159
|
return "?"
|
|
135
160
|
|
|
@@ -137,56 +162,54 @@ class RdsUtils:
|
|
|
137
162
|
if not host or not host.strip():
|
|
138
163
|
return None
|
|
139
164
|
|
|
140
|
-
|
|
141
|
-
if
|
|
142
|
-
return
|
|
165
|
+
group = self._get_group(host, RdsUtils.REGION_GROUP)
|
|
166
|
+
if group:
|
|
167
|
+
return group
|
|
143
168
|
|
|
169
|
+
elb_matcher = search(RdsUtils.ELB_PATTERN, host)
|
|
170
|
+
if elb_matcher:
|
|
171
|
+
return elb_matcher.group(RdsUtils.REGION_GROUP)
|
|
144
172
|
return None
|
|
145
173
|
|
|
146
174
|
def is_writer_cluster_dns(self, host: str) -> bool:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
match = self._find(host, [self.AURORA_CLUSTER_PATTERN, self.AURORA_CHINA_CLUSTER_PATTERN])
|
|
151
|
-
if match:
|
|
152
|
-
return "cluster-".casefold() == match.group(self.DNS_GROUP).casefold()
|
|
153
|
-
|
|
154
|
-
return False
|
|
175
|
+
dns_group = self._get_dns_group(host)
|
|
176
|
+
return dns_group is not None and dns_group.casefold() == "cluster-"
|
|
155
177
|
|
|
156
178
|
def is_reader_cluster_dns(self, host: str) -> bool:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return "cluster-ro-".casefold() == match.group(self.DNS_GROUP).casefold()
|
|
160
|
-
|
|
161
|
-
return False
|
|
179
|
+
dns_group = self._get_dns_group(host)
|
|
180
|
+
return dns_group is not None and dns_group.casefold() == "cluster-ro-"
|
|
162
181
|
|
|
163
182
|
def get_rds_cluster_host_url(self, host: str):
|
|
164
183
|
if not host or not host.strip():
|
|
165
184
|
return None
|
|
166
185
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
186
|
+
for pattern in [RdsUtils.AURORA_DNS_PATTERN,
|
|
187
|
+
RdsUtils.AURORA_CHINA_DNS_PATTERN,
|
|
188
|
+
RdsUtils.AURORA_OLD_CHINA_DNS_PATTERN,
|
|
189
|
+
RdsUtils.AURORA_GOV_DNS_PATTERN]:
|
|
190
|
+
if m := search(pattern, host):
|
|
191
|
+
group = self._get_regex_group(m, RdsUtils.DNS_GROUP)
|
|
192
|
+
if group is not None:
|
|
193
|
+
return sub(pattern, r"\g<instance>.cluster-\g<domain>", host)
|
|
194
|
+
return None
|
|
172
195
|
|
|
173
196
|
return None
|
|
174
197
|
|
|
175
198
|
def get_instance_id(self, host: str) -> Optional[str]:
|
|
176
|
-
if
|
|
177
|
-
return
|
|
178
|
-
|
|
179
|
-
match = self._find(host, [self.AURORA_INSTANCE_PATTERN, self.AURORA_CHINA_INSTANCE_PATTERN])
|
|
180
|
-
if match:
|
|
181
|
-
return match.group(self.INSTANCE_GROUP)
|
|
199
|
+
if self._get_dns_group(host) is None:
|
|
200
|
+
return self._get_group(host, self.INSTANCE_GROUP)
|
|
182
201
|
|
|
183
202
|
return None
|
|
184
203
|
|
|
185
204
|
def is_ipv4(self, host: str) -> bool:
|
|
186
|
-
|
|
205
|
+
if host is None or not host.strip():
|
|
206
|
+
return False
|
|
207
|
+
return search(RdsUtils.IP_V4, host) is not None
|
|
187
208
|
|
|
188
209
|
def is_ipv6(self, host: str) -> bool:
|
|
189
|
-
|
|
210
|
+
if host is None or not host.strip():
|
|
211
|
+
return False
|
|
212
|
+
return search(RdsUtils.IP_V6_COMPRESSED, host) is not None or search(RdsUtils.IP_V6, host) is not None
|
|
190
213
|
|
|
191
214
|
def is_dns_pattern_valid(self, host: str) -> bool:
|
|
192
215
|
return "?" in host
|
|
@@ -210,17 +233,48 @@ class RdsUtils:
|
|
|
210
233
|
|
|
211
234
|
return RdsUrlType.OTHER
|
|
212
235
|
|
|
213
|
-
def _contains(self, host: str, patterns: list) -> bool:
|
|
214
|
-
if not host or not host.strip():
|
|
215
|
-
return False
|
|
216
|
-
|
|
217
|
-
return len([pattern for pattern in patterns if search(pattern, host)]) > 0
|
|
218
|
-
|
|
219
236
|
def _find(self, host: str, patterns: list):
|
|
220
237
|
if not host or not host.strip():
|
|
221
238
|
return None
|
|
222
239
|
|
|
223
240
|
for pattern in patterns:
|
|
241
|
+
match = RdsUtils.CACHE_DNS_PATTERNS.get(host)
|
|
242
|
+
if match:
|
|
243
|
+
return match
|
|
244
|
+
|
|
224
245
|
match = search(pattern, host)
|
|
225
246
|
if match:
|
|
247
|
+
RdsUtils.CACHE_DNS_PATTERNS[host] = match
|
|
226
248
|
return match
|
|
249
|
+
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
def _get_regex_group(self, pattern: Match[str], group_name: str):
|
|
253
|
+
if pattern is None:
|
|
254
|
+
return None
|
|
255
|
+
return pattern.group(group_name)
|
|
256
|
+
|
|
257
|
+
def _get_group(self, host: str, group: str):
|
|
258
|
+
if not host or not host.strip():
|
|
259
|
+
return None
|
|
260
|
+
|
|
261
|
+
pattern = self._find(host, [RdsUtils.AURORA_DNS_PATTERN,
|
|
262
|
+
RdsUtils.AURORA_CHINA_DNS_PATTERN,
|
|
263
|
+
RdsUtils.AURORA_OLD_CHINA_DNS_PATTERN,
|
|
264
|
+
RdsUtils.AURORA_GOV_DNS_PATTERN])
|
|
265
|
+
return self._get_regex_group(pattern, group)
|
|
266
|
+
|
|
267
|
+
def _get_dns_group(self, host: str):
|
|
268
|
+
return self._get_group(host, RdsUtils.DNS_GROUP)
|
|
269
|
+
|
|
270
|
+
def remove_port(self, url: str):
|
|
271
|
+
if not url or not url.strip():
|
|
272
|
+
return None
|
|
273
|
+
if ":" in url:
|
|
274
|
+
return url.split(":")[0]
|
|
275
|
+
return url
|
|
276
|
+
|
|
277
|
+
@staticmethod
|
|
278
|
+
def clear_cache():
|
|
279
|
+
RdsUtils.CACHE_PATTERNS.clear()
|
|
280
|
+
RdsUtils.CACHE_DNS_PATTERNS.clear()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|