12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
15
- from re import search , sub
16
- from typing import Optional
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,135 +60,156 @@ 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
- AURORA_CHINA_DNS_PATTERN = r"(?P<instance>.+)\." \
81
- r"(?P<dns>proxy-|cluster-|cluster-ro-|cluster-custom-)?" \
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\-]+)\.rds\.amazonaws\.com\.cn)"
84
- AURORA_CHINA_INSTANCE_PATTERN = r"(?P<instance>.+)\." \
85
- r"(?P<domain>[a-zA-Z0-9]+\." \
86
- r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com\.cn)"
87
- AURORA_CHINA_CLUSTER_PATTERN = r"(?P<instance>.+)\." \
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\-]+)\.rds\.amazonaws\.com\.cn)"
91
- AURORA_CHINA_CUSTOM_CLUSTER_PATTERN = r"(?P<instance>.+)\." \
92
- r"(?P<dns>cluster-custom-)+" \
93
- r"(?P<domain>[a-zA-Z0-9]+\." \
94
- r"(?P<region>[a-zA-Z0-9\-]+)\.rds\.amazonaws\.com\.cn)"
95
- AURORA_CHINA_PROXY_DNS_PATTERN = r"(?P<instance>.+)\." \
96
- r"(?P<dns>proxy-)+" \
97
- r"(?P<domain>[a-zA-Z0-9]+\." \
98
- r"(?P<region>[a-zA-Z0-9\-])+\.rds\.amazonaws\.com\.cn)"
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
- return self ._contains (host , [self .AURORA_CLUSTER_PATTERN , self .AURORA_CHINA_CLUSTER_PATTERN ])
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
- return self ._contains (host , [self .AURORA_CUSTOM_CLUSTER_PATTERN , self .AURORA_CHINA_CUSTOM_CLUSTER_PATTERN ])
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
- return self ._contains (host , [self .AURORA_DNS_PATTERN , self .AURORA_CHINA_DNS_PATTERN ])
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 (self ._contains (host , [self .AURORA_INSTANCE_PATTERN , self .AURORA_CHINA_INSTANCE_PATTERN ])
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
- return self ._contains (host , [self .AURORA_PROXY_DNS_PATTERN , self .AURORA_CHINA_PROXY_DNS_PATTERN ])
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 ._find (host , [ self . AURORA_DNS_PATTERN , self . AURORA_CHINA_DNS_PATTERN ] )
155
+ match = self ._get_group (host , RdsUtils . DOMAIN_GROUP )
131
156
if match :
132
- return f"?.{ match . group ( self . DOMAIN_GROUP ) } "
157
+ return f"?.{ match } "
133
158
134
159
return "?"
135
160
136
161
def get_rds_region (self , host : Optional [str ]):
137
162
if not host or not host .strip ():
138
163
return None
139
164
140
- match = self ._find (host , [ self . AURORA_DNS_PATTERN , self . AURORA_CHINA_DNS_PATTERN ] )
141
- if match :
142
- return match . group ( self . REGION_GROUP )
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
- if not host or not host .strip ():
148
- return False
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
- match = self ._find (host , [self .AURORA_CLUSTER_PATTERN , self .AURORA_CHINA_CLUSTER_PATTERN ])
158
- if match :
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
- if search (self .AURORA_CLUSTER_PATTERN , host ):
168
- return sub (self .AURORA_CLUSTER_PATTERN , r"\g<instance>.cluster-\g<domain>" , host )
169
-
170
- if search (self .AURORA_CHINA_CLUSTER_PATTERN , host ):
171
- return sub (self .AURORA_CHINA_CLUSTER_PATTERN , r"\g<instance>.cluster-\g<domain>" , host )
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 not host or not host .strip ():
177
- return None
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
- return self ._contains (host , [self .IP_V4 ])
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
- return self ._contains (host , [self .IP_V6 , self .IP_V6_COMPRESSED ])
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 @@ def identify_rds_type(self, host: Optional[str]) -> RdsUrlType:
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 ()
0 commit comments