aws_advanced_ruby_driver_wrapper 1.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +23 -0
- data/LICENSE +175 -0
- data/NOTICE +1 -0
- data/README.md +168 -0
- data/THIRD-PARTY-LICENSES +473 -0
- data/aws_advanced_ruby_driver_wrapper.gemspec +73 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +73 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/custom_configuration.rb +58 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_mysql_dialect.rb +103 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_pg_dialect.rb +124 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/dialect_codes.rb +38 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_mysql_dialect.rb +91 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_pg_dialect.rb +92 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_mysql_dialect.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_pg_dialect.rb +86 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/mysql_dialect.rb +98 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/pg_dialect.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_mysql_dialect.rb +88 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_pg_dialect.rb +86 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/unknown_dialect.rb +72 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/utils/dialect_utils.rb +71 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +154 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +55 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +165 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +201 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +62 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +80 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/pg_error_handler.rb +126 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +59 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/connection_string_host_list_provider.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/global_aurora_host_list_provider.rb +65 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability.rb +24 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability_strategy.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_info.rb +137 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_role.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/random_host_selector.rb +40 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/rds_host_list_provider.rb +206 -0
- data/lib/aws_advanced_ruby_driver_wrapper/logging.rb +110 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +709 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/global_cluster_topology_monitor.rb +72 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +99 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +57 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_state.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +429 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +205 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +132 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/iam_host_tracker.rb +84 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interim_status.rb +92 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interval_rate.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase.rb +69 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_event_log.rb +85 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_time_info.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/role.rb +38 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +83 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/reject_connect_routing.rb +40 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +136 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +53 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +52 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +83 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status.rb +68 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +244 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_info.rb +30 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +564 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +414 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_state.rb +98 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_timer.rb +46 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +266 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +158 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/info.rb +111 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/member_list_type.rb +31 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/role.rb +45 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_mode.rb +43 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +467 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_mode.rb +68 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +403 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +159 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +485 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/audit_logger.rb +157 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_cipher.rb +159 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_encryption_config.rb +61 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/connection_source.rb +91 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/data_key_cache.rb +220 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_algorithm.rb +75 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_config.rb +146 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_service.rb +391 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/error_context.rb +198 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/errors.rb +259 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +435 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +378 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_metadata.rb +86 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +890 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_utility.rb +281 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/metadata_manager.rb +332 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sanitizer.rb +147 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_name.rb +70 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_validator.rb +211 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql_runner.rb +147 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/type_marker.rb +109 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +358 -0
- data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +659 -0
- data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +409 -0
- data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +122 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/connection_service.rb +143 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +267 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +199 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +186 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_call_context.rb +63 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +273 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +30 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +78 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/session_state_service.rb +56 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/accessible_regions.rb +52 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/aurora_topology_utils.rb +99 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/aws_credentials_utils.rb +62 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +91 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +368 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/conversion_utils.rb +51 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +119 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/data_access_event.rb +26 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/monitor_reset_event.rb +26 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +185 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/host_list_utils.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +112 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/multi_az_topology_utils.rb +117 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +99 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +641 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +502 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +63 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_type.rb +35 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint_parser.rb +50 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +139 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_url_type.rb +71 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_utils.rb +575 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +153 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_encoding.rb +56 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_method_analyzer.rb +195 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/cache_entry.rb +56 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/expiration_cache.rb +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/sliding_expiration_cache.rb +137 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +172 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +127 -0
- data/lib/aws_advanced_ruby_driver_wrapper/version.rb +19 -0
- data/lib/aws_advanced_ruby_driver_wrapper/wrapper_property.rb +64 -0
- data/lib/aws_advanced_ruby_driver_wrapper.rb +116 -0
- metadata +227 -0
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License").
|
|
6
|
+
# You may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require 'concurrent'
|
|
18
|
+
require_relative 'rds_url_type'
|
|
19
|
+
|
|
20
|
+
module AwsAdvancedRubyDriverWrapper
|
|
21
|
+
module Utils
|
|
22
|
+
# Utility module for parsing and classifying Amazon RDS/Aurora endpoint hostnames.
|
|
23
|
+
#
|
|
24
|
+
# Determines endpoint type (writer cluster, reader cluster, instance, proxy, etc.),
|
|
25
|
+
# extracts metadata (region, cluster ID, instance ID), and supports blue/green
|
|
26
|
+
# deployment host manipulation.
|
|
27
|
+
#
|
|
28
|
+
# Aurora endpoint format reference:
|
|
29
|
+
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.Endpoints.html
|
|
30
|
+
#
|
|
31
|
+
# Cluster (Writer): <db-cluster>.cluster-<xyz>.<region>.rds.amazonaws.com
|
|
32
|
+
# Cluster Reader: <db-cluster>.cluster-ro-<xyz>.<region>.rds.amazonaws.com
|
|
33
|
+
# Custom Cluster: <alias>.cluster-custom-<xyz>.<region>.rds.amazonaws.com
|
|
34
|
+
# Instance: <instance>.<xyz>.<region>.rds.amazonaws.com
|
|
35
|
+
# RDS Proxy: <proxy>.proxy-<xyz>.<region>.rds.amazonaws.com
|
|
36
|
+
# RDS Proxy Custom: <name>.endpoint.proxy-<xyz>.<region>.rds.amazonaws.com
|
|
37
|
+
# Global DB Writer: <gdb>.global-<xyz>.global.rds.amazonaws.com
|
|
38
|
+
# Limitless: <db>.shardgrp-<xyz>.<region>.rds.amazonaws.com
|
|
39
|
+
#
|
|
40
|
+
# China regions use a different structure:
|
|
41
|
+
# New: <xyz>.rds.<region>.amazonaws.com.cn
|
|
42
|
+
# Old: <xyz>.<region>.rds.amazonaws.com.cn
|
|
43
|
+
#
|
|
44
|
+
# Gov/ISO/ISOB regions:
|
|
45
|
+
# <xyz>.(rds|rds-fips).<region>.(amazonaws.com|c2s.ic.gov|sc2s.sgov.gov)
|
|
46
|
+
module RdsUtils
|
|
47
|
+
extend self
|
|
48
|
+
|
|
49
|
+
# Authoritative allow-list of AWS regions that can host an RDS/Aurora endpoint.
|
|
50
|
+
KNOWN_REGIONS = %w[
|
|
51
|
+
af-south-1
|
|
52
|
+
ap-east-1 ap-east-2
|
|
53
|
+
ap-northeast-1 ap-northeast-2 ap-northeast-3
|
|
54
|
+
ap-south-1 ap-south-2
|
|
55
|
+
ap-southeast-1 ap-southeast-2 ap-southeast-3 ap-southeast-4
|
|
56
|
+
ap-southeast-5 ap-southeast-6 ap-southeast-7
|
|
57
|
+
ca-central-1 ca-west-1
|
|
58
|
+
cn-north-1 cn-northwest-1
|
|
59
|
+
eu-central-1 eu-central-2
|
|
60
|
+
eu-isoe-west-1
|
|
61
|
+
eu-north-1
|
|
62
|
+
eu-south-1 eu-south-2
|
|
63
|
+
eu-west-1 eu-west-2 eu-west-3
|
|
64
|
+
eusc-de-east-1
|
|
65
|
+
il-central-1
|
|
66
|
+
me-central-1 me-south-1
|
|
67
|
+
mx-central-1
|
|
68
|
+
sa-east-1
|
|
69
|
+
us-east-1 us-east-2
|
|
70
|
+
us-gov-east-1 us-gov-west-1
|
|
71
|
+
us-iso-east-1 us-iso-west-1
|
|
72
|
+
us-isob-east-1 us-isob-west-1
|
|
73
|
+
us-isof-east-1 us-isof-south-1
|
|
74
|
+
us-west-1 us-west-2
|
|
75
|
+
].to_set.freeze
|
|
76
|
+
|
|
77
|
+
# -- Standard commercial regions --
|
|
78
|
+
AURORA_DNS_PATTERN = /
|
|
79
|
+
^(?<instance>.+)\.
|
|
80
|
+
(?<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|shardgrp-)?
|
|
81
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
82
|
+
\.(?:rds|rds-fips)\.amazonaws\.(?:com|au|eu|uk)\.?)$
|
|
83
|
+
/ix
|
|
84
|
+
|
|
85
|
+
AURORA_CLUSTER_PATTERN = /
|
|
86
|
+
^(?<instance>.+)\.
|
|
87
|
+
(?<dns>cluster-|cluster-ro-)+
|
|
88
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
89
|
+
\.(?:rds|rds-fips)\.amazonaws\.(?:com|au|eu|uk)\.?)$
|
|
90
|
+
/ix
|
|
91
|
+
|
|
92
|
+
# -- Limitless (covers all TLD variants) --
|
|
93
|
+
AURORA_LIMITLESS_CLUSTER_PATTERN = /
|
|
94
|
+
(?<instance>.+)\.
|
|
95
|
+
(?<dns>shardgrp-)+
|
|
96
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
97
|
+
\.(?:rds|rds-fips)\.(?:amazonaws\.com\.?|amazonaws\.eu\.?|amazonaws\.au\.?|amazonaws\.uk\.?
|
|
98
|
+
|amazonaws\.com\.cn\.?|sc2s\.sgov\.gov\.?|c2s\.ic\.gov\.?))$
|
|
99
|
+
/ix
|
|
100
|
+
|
|
101
|
+
# -- China (new format: <xyz>.rds.<region>.amazonaws.com.cn) --
|
|
102
|
+
AURORA_CHINA_DNS_PATTERN = /
|
|
103
|
+
^(?<instance>.+)\.
|
|
104
|
+
(?<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|shardgrp-)?
|
|
105
|
+
(?<domain>[a-zA-Z0-9]+\.(?:rds|rds-fips)\.(?<region>[a-zA-Z0-9-]+)
|
|
106
|
+
\.amazonaws\.com\.cn\.?)$
|
|
107
|
+
/ix
|
|
108
|
+
|
|
109
|
+
AURORA_CHINA_CLUSTER_PATTERN = /
|
|
110
|
+
^(?<instance>.+)\.
|
|
111
|
+
(?<dns>cluster-|cluster-ro-)+
|
|
112
|
+
(?<domain>[a-zA-Z0-9]+\.(?:rds|rds-fips)\.(?<region>[a-zA-Z0-9-]+)
|
|
113
|
+
\.amazonaws\.com\.cn\.?)$
|
|
114
|
+
/ix
|
|
115
|
+
|
|
116
|
+
# -- China (old/legacy format: <xyz>.<region>.rds.amazonaws.com.cn) --
|
|
117
|
+
AURORA_OLD_CHINA_DNS_PATTERN = /
|
|
118
|
+
^(?<instance>.+)\.
|
|
119
|
+
(?<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|shardgrp-)?
|
|
120
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
121
|
+
\.(?:rds|rds-fips)\.amazonaws\.com\.cn\.?)$
|
|
122
|
+
/ix
|
|
123
|
+
|
|
124
|
+
AURORA_OLD_CHINA_CLUSTER_PATTERN = /
|
|
125
|
+
^(?<instance>.+)\.
|
|
126
|
+
(?<dns>cluster-|cluster-ro-)+
|
|
127
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
128
|
+
\.(?:rds|rds-fips)\.amazonaws\.com\.cn\.?)$
|
|
129
|
+
/ix
|
|
130
|
+
|
|
131
|
+
# -- Gov / ISO / ISOB regions --
|
|
132
|
+
AURORA_GOV_DNS_PATTERN = /
|
|
133
|
+
^(?<instance>.+)\.
|
|
134
|
+
(?<dns>proxy-|cluster-|cluster-ro-|cluster-custom-|shardgrp-)?
|
|
135
|
+
(?<domain>[a-zA-Z0-9]+\.(?:rds|rds-fips)\.(?<region>[a-zA-Z0-9-]+)
|
|
136
|
+
\.(?:amazonaws\.com\.?|c2s\.ic\.gov\.?|sc2s\.sgov\.gov\.?))$
|
|
137
|
+
/ix
|
|
138
|
+
|
|
139
|
+
AURORA_GOV_CLUSTER_PATTERN = /
|
|
140
|
+
^(?<instance>.+)\.
|
|
141
|
+
(?<dns>cluster-|cluster-ro-)+
|
|
142
|
+
(?<domain>[a-zA-Z0-9]+\.(?:rds|rds-fips)\.(?<region>[a-zA-Z0-9-]+)
|
|
143
|
+
\.(?:amazonaws\.com\.?|c2s\.ic\.gov\.?|sc2s\.sgov\.gov\.?))$
|
|
144
|
+
/ix
|
|
145
|
+
|
|
146
|
+
# -- ELB (region extraction only) --
|
|
147
|
+
ELB_PATTERN = /
|
|
148
|
+
^(?<instance>.+)\.elb\.
|
|
149
|
+
(?<region>[a-zA-Z0-9-]+)\.amazonaws\.(?:com|au|eu|uk)\.?$
|
|
150
|
+
/ix
|
|
151
|
+
|
|
152
|
+
# -- IP addresses --
|
|
153
|
+
IP_V4 = /
|
|
154
|
+
^(?:[1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.
|
|
155
|
+
(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}
|
|
156
|
+
(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
|
|
157
|
+
/x
|
|
158
|
+
|
|
159
|
+
IP_V6 = /^[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){7}$/i
|
|
160
|
+
|
|
161
|
+
IP_V6_COMPRESSED = /
|
|
162
|
+
^(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){0,5})?
|
|
163
|
+
::
|
|
164
|
+
(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){0,5})?$
|
|
165
|
+
/ix
|
|
166
|
+
|
|
167
|
+
# -- Blue/green deployment --
|
|
168
|
+
BG_GREEN_HOST_PATTERN = /(?<prefix>-green-[0-9a-z]{6})\./i
|
|
169
|
+
BG_GREEN_HOSTID_PATTERN = /\A(.+)-green-[0-9a-z]{6}\z/i
|
|
170
|
+
BG_OLD_HOST_PATTERN = /(?<prefix>-old1)\./i
|
|
171
|
+
|
|
172
|
+
# -- Global database --
|
|
173
|
+
AURORA_GLOBAL_WRITER_DNS_PATTERN = /
|
|
174
|
+
^(?<instance>.+)\.
|
|
175
|
+
(?<dns>global-)?
|
|
176
|
+
(?<domain>[a-zA-Z0-9]+\.global\.rds\.amazonaws\.com\.?)$
|
|
177
|
+
/ix
|
|
178
|
+
|
|
179
|
+
# -- RDS Proxy endpoints --
|
|
180
|
+
RDS_PROXY_ENDPOINT_DNS_PATTERN = /
|
|
181
|
+
^(?<instance>.+)\.endpoint\.
|
|
182
|
+
(?<dns>proxy-)?
|
|
183
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
184
|
+
\.rds\.amazonaws\.com\.?)$
|
|
185
|
+
/ix
|
|
186
|
+
|
|
187
|
+
RDS_PROXY_ENDPOINT_CHINA_DNS_PATTERN = /
|
|
188
|
+
^(?<instance>.+)\.endpoint\.
|
|
189
|
+
(?<dns>proxy-)+
|
|
190
|
+
(?<domain>[a-zA-Z0-9]+\.rds\.(?<region>[a-zA-Z0-9-]+)
|
|
191
|
+
\.amazonaws\.com\.cn\.?)$
|
|
192
|
+
/ix
|
|
193
|
+
|
|
194
|
+
RDS_PROXY_ENDPOINT_OLD_CHINA_DNS_PATTERN = /
|
|
195
|
+
^(?<instance>.+)\.endpoint\.
|
|
196
|
+
(?<dns>proxy-)?
|
|
197
|
+
(?<domain>[a-zA-Z0-9]+\.(?<region>[a-zA-Z0-9-]+)
|
|
198
|
+
\.rds\.amazonaws\.com\.cn\.?)$
|
|
199
|
+
/ix
|
|
200
|
+
|
|
201
|
+
DNS_PATTERNS = [
|
|
202
|
+
AURORA_DNS_PATTERN,
|
|
203
|
+
AURORA_CHINA_DNS_PATTERN,
|
|
204
|
+
AURORA_OLD_CHINA_DNS_PATTERN,
|
|
205
|
+
AURORA_GOV_DNS_PATTERN
|
|
206
|
+
].freeze
|
|
207
|
+
|
|
208
|
+
DNS_GROUP_PATTERNS = [
|
|
209
|
+
AURORA_DNS_PATTERN,
|
|
210
|
+
AURORA_CHINA_DNS_PATTERN,
|
|
211
|
+
AURORA_OLD_CHINA_DNS_PATTERN,
|
|
212
|
+
AURORA_GOV_DNS_PATTERN,
|
|
213
|
+
AURORA_GLOBAL_WRITER_DNS_PATTERN
|
|
214
|
+
].freeze
|
|
215
|
+
|
|
216
|
+
CLUSTER_PATTERNS = [
|
|
217
|
+
[AURORA_CLUSTER_PATTERN, 'cluster-'],
|
|
218
|
+
[AURORA_CHINA_CLUSTER_PATTERN, 'cluster-'],
|
|
219
|
+
[AURORA_OLD_CHINA_CLUSTER_PATTERN, 'cluster-'],
|
|
220
|
+
[AURORA_GOV_CLUSTER_PATTERN, 'cluster-'],
|
|
221
|
+
[AURORA_LIMITLESS_CLUSTER_PATTERN, 'shardgrp-']
|
|
222
|
+
].freeze
|
|
223
|
+
|
|
224
|
+
PROXY_ENDPOINT_PATTERNS = [
|
|
225
|
+
RDS_PROXY_ENDPOINT_DNS_PATTERN,
|
|
226
|
+
RDS_PROXY_ENDPOINT_CHINA_DNS_PATTERN,
|
|
227
|
+
RDS_PROXY_ENDPOINT_OLD_CHINA_DNS_PATTERN
|
|
228
|
+
].freeze
|
|
229
|
+
|
|
230
|
+
# Caches the regex match groups per host. Only positive matches are ever stored (never nil),
|
|
231
|
+
# so a lock-free concurrent map is safe here and its reads avoid a mutex on the hot path.
|
|
232
|
+
@cached_matches = Concurrent::Map.new
|
|
233
|
+
|
|
234
|
+
# Caches the DNS-group token per host. Unlike the other two, this caches nil results (a host
|
|
235
|
+
# with no DNS group), which a concurrent map cannot hold, so it stays a plain hash guarded by
|
|
236
|
+
# @mutex.
|
|
237
|
+
@cached_dns_groups = {}
|
|
238
|
+
@mutex = Mutex.new
|
|
239
|
+
@prepare_host_func = nil
|
|
240
|
+
|
|
241
|
+
# Caches the final endpoint classification per host. Values are never nil, so like
|
|
242
|
+
# @cached_matches it uses a lock-free concurrent map; a hit skips the whole pattern sweep.
|
|
243
|
+
@cached_url_types = Concurrent::Map.new
|
|
244
|
+
|
|
245
|
+
def clear_cache
|
|
246
|
+
@cached_matches.clear
|
|
247
|
+
@cached_url_types.clear
|
|
248
|
+
@mutex.synchronize { @cached_dns_groups.clear }
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
attr_reader :prepare_host_func
|
|
252
|
+
|
|
253
|
+
# Changing how hosts are prepared can change their classification, so the classification cache
|
|
254
|
+
# (keyed by the raw host) must be dropped when the prepare function changes. The pattern caches
|
|
255
|
+
# are keyed by the prepared host and self-invalidate, so they do not need clearing here.
|
|
256
|
+
def prepare_host_func=(func)
|
|
257
|
+
@prepare_host_func = func
|
|
258
|
+
@cached_url_types.clear
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def reset_prepare_host_func
|
|
262
|
+
@prepare_host_func = nil
|
|
263
|
+
@cached_url_types.clear
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def rds_dns?(host)
|
|
267
|
+
prepared = prepared_host(host)
|
|
268
|
+
groups = cache_match(prepared, *DNS_PATTERNS)
|
|
269
|
+
if groups
|
|
270
|
+
dns = groups['dns']
|
|
271
|
+
@mutex.synchronize { @cached_dns_groups[prepared] = dns } if dns
|
|
272
|
+
true
|
|
273
|
+
else
|
|
274
|
+
false
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def rds_cluster_dns?(host)
|
|
279
|
+
dns = dns_group(prepared_host(host))
|
|
280
|
+
!dns.nil? && (dns.casecmp('cluster-').zero? || dns.casecmp('cluster-ro-').zero?)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def rds_custom_cluster_dns?(host)
|
|
284
|
+
dns = dns_group(prepared_host(host))
|
|
285
|
+
!dns.nil? && dns.downcase.start_with?('cluster-custom-')
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def rds_instance?(host)
|
|
289
|
+
prepared = prepared_host(host)
|
|
290
|
+
dns_group(prepared).nil? && rds_dns?(prepared)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def rds_proxy_dns?(host)
|
|
294
|
+
dns = dns_group(prepared_host(host))
|
|
295
|
+
!dns.nil? && dns.downcase.start_with?('proxy-')
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def rds_proxy_endpoint_dns?(host)
|
|
299
|
+
prepared = prepared_host(host)
|
|
300
|
+
return false if blank?(prepared)
|
|
301
|
+
|
|
302
|
+
groups = match_first(prepared, *PROXY_ENDPOINT_PATTERNS)
|
|
303
|
+
!groups.nil? && !groups['dns'].nil? && !groups['instance'].nil?
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def writer_cluster_dns?(host)
|
|
307
|
+
dns = dns_group(prepared_host(host))
|
|
308
|
+
!dns.nil? && dns.casecmp('cluster-').zero?
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def reader_cluster_dns?(host)
|
|
312
|
+
dns = dns_group(prepared_host(host))
|
|
313
|
+
!dns.nil? && dns.casecmp('cluster-ro-').zero?
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def limitless_db_shard_group_dns?(host)
|
|
317
|
+
dns = dns_group(prepared_host(host))
|
|
318
|
+
!dns.nil? && dns.casecmp('shardgrp-').zero?
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def global_db_writer_cluster_dns?(host)
|
|
322
|
+
dns = dns_group(prepared_host(host))
|
|
323
|
+
!dns.nil? && dns.casecmp('global-').zero?
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def ip?(host)
|
|
327
|
+
ipv4?(host) || ipv6?(host)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def ipv4?(host)
|
|
331
|
+
!blank?(host) && IP_V4.match?(host)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def ipv6?(host)
|
|
335
|
+
!blank?(host) && (IP_V6.match?(host) || IP_V6_COMPRESSED.match?(host))
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Priority-ordered type checks; first match wins.
|
|
339
|
+
RDS_TYPE_CHECKS = [
|
|
340
|
+
[:ip?, RdsUrlType::IP_ADDRESS],
|
|
341
|
+
[:global_db_writer_cluster_dns?, RdsUrlType::RDS_GLOBAL_WRITER_CLUSTER],
|
|
342
|
+
[:writer_cluster_dns?, RdsUrlType::RDS_WRITER_CLUSTER],
|
|
343
|
+
[:reader_cluster_dns?, RdsUrlType::RDS_READER_CLUSTER],
|
|
344
|
+
[:rds_custom_cluster_dns?, RdsUrlType::RDS_CUSTOM_CLUSTER],
|
|
345
|
+
[:limitless_db_shard_group_dns?, RdsUrlType::RDS_AURORA_LIMITLESS_DB_SHARD_GROUP],
|
|
346
|
+
[:rds_proxy_endpoint_dns?, RdsUrlType::RDS_PROXY_ENDPOINT],
|
|
347
|
+
[:rds_proxy_dns?, RdsUrlType::RDS_PROXY],
|
|
348
|
+
[:rds_dns?, RdsUrlType::RDS_INSTANCE]
|
|
349
|
+
].freeze
|
|
350
|
+
|
|
351
|
+
def identify_rds_type(host)
|
|
352
|
+
return RdsUrlType::OTHER if blank?(host)
|
|
353
|
+
|
|
354
|
+
@cached_url_types.compute_if_absent(host) { classify_rds_type(host) }
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def classify_rds_type(host)
|
|
358
|
+
RDS_TYPE_CHECKS.each do |check, type|
|
|
359
|
+
return type if send(check, host)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
RdsUrlType::OTHER
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def rds_host_id(host)
|
|
366
|
+
prepared = prepared_host(host)
|
|
367
|
+
return nil if blank?(prepared)
|
|
368
|
+
|
|
369
|
+
groups = cache_match(prepared, *DNS_PATTERNS)
|
|
370
|
+
return nil unless groups
|
|
371
|
+
|
|
372
|
+
groups['dns'] ? groups['instance'] : nil
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def rds_cluster_id(host)
|
|
376
|
+
prepared = prepared_host(host)
|
|
377
|
+
return nil if blank?(prepared)
|
|
378
|
+
|
|
379
|
+
groups = cache_match(prepared, *DNS_GROUP_PATTERNS)
|
|
380
|
+
return nil unless groups
|
|
381
|
+
|
|
382
|
+
groups['dns'] ? groups['instance'] : nil
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def rds_instance_name(host)
|
|
386
|
+
prepared = prepared_host(host)
|
|
387
|
+
return nil if blank?(prepared)
|
|
388
|
+
|
|
389
|
+
groups = cache_match(prepared, *DNS_PATTERNS)
|
|
390
|
+
return nil unless groups
|
|
391
|
+
|
|
392
|
+
groups['dns'].nil? ? groups['instance'] : nil
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def rds_instance_host_pattern(host)
|
|
396
|
+
prepared = prepared_host(host)
|
|
397
|
+
return '?' if blank?(prepared)
|
|
398
|
+
|
|
399
|
+
groups = cache_match(prepared, *DNS_PATTERNS)
|
|
400
|
+
domain = groups&.[]('domain')
|
|
401
|
+
domain ? "?.#{domain}" : '?'
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def rds_region(host)
|
|
405
|
+
prepared = prepared_host(host)
|
|
406
|
+
return nil if blank?(prepared)
|
|
407
|
+
|
|
408
|
+
groups = cache_match(prepared, *DNS_PATTERNS)
|
|
409
|
+
region = groups&.[]('region')
|
|
410
|
+
return region if valid_region?(region)
|
|
411
|
+
|
|
412
|
+
elb_match = ELB_PATTERN.match(prepared)
|
|
413
|
+
elb_region = elb_match&.[]('region')
|
|
414
|
+
valid_region?(elb_region) ? elb_region : nil
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# Whether the given value is a real AWS region known to this wrapper.
|
|
418
|
+
#
|
|
419
|
+
# Case-insensitive. Returns false for nil/blank and for typos or otherwise
|
|
420
|
+
# incorrect values (e.g. "us-esat-1").
|
|
421
|
+
#
|
|
422
|
+
# @param region [String, nil]
|
|
423
|
+
# @return [Boolean]
|
|
424
|
+
def valid_region?(region)
|
|
425
|
+
return false if blank?(region)
|
|
426
|
+
|
|
427
|
+
KNOWN_REGIONS.include?(region.downcase)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
# Whether the host carries a region segment that was parsed out of the
|
|
431
|
+
# endpoint but is NOT a real AWS region (i.e. a likely typo such as
|
|
432
|
+
# "us-esat-1").
|
|
433
|
+
#
|
|
434
|
+
# @param host [String, nil]
|
|
435
|
+
# @return [Boolean] true only when a region was captured and is invalid
|
|
436
|
+
def region_typo?(host)
|
|
437
|
+
prepared = prepared_host(host)
|
|
438
|
+
return false if blank?(prepared)
|
|
439
|
+
|
|
440
|
+
# Aurora Global Database endpoints carry the literal "global" in the region
|
|
441
|
+
# slot (e.g. "<id>.global.rds.amazonaws.com"), must never be treated as a typo.
|
|
442
|
+
return false if AURORA_GLOBAL_WRITER_DNS_PATTERN.match?(prepared)
|
|
443
|
+
|
|
444
|
+
groups = cache_match(prepared, *DNS_PATTERNS)
|
|
445
|
+
captured = groups&.[]('region')
|
|
446
|
+
return false if captured.nil? || captured.empty?
|
|
447
|
+
|
|
448
|
+
!valid_region?(captured)
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def same_region?(host1, host2)
|
|
452
|
+
return false if blank?(host1) || blank?(host2)
|
|
453
|
+
|
|
454
|
+
region1 = rds_region(host1)
|
|
455
|
+
region2 = rds_region(host2)
|
|
456
|
+
!region1.nil? && region1.casecmp(region2).zero?
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def rds_cluster_host_url(host)
|
|
460
|
+
prepared = prepared_host(host)
|
|
461
|
+
return nil if blank?(prepared)
|
|
462
|
+
|
|
463
|
+
CLUSTER_PATTERNS.each do |pattern, prefix|
|
|
464
|
+
m = pattern.match(prepared)
|
|
465
|
+
next unless m
|
|
466
|
+
|
|
467
|
+
return "#{m[:instance]}.#{prefix}#{m[:domain]}"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
nil
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def dns_pattern_valid?(pattern)
|
|
474
|
+
return false if blank?(pattern)
|
|
475
|
+
|
|
476
|
+
pattern.count('?') == 1
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
def remove_port(host_and_port)
|
|
480
|
+
return host_and_port if blank?(host_and_port)
|
|
481
|
+
|
|
482
|
+
idx = host_and_port.index(':')
|
|
483
|
+
idx ? host_and_port[0...idx] : host_and_port
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def green_instance?(host)
|
|
487
|
+
prepared = prepared_host(host)
|
|
488
|
+
!blank?(prepared) && BG_GREEN_HOST_PATTERN.match?(prepared)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def old_instance?(host)
|
|
492
|
+
prepared = prepared_host(host)
|
|
493
|
+
!blank?(prepared) && BG_OLD_HOST_PATTERN.match?(prepared)
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
def not_old_instance?(host)
|
|
497
|
+
prepared = prepared_host(host)
|
|
498
|
+
blank?(prepared) || !BG_OLD_HOST_PATTERN.match?(prepared)
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def not_green_and_old_prefix_instance?(host)
|
|
502
|
+
prepared = prepared_host(host)
|
|
503
|
+
!blank?(prepared) &&
|
|
504
|
+
!BG_GREEN_HOST_PATTERN.match?(prepared) &&
|
|
505
|
+
!BG_OLD_HOST_PATTERN.match?(prepared)
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def remove_green_instance_prefix(host)
|
|
509
|
+
return nil if host.nil?
|
|
510
|
+
return host if host.empty?
|
|
511
|
+
|
|
512
|
+
prepared = prepared_host(host)
|
|
513
|
+
m = BG_GREEN_HOST_PATTERN.match(prepared)
|
|
514
|
+
unless m
|
|
515
|
+
hostid_m = BG_GREEN_HOSTID_PATTERN.match(prepared)
|
|
516
|
+
return hostid_m ? hostid_m[1] : host
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
prefix = m[:prefix]
|
|
520
|
+
return host if blank?(prefix)
|
|
521
|
+
|
|
522
|
+
host.sub("#{prefix}.", '.')
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
private
|
|
526
|
+
|
|
527
|
+
def blank?(str)
|
|
528
|
+
str.nil? || str.empty?
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
def prepared_host(host)
|
|
532
|
+
return host unless @prepare_host_func
|
|
533
|
+
|
|
534
|
+
result = @prepare_host_func.call(host)
|
|
535
|
+
result || host
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def cache_match(host, *patterns)
|
|
539
|
+
# Only non-nil match groups are stored, so a nil lookup means "not cached".
|
|
540
|
+
cached = @cached_matches[host]
|
|
541
|
+
return cached if cached
|
|
542
|
+
|
|
543
|
+
patterns.each do |pattern|
|
|
544
|
+
m = pattern.match(host)
|
|
545
|
+
next unless m
|
|
546
|
+
|
|
547
|
+
groups = m.named_captures
|
|
548
|
+
@cached_matches[host] = groups
|
|
549
|
+
return groups
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
nil
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def dns_group(host)
|
|
556
|
+
return nil if blank?(host)
|
|
557
|
+
|
|
558
|
+
@mutex.synchronize { return @cached_dns_groups[host] if @cached_dns_groups.key?(host) }
|
|
559
|
+
|
|
560
|
+
groups = cache_match(host, *DNS_GROUP_PATTERNS)
|
|
561
|
+
dns = groups&.[]('dns')
|
|
562
|
+
@mutex.synchronize { @cached_dns_groups[host] = dns }
|
|
563
|
+
dns
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def match_first(host, *patterns)
|
|
567
|
+
patterns.each do |pattern|
|
|
568
|
+
m = pattern.match(host)
|
|
569
|
+
return m.named_captures if m
|
|
570
|
+
end
|
|
571
|
+
nil
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|