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.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +23 -0
  3. data/LICENSE +175 -0
  4. data/NOTICE +1 -0
  5. data/README.md +168 -0
  6. data/THIRD-PARTY-LICENSES +473 -0
  7. data/aws_advanced_ruby_driver_wrapper.gemspec +73 -0
  8. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +73 -0
  9. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +95 -0
  10. data/lib/aws_advanced_ruby_driver_wrapper/custom_configuration.rb +58 -0
  11. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_mysql_dialect.rb +103 -0
  12. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_pg_dialect.rb +124 -0
  13. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/dialect_codes.rb +38 -0
  14. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_mysql_dialect.rb +91 -0
  15. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_pg_dialect.rb +92 -0
  16. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_mysql_dialect.rb +95 -0
  17. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_pg_dialect.rb +86 -0
  18. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/mysql_dialect.rb +98 -0
  19. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/pg_dialect.rb +95 -0
  20. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_mysql_dialect.rb +88 -0
  21. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_pg_dialect.rb +86 -0
  22. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/unknown_dialect.rb +72 -0
  23. data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/utils/dialect_utils.rb +71 -0
  24. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +154 -0
  25. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +55 -0
  26. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +165 -0
  27. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +201 -0
  28. data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +62 -0
  29. data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +80 -0
  30. data/lib/aws_advanced_ruby_driver_wrapper/errors/pg_error_handler.rb +126 -0
  31. data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +59 -0
  32. data/lib/aws_advanced_ruby_driver_wrapper/host/connection_string_host_list_provider.rb +95 -0
  33. data/lib/aws_advanced_ruby_driver_wrapper/host/global_aurora_host_list_provider.rb +65 -0
  34. data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability.rb +24 -0
  35. data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability_strategy.rb +27 -0
  36. data/lib/aws_advanced_ruby_driver_wrapper/host/host_info.rb +137 -0
  37. data/lib/aws_advanced_ruby_driver_wrapper/host/host_role.rb +25 -0
  38. data/lib/aws_advanced_ruby_driver_wrapper/host/random_host_selector.rb +40 -0
  39. data/lib/aws_advanced_ruby_driver_wrapper/host/rds_host_list_provider.rb +206 -0
  40. data/lib/aws_advanced_ruby_driver_wrapper/logging.rb +110 -0
  41. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +709 -0
  42. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/global_cluster_topology_monitor.rb +72 -0
  43. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +99 -0
  44. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +57 -0
  45. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_state.rb +25 -0
  46. data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +429 -0
  47. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +205 -0
  48. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +132 -0
  49. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/iam_host_tracker.rb +84 -0
  50. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interim_status.rb +92 -0
  51. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interval_rate.rb +27 -0
  52. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase.rb +69 -0
  53. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_event_log.rb +85 -0
  54. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_time_info.rb +25 -0
  55. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/role.rb +38 -0
  56. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +83 -0
  57. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/reject_connect_routing.rb +40 -0
  58. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +136 -0
  59. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +53 -0
  60. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +52 -0
  61. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +83 -0
  62. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status.rb +68 -0
  63. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +244 -0
  64. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_info.rb +30 -0
  65. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +564 -0
  66. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +414 -0
  67. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_state.rb +98 -0
  68. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_timer.rb +46 -0
  69. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +266 -0
  70. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +158 -0
  71. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/info.rb +111 -0
  72. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/member_list_type.rb +31 -0
  73. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/role.rb +45 -0
  74. data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +108 -0
  75. data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_mode.rb +43 -0
  76. data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +467 -0
  77. data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_mode.rb +68 -0
  78. data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +403 -0
  79. data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +159 -0
  80. data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +485 -0
  81. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/audit_logger.rb +157 -0
  82. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_cipher.rb +159 -0
  83. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_encryption_config.rb +61 -0
  84. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/connection_source.rb +91 -0
  85. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/data_key_cache.rb +220 -0
  86. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_algorithm.rb +75 -0
  87. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_config.rb +146 -0
  88. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_service.rb +391 -0
  89. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/error_context.rb +198 -0
  90. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/errors.rb +259 -0
  91. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +435 -0
  92. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +378 -0
  93. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_metadata.rb +86 -0
  94. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +890 -0
  95. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_utility.rb +281 -0
  96. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/metadata_manager.rb +332 -0
  97. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sanitizer.rb +147 -0
  98. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_name.rb +70 -0
  99. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_validator.rb +211 -0
  100. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql_runner.rb +147 -0
  101. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/type_marker.rb +109 -0
  102. data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +358 -0
  103. data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +659 -0
  104. data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +409 -0
  105. data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +122 -0
  106. data/lib/aws_advanced_ruby_driver_wrapper/services/connection_service.rb +143 -0
  107. data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +267 -0
  108. data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +199 -0
  109. data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +186 -0
  110. data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_call_context.rb +63 -0
  111. data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +273 -0
  112. data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +30 -0
  113. data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +78 -0
  114. data/lib/aws_advanced_ruby_driver_wrapper/services/session_state_service.rb +56 -0
  115. data/lib/aws_advanced_ruby_driver_wrapper/utils/accessible_regions.rb +52 -0
  116. data/lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb +25 -0
  117. data/lib/aws_advanced_ruby_driver_wrapper/utils/aurora_topology_utils.rb +99 -0
  118. data/lib/aws_advanced_ruby_driver_wrapper/utils/aws_credentials_utils.rb +62 -0
  119. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +91 -0
  120. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +368 -0
  121. data/lib/aws_advanced_ruby_driver_wrapper/utils/conversion_utils.rb +51 -0
  122. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +119 -0
  123. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/data_access_event.rb +26 -0
  124. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/monitor_reset_event.rb +26 -0
  125. data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +185 -0
  126. data/lib/aws_advanced_ruby_driver_wrapper/utils/host_list_utils.rb +27 -0
  127. data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +112 -0
  128. data/lib/aws_advanced_ruby_driver_wrapper/utils/multi_az_topology_utils.rb +117 -0
  129. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +99 -0
  130. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +641 -0
  131. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +502 -0
  132. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +63 -0
  133. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_type.rb +35 -0
  134. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint.rb +27 -0
  135. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint_parser.rb +50 -0
  136. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +139 -0
  137. data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_url_type.rb +71 -0
  138. data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_utils.rb +575 -0
  139. data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +153 -0
  140. data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_encoding.rb +56 -0
  141. data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_method_analyzer.rb +195 -0
  142. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/cache_entry.rb +56 -0
  143. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/expiration_cache.rb +108 -0
  144. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/sliding_expiration_cache.rb +137 -0
  145. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +172 -0
  146. data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +127 -0
  147. data/lib/aws_advanced_ruby_driver_wrapper/version.rb +19 -0
  148. data/lib/aws_advanced_ruby_driver_wrapper/wrapper_property.rb +64 -0
  149. data/lib/aws_advanced_ruby_driver_wrapper.rb +116 -0
  150. metadata +227 -0
@@ -0,0 +1,206 @@
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 '../logging'
19
+ require_relative '../errors'
20
+ require_relative '../property_definition'
21
+ require_relative '../utils/rds_utils'
22
+ require_relative '../utils/rds_url_type'
23
+ require_relative 'host_info'
24
+ require_relative '../monitoring/cluster_topology_monitor'
25
+
26
+ module AwsAdvancedRubyDriverWrapper
27
+ module Host
28
+ # Dynamic host list provider for RDS/Aurora clusters.
29
+ # Manages topology cache reads and lazily creates a ClusterTopologyMonitor
30
+ # to keep the topology up to date in the background.
31
+ class RdsHostListProvider
32
+ include Logging
33
+
34
+ TOPOLOGY_CACHE_NAME = :topology
35
+ DEFAULT_TOPOLOGY_QUERY_TIMEOUT_SEC = 5.0
36
+ MONITOR_EXPIRATION_TIMEOUT_SEC = 900.0 # 15 minutes
37
+
38
+ attr_reader :cluster_id, :instance_template, :rds_url_type
39
+
40
+ # @param service_container [Services::ServiceContainer]
41
+ # @param topology_utils [Object] responds to #query_topology
42
+ def initialize(service_container:, topology_utils:)
43
+ @service_container = service_container
44
+ @topology_utils = topology_utils
45
+
46
+ props = @service_container.connection_service.wrapper_props
47
+ @cluster_id = PropertyDefinition::CLUSTER_ID.get_string(props)
48
+ @instance_template = build_instance_template(props)
49
+ validate_host_pattern!(@instance_template.host)
50
+ @rds_url_type = Utils::RdsUtils.identify_rds_type(initial_host_info.host)
51
+
52
+ prefixed_wrapper_config = @service_container.connection_service.prefixed_wrapper_config[PropertyDefinition::TOPOLOGY_MONITORING_PREFIX]
53
+ @monitoring_wrapper_props = build_monitoring_wrapper_props(prefixed_wrapper_config || ::Concurrent::Map.new)
54
+ prefixed_driver_config = @service_container.connection_service.prefixed_driver_config[PropertyDefinition::TOPOLOGY_MONITORING_PREFIX]
55
+ @monitoring_driver_props = build_monitoring_driver_props(prefixed_driver_config || ::Concurrent::Map.new)
56
+
57
+ register_monitor_type
58
+ register_topology_cache
59
+ end
60
+
61
+ # Returns cached topology, otherwise starts the topology monitor in the background and
62
+ # returns immediately without waiting for a fetch. Initial connections must not block on
63
+ # topology being available; the monitor warms the cache for subsequent connections. Callers
64
+ # that explicitly want to wait use force_refresh with a positive timeout.
65
+ #
66
+ # @return [Array<HostInfo>]
67
+ def refresh
68
+ stored = stored_topology
69
+ return stored unless stored.nil? || stored.empty?
70
+
71
+ return initial_host_list unless @service_container.dialect_service.dialect_final?
72
+
73
+ hosts = force_refresh(false, 0.0)
74
+ return hosts unless hosts.nil? || hosts.empty?
75
+
76
+ stored_topology || initial_host_list
77
+ end
78
+
79
+ # Forces monitor to fetch fresh topology.
80
+ # @param verify_writer [Boolean]
81
+ # @param timeout_sec [Float]
82
+ # @return [Array<HostInfo>, nil]
83
+ def force_refresh(verify_writer, timeout_sec)
84
+ unless @service_container.dialect_service.dialect_final?
85
+ logger.debug('force_refresh was called but the dialect must be finalized before starting a topology monitor. ' \
86
+ 'Returning initial host list.')
87
+ return initial_host_list
88
+ end
89
+
90
+ monitor = @service_container.monitor_service.run_if_absent(:cluster_topology, @cluster_id, @service_container) do |_sc|
91
+ Monitoring::ClusterTopologyMonitor.new(
92
+ service_container: @service_container,
93
+ cluster_id: @cluster_id,
94
+ instance_template: @instance_template,
95
+ topology_utils: @topology_utils,
96
+ monitoring_driver_props: @monitoring_driver_props,
97
+ monitoring_wrapper_props: @monitoring_wrapper_props
98
+ )
99
+ end
100
+ monitor.force_refresh(verify_writer, timeout_sec)
101
+ rescue Timeout::Error
102
+ nil
103
+ end
104
+
105
+ # Stops the topology monitor for this cluster.
106
+ def stop_monitor
107
+ @service_container.monitor_service.stop_and_remove(:cluster_topology, @cluster_id)
108
+ end
109
+
110
+ private
111
+
112
+ def stored_topology
113
+ @service_container.storage_service.get(TOPOLOGY_CACHE_NAME, @cluster_id, register_access: true)
114
+ end
115
+
116
+ def initial_host_list
117
+ [initial_host_info]
118
+ end
119
+
120
+ # --- Construction helpers ---
121
+
122
+ def build_instance_template(props)
123
+ pattern = PropertyDefinition::CLUSTER_INSTANCE_HOST_PATTERN.get(props)
124
+ if pattern
125
+ host, port = parse_host_port_pattern(pattern)
126
+ port ||= initial_host_info.port
127
+ HostInfo.new(host: host, port: port)
128
+ else
129
+ auto_pattern = Utils::RdsUtils.rds_instance_host_pattern(initial_host_info.host)
130
+ HostInfo.new(host: auto_pattern, port: initial_host_info.port)
131
+ end
132
+ end
133
+
134
+ def parse_host_port_pattern(pattern)
135
+ last_colon = pattern.rindex(':')
136
+ return [pattern, nil] if last_colon.nil?
137
+
138
+ possible_port = pattern[(last_colon + 1)..]
139
+ if possible_port.match?(/\A\d+\z/)
140
+ [pattern[0...last_colon], possible_port]
141
+ else
142
+ [pattern, nil]
143
+ end
144
+ end
145
+
146
+ # Splits prefixed overrides into driver-level and wrapper-level props.
147
+ # Driver overrides are merged onto base driver_props with defaults applied.
148
+ # @return Hash monitoring_driver_props
149
+ def build_monitoring_driver_props(prefixed_driver_props)
150
+ monitoring_driver_props = @service_container.connection_service.driver_props.dup
151
+
152
+ prefixed_driver_props.each do |key, value|
153
+ monitoring_driver_props[key] = value
154
+ end
155
+
156
+ monitoring_driver_props
157
+ end
158
+
159
+ # Driver overrides are merged onto base wrapper_props with defaults applied.
160
+ # @return Hash monitoring_wrapper_props
161
+ def build_monitoring_wrapper_props(prefixed_wrapper_props)
162
+ monitoring_wrapper_props = @service_container.connection_service.wrapper_props.dup
163
+
164
+ prefixed_wrapper_props.each do |key, value|
165
+ monitoring_wrapper_props[key] = value
166
+ end
167
+
168
+ monitoring_wrapper_props
169
+ end
170
+
171
+ def validate_host_pattern!(pattern)
172
+ raise Errors::AwsError, "Invalid cluster instance host pattern: '#{pattern}'" unless Utils::RdsUtils.dns_pattern_valid?(pattern)
173
+
174
+ url_type = Utils::RdsUtils.identify_rds_type(pattern)
175
+ if [Utils::RdsUrlType::RDS_PROXY, Utils::RdsUrlType::RDS_PROXY_ENDPOINT].include?(url_type)
176
+ raise Errors::AwsError, "cluster_instance_host_pattern is not supported for RDS Proxy: '#{pattern}'"
177
+ end
178
+
179
+ if url_type == Utils::RdsUrlType::RDS_CUSTOM_CLUSTER
180
+ raise Errors::AwsError, "cluster_instance_host_pattern is not supported for RDS Custom Clusters: '#{pattern}'"
181
+ end
182
+
183
+ return unless Utils::RdsUtils.region_typo?(pattern)
184
+
185
+ raise Errors::AwsError,
186
+ "cluster_instance_host_pattern '#{pattern}' contains an unknown or misspelled AWS region"
187
+ end
188
+
189
+ def register_monitor_type
190
+ @service_container.monitor_service.register_type(
191
+ :cluster_topology,
192
+ expiration_timeout_sec: MONITOR_EXPIRATION_TIMEOUT_SEC,
193
+ produced_data_type: TOPOLOGY_CACHE_NAME
194
+ )
195
+ end
196
+
197
+ def register_topology_cache
198
+ @service_container.storage_service.register(TOPOLOGY_CACHE_NAME, ttl: 300)
199
+ end
200
+
201
+ def initial_host_info
202
+ @service_container.connection_service.initial_host_info
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,110 @@
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 'logger'
18
+
19
+ module AwsAdvancedRubyDriverWrapper
20
+ # The value substituted for any redacted (sensitive) property value.
21
+ REDACTED = '***'
22
+
23
+ # Sensitive property markers. A property key is treated as secret when it
24
+ # equals one of these or contains one as a substring.
25
+ SECRET_PROPERTY_KEYS = %w[password token secret credential].freeze
26
+
27
+ class << self
28
+ # Returns the logger used by the wrapper. Defaults to a Logger writing to $stderr.
29
+ # Users can replace this with any object that responds to the standard Logger methods
30
+ # (debug, info, warn, error, fatal).
31
+ #
32
+ # @example Setting a custom logger
33
+ # AwsAdvancedRubyDriverWrapper.logger = Logger.new('wrapper.log')
34
+ #
35
+ # @example Using Rails logger
36
+ # AwsAdvancedRubyDriverWrapper.logger = Rails.logger
37
+ #
38
+ # @return [Logger]
39
+ attr_writer :logger
40
+
41
+ def logger
42
+ @logger ||= default_logger
43
+ end
44
+
45
+ # Returns a copy of the given properties with the values of any sensitive
46
+ # keys (password, token, secret, credential, or keys containing those
47
+ # substrings) replaced with a redaction marker. The original collection is
48
+ # never mutated. Use this whenever properties may be written to logs.
49
+ #
50
+ # Accepts a Hash, Concurrent::Map, or any object responding to #each_pair or
51
+ # #each_key/#[]. Returns a plain Hash so it is always safe to interpolate.
52
+ #
53
+ # @example
54
+ # logger.debug("connecting with #{AwsAdvancedRubyDriverWrapper.mask_properties(props)}")
55
+ #
56
+ # @param props [#each_pair, #to_h, nil] the properties to mask
57
+ # @param extra_secret_keys [Array<String, Symbol>] further property names to redact exactly, for
58
+ # properties whose name is configurable (such as the IAM token property)
59
+ # @return [Hash] a new hash with sensitive values redacted
60
+ def mask_properties(props, extra_secret_keys = [])
61
+ return {} if props.nil?
62
+
63
+ pairs =
64
+ if props.respond_to?(:each_pair)
65
+ props.each_pair
66
+ elsif props.respond_to?(:to_h)
67
+ props.to_h
68
+ else
69
+ return {}
70
+ end
71
+
72
+ extra = extra_secret_keys.compact.map { |name| name.to_s.downcase }
73
+ pairs.each_with_object({}) do |(key, value), masked|
74
+ masked[key] = secret_key?(key, extra) ? REDACTED : value
75
+ end
76
+ end
77
+
78
+ # @param extra_secret_keys [Array<String>] further lower-case property names to treat as secret
79
+ # @return [Boolean] whether the given property key is considered sensitive
80
+ def secret_key?(key, extra_secret_keys = [])
81
+ normalized = key.to_s.downcase
82
+ extra_secret_keys.include?(normalized) || SECRET_PROPERTY_KEYS.any? { |marker| normalized.include?(marker) }
83
+ end
84
+
85
+ private
86
+
87
+ def default_logger
88
+ logger = Logger.new($stderr)
89
+ logger.progname = 'AwsAdvancedRubyDriverWrapper'
90
+ logger.level = Logger::INFO
91
+ logger
92
+ end
93
+ end
94
+
95
+ # Include this module in any class that needs logging.
96
+ # Provides a private `logger` method that delegates to the module-level logger,
97
+ # and a private `mask_properties` helper for redacting sensitive values.
98
+ module Logging
99
+ private
100
+
101
+ def logger
102
+ AwsAdvancedRubyDriverWrapper.logger
103
+ end
104
+
105
+ # @see AwsAdvancedRubyDriverWrapper.mask_properties
106
+ def mask_properties(props, extra_secret_keys = [])
107
+ AwsAdvancedRubyDriverWrapper.mask_properties(props, extra_secret_keys)
108
+ end
109
+ end
110
+ end