aws_advanced_ruby_driver_wrapper 1.0.1 → 1.1.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 +4 -4
- data/CHANGELOG.md +32 -2
- data/README.md +115 -6
- data/THIRD-PARTY-LICENSES +70 -11
- data/aws_advanced_ruby_driver_wrapper.gemspec +9 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +17 -3
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter.rb +80 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +43 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +11 -4
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql2_driver_dialect.rb +129 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +9 -91
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +18 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/trilogy_driver_dialect.rb +118 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +16 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +10 -5
- data/lib/aws_advanced_ruby_driver_wrapper/errors/trilogy_error_handler.rb +127 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +1 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +1 -0
- data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +27 -9
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +115 -7
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/drop_blue_connections_marker.rb +84 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +3 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +7 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +68 -41
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +4 -2
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +5 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +7 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +6 -13
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +90 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +11 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +14 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +68 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/base_saml_auth_plugin.rb +266 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/federated_auth_plugin.rb +134 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/okta_auth_plugin.rb +113 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +30 -9
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +16 -2
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +6 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +13 -4
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +29 -6
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_mysql.sql +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_pg.sql +54 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +14 -0
- data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +41 -23
- data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +63 -1
- data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +3 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +20 -7
- data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +34 -8
- data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +80 -29
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +10 -2
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/trilogy.rb +167 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +25 -15
- data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +2 -2
- data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +13 -4
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +15 -31
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +55 -76
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_text.rb +215 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +11 -20
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +2 -3
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +21 -14
- data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +2 -1
- data/lib/aws_advanced_ruby_driver_wrapper/utils/saml_utils.rb +133 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +9 -5
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/null_telemetry.rb +89 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_context.rb +124 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_counter.rb +39 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_factory.rb +122 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_gauge.rb +36 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_const.rb +50 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_factory.rb +143 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +9 -2
- data/lib/aws_advanced_ruby_driver_wrapper/version.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper.rb +9 -2
- metadata +54 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3f6f4cf5575f7126636ad09c23b81a3feec7544b36c7fd3a1d13cb159f0978d
|
|
4
|
+
data.tar.gz: e5053d0035262786e689706ecc48788fd031c06b4144f2cc3e15e0dba2d44589
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c3bfe267a552d4542b4b89944c76f35442ffbe1a16fde107126660b8aa0e352f932353fba29e67029db860fda83aea0c3acace10c3997a4a50b7b0bc89d0652
|
|
7
|
+
data.tar.gz: fe7c1b9e226219d8740daa00f0f101004e3c869044cac2b7b950a8cf6447c6ebc9ac418c2fcc30ea3c86767d72cb9091ce18c587d19fbae4663d174fd20f98b5
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,35 @@ All notable changes to this project will be documented in this file.
|
|
|
3
3
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/#semantic-versioning-200).
|
|
5
5
|
|
|
6
|
+
## [1.1.0] - 2026-11-05
|
|
7
|
+
|
|
8
|
+
### :magic_wand: Added
|
|
9
|
+
- [Federated Authentication Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/federated-auth), which authenticates with Active Directory Federation Services (AD FS), exchanges the resulting SAML assertion for temporary AWS credentials via STS, and connects to the database with an RDS IAM authentication token. Enabled with the `federated_auth` plugin code ([PR #207](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/207)).
|
|
10
|
+
- [Okta Authentication Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/okta-auth), which uses the same SAML-to-STS flow as AD FS but against Okta, is also available via the `okta` plugin code ([PR #215](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/215)).
|
|
11
|
+
- [Telemetry](https://aws.github.io/aws-advanced-wrapper-docs/ruby/telemetry) through OpenTelemetry. With `enable_telemetry` set, the wrapper records traces of each wrapper call, the plugins it passes through, and the driver, plus failover, Blue/Green switchover, and authentication spans, and metrics such as failover and token fetch counts. Traces and metrics are sent wherever the application's OpenTelemetry SDK exports them. The OpenTelemetry gems are optional dependencies ([PR #220](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/220), [PR #225](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/225)).
|
|
12
|
+
- Support for the [`trilogy`](https://rubygems.org/gems/trilogy) MySQL driver, through the `WrapperTrilogyClient` connection class and the drop-in `aws_trilogy` ActiveRecord adapter. The KMS Encryption Plugin is not supported with `trilogy` ([PR #203](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/203)).
|
|
13
|
+
- The [Blue/Green Deployment plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/blue-green) now invalidates connections that were opened to the old blue environment before a switchover, controlled by the new `bg_drop_blue_connections` property (default `true`). Once a switchover is confirmed, each such connection is closed the next time it is used, so with the failover plugin enabled it fails over through Blue/Green routing and raises `FailoverSuccessError` (or `TransactionStateUnknownError` inside a transaction), and without failover the driver raises its closed-connection error ([PR #223](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/223)).
|
|
14
|
+
- AI assistant skills for the wrapper, in the repository under [`skills/`](https://github.com/aws/aws-advanced-ruby-driver-wrapper/tree/main/skills): a [configuration assistant](https://github.com/aws/aws-advanced-ruby-driver-wrapper/tree/main/skills/ruby-wrapper-configuration-assistant) that builds a working configuration through an interview, reviews existing configurations, and answers parameter and plugin questions, and a [troubleshooting assistant](https://github.com/aws/aws-advanced-ruby-driver-wrapper/tree/main/skills/ruby-wrapper-troubleshooting-assistant) that diagnoses errors and unexpected behavior and classifies the cause as configuration, environment, wrapper bug, or not the wrapper. Both are self-contained and grounded in the wrapper source and the official Ruby docs ([PR #214](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/214), [PR #219](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/219), [PR #233](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/233), [PR #237](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/237), [PR #239](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/239)).
|
|
15
|
+
|
|
16
|
+
### :crab: Changed
|
|
17
|
+
- Simplified the KMS Encryption Plugin's PostgreSQL trigger SQL to read the column's HMAC key from `key_storage` for every row. Re-run the trigger SQL from the [documentation](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/kms-encryption#postgresql-1) to update existing deployments ([PR #216](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/216)).
|
|
18
|
+
- The KMS Encryption Plugin's trigger SQL now ships with the gem and is stamped with its version, so deployed triggers can be checked against the version in use ([PR #218](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/218)).
|
|
19
|
+
- With `mysql2` (`WrapperMysql2Client` and the `aws_mysql2` ActiveRecord adapter), the failover plugin now fails over on a `read_timeout`, when MySQL 8.0.24+ disconnects a connection that exceeded `wait_timeout` (error 4031), and on a lost connection reported as error 2055 (`CR_SERVER_LOST_EXTENDED`), matching `trilogy`. Before, none of these triggered failover: a `read_timeout` raised `Mysql2::Error::TimeoutError` (`ActiveRecord::AdapterTimeout` under `aws_mysql2`), and errors 4031 and 2055 were raised as-is (`ActiveRecord::ConnectionFailed` under `aws_mysql2`, which ActiveRecord answered by reconnecting to the original endpoint and retrying queries it considers retryable). **Behavior change:** these errors now fail over and raise `FailoverSuccessError` (or `TransactionStateUnknownError` inside a transaction), which ActiveRecord does not retry. This includes:
|
|
20
|
+
- a query that runs longer than `read_timeout`. Set `read_timeout` higher than your slowest expected query.
|
|
21
|
+
- the first query on a pooled connection that sat idle longer than the server's `wait_timeout`. Raise `wait_timeout`, or have the pool reap idle connections sooner (for example with ActiveRecord's `idle_timeout`).
|
|
22
|
+
|
|
23
|
+
Lock wait timeouts (error 1205) still do not trigger failover ([PR #234](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/234)).
|
|
24
|
+
- Declared `bigdecimal` and `logger` as runtime dependencies, since Ruby no longer installs them by default from 3.4 (`bigdecimal`) and 4.0 (`logger`) on, and dropped the need for `base64` and the full `cgi` library. This keeps a bundle that does not otherwise include them, such as an app using the drivers without ActiveRecord, from failing to load the wrapper ([PR #224](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/224)).
|
|
25
|
+
|
|
26
|
+
### :bug: Fixed
|
|
27
|
+
- Fixed the Custom Endpoint Plugin signing its RDS API calls with the default credential chain instead of the configured `aws_credentials_provider`, so a custom endpoint could not be resolved in an account reachable only through the configured credentials ([PR #205](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/205)).
|
|
28
|
+
- Fixed an unknown host selection strategy being accepted at configuration time and only failing later during connection use. An invalid strategy is now rejected when the connection is set up ([PR #206](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/206)).
|
|
29
|
+
- Fixed `iam_access_token_property_name`, `cluster_id`, and `bgd_id` not accepting YAML-typed (non-string) values from `database.yml`, such as a numeric `cluster_id` ([PR #209](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/209)).
|
|
30
|
+
- Fixed the block form of `pg`'s `exec`, `query`, `exec_params`, and `exec_prepared` not working through `WrapperPgConnection`. The wrapper now yields the result to the block, clears it when the block returns, and returns the block's value, matching `pg` ([PR #221](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/221)).
|
|
31
|
+
- Fixed the cluster topology and custom endpoint monitors stopping when their stored data was read, which could leave the wrapper with a stale topology so failover could not find the new writer ([PR #226](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/226)).
|
|
32
|
+
- Fixed the KMS Encryption Plugin matching MySQL placeholders to the wrong encrypted columns when the statement contained comments, so values could be encrypted against the wrong column ([PR #227](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/227)).
|
|
33
|
+
- Fixed several ActiveRecord error-handling gaps: a `nil` connection is now recognized as a connection error; a `pg` IAM authentication failure is classified as a connection error rather than `ActiveRecord::NoDatabaseError`; `trilogy` schema errors are identified correctly; and `ping` and `close` now match the underlying driver's behavior ([PR #228](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/228)).
|
|
34
|
+
|
|
6
35
|
## [1.0.1] - 2026-10-07
|
|
7
36
|
|
|
8
37
|
### :bug: Fixed
|
|
@@ -35,5 +64,6 @@ The Amazon Web Services (AWS) Advanced Ruby Driver Wrapper allows an application
|
|
|
35
64
|
- [Initial Connection Strategy Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/initial-connection-strategy).
|
|
36
65
|
- [KMS Encryption Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/kms-encryption).
|
|
37
66
|
|
|
38
|
-
[1.0
|
|
39
|
-
[1.0.
|
|
67
|
+
[1.1.0]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/v1.1.0
|
|
68
|
+
[1.0.1]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/v1.0.1
|
|
69
|
+
[1.0.0]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/v1.0.0
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
The **AWS Advanced Ruby Driver Wrapper** is complementary to an existing Ruby database driver and aims to extend the functionality of the driver to enable applications to take full advantage of the features of clustered databases such as Amazon Aurora. In other words, the AWS Advanced Ruby Driver Wrapper does not connect directly to any database, but enables support of AWS and Aurora functionalities on top of an underlying Ruby driver of the user's choice. This approach enables service-specific enhancements without requiring users to change their workflow with their existing Ruby drivers and tooling.
|
|
6
6
|
|
|
7
|
-
The wrapper integrates with [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) by providing drop-in `aws_mysql2` and `aws_postgresql` adapters that sit on top of the community [`mysql2`](https://rubygems.org/gems/mysql2) and [`pg`](https://rubygems.org/gems/pg) drivers.
|
|
7
|
+
The wrapper integrates with [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) by providing drop-in `aws_mysql2`, `aws_trilogy` and `aws_postgresql` adapters that sit on top of the community [`mysql2`](https://rubygems.org/gems/mysql2), [`trilogy`](https://rubygems.org/gems/trilogy) and [`pg`](https://rubygems.org/gems/pg) drivers.
|
|
8
8
|
|
|
9
9
|
## About the Wrapper
|
|
10
10
|
|
|
@@ -54,10 +54,12 @@ Add this line to your application's Gemfile:
|
|
|
54
54
|
gem 'aws_advanced_ruby_driver_wrapper'
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
For MySQL users, also install the underlying
|
|
57
|
+
For MySQL users, also install one of the underlying drivers:
|
|
58
58
|
|
|
59
59
|
```ruby
|
|
60
60
|
gem 'mysql2'
|
|
61
|
+
# or
|
|
62
|
+
gem 'trilogy'
|
|
61
63
|
```
|
|
62
64
|
|
|
63
65
|
For PostgreSQL users, also install the underlying driver:
|
|
@@ -74,14 +76,17 @@ bundle install
|
|
|
74
76
|
|
|
75
77
|
## Getting Started
|
|
76
78
|
|
|
77
|
-
The wrapper registers
|
|
79
|
+
The wrapper registers three ActiveRecord adapters — `aws_mysql2`, `aws_trilogy` and `aws_postgresql` — that are drop-in replacements for the standard `mysql2`, `trilogy` and `postgresql` adapters.
|
|
78
80
|
|
|
79
81
|
Require the appropriate entry point for your database:
|
|
80
82
|
|
|
81
83
|
```ruby
|
|
82
|
-
# For MySQL
|
|
84
|
+
# For MySQL with mysql2
|
|
83
85
|
require 'aws_advanced_ruby_driver_wrapper/mysql'
|
|
84
86
|
|
|
87
|
+
# For MySQL with trilogy
|
|
88
|
+
require 'aws_advanced_ruby_driver_wrapper/trilogy'
|
|
89
|
+
|
|
85
90
|
# For PostgreSQL
|
|
86
91
|
require 'aws_advanced_ruby_driver_wrapper/postgresql'
|
|
87
92
|
```
|
|
@@ -89,7 +94,7 @@ require 'aws_advanced_ruby_driver_wrapper/postgresql'
|
|
|
89
94
|
Then set the adapter in your database configuration (for example, `config/database.yml` in a Rails application):
|
|
90
95
|
|
|
91
96
|
```yaml
|
|
92
|
-
# MySQL
|
|
97
|
+
# MySQL (use aws_trilogy with the trilogy driver)
|
|
93
98
|
production:
|
|
94
99
|
adapter: aws_mysql2
|
|
95
100
|
host: my-cluster.cluster-xxxx.us-east-1.rds.amazonaws.com
|
|
@@ -106,6 +111,105 @@ production:
|
|
|
106
111
|
password: <password>
|
|
107
112
|
```
|
|
108
113
|
|
|
114
|
+
This is a minimal configuration. To add failover tuning, IAM or Secrets Manager authentication, TLS, and other plugins for your deployment, see the [documentation](#documentation), or [let an AI assistant build the configuration with you](#configuring-the-wrapper-with-ai-tools).
|
|
115
|
+
|
|
116
|
+
### Configuring the Wrapper with AI Tools
|
|
117
|
+
|
|
118
|
+
If you use an AI assistant (Kiro, Cursor, Claude Code, GitHub Copilot, ChatGPT, Amazon Bedrock, etc.), you can give it the wrapper's configuration assistant skill to help build, review, or troubleshoot your wrapper configuration.
|
|
119
|
+
|
|
120
|
+
The skill is a single self-contained markdown file, [`skills/ruby-wrapper-configuration-assistant/SKILL.md`](./skills/ruby-wrapper-configuration-assistant/SKILL.md). It covers every plugin, parameter, default value, dialect, failover mode, and compatibility constraint, so the AI can answer configuration questions without access to the wrapper source. It follows the [Agent Skills](https://agentskills.io) format. It is about 65,000 tokens on Claude Opus 5.5 and Sonnet 5.5 (other models count tokens differently). How much of that you pay for depends on how you add it:
|
|
121
|
+
|
|
122
|
+
- **Tools that support Agent Skills** load only the skill's name and description (about 100 tokens) until a request needs the skill. They then load the full file, and it stays in context for the rest of that conversation.
|
|
123
|
+
- **A system prompt, or a file pasted into a chat,** sends the full file with every message.
|
|
124
|
+
|
|
125
|
+
Once the full file is in context, it is sent again with each message, so tools that cache prompts handle it most cheaply.
|
|
126
|
+
|
|
127
|
+
#### Quick start
|
|
128
|
+
|
|
129
|
+
1. Download or copy [`SKILL.md`](https://github.com/aws/aws-advanced-ruby-driver-wrapper/blob/v1.1.0/skills/ruby-wrapper-configuration-assistant/SKILL.md) from the latest release, or the whole `skills/ruby-wrapper-configuration-assistant` folder. The copy on `main` can describe changes that aren't released yet; it marks them `[Unreleased]`, and the AI won't recommend them for a released gem version.
|
|
130
|
+
2. Add it to your AI tool:
|
|
131
|
+
- **Tools that support Agent Skills** (Kiro, Cursor, Claude Code, GitHub Copilot in VS Code, and others): copy the `ruby-wrapper-configuration-assistant` folder (or create a folder with that name and save `SKILL.md` in it) into one of the tool's skills directories. The folder name must match the `name` field at the top of the file (`ruby-wrapper-configuration-assistant`), as the Agent Skills format requires; a tool may not load the skill if they differ.
|
|
132
|
+
|
|
133
|
+
| Tool | Project skills directory | User skills directory |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| Kiro | `.kiro/skills/` | `~/.kiro/skills/` |
|
|
136
|
+
| Cursor | `.cursor/skills/`, `.agents/skills/`, or `.claude/skills/` | `~/.cursor/skills/`, `~/.agents/skills/`, or `~/.claude/skills/` |
|
|
137
|
+
| Claude Code | `.claude/skills/` | `~/.claude/skills/` |
|
|
138
|
+
| GitHub Copilot in VS Code | `.github/skills/`, `.agents/skills/`, or `.claude/skills/` | `~/.copilot/skills/`, `~/.agents/skills/`, or `~/.claude/skills/` |
|
|
139
|
+
|
|
140
|
+
For example, to add the skill to a project for Claude Code:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
mkdir -p .claude/skills/ruby-wrapper-configuration-assistant
|
|
144
|
+
curl -fsSL -o .claude/skills/ruby-wrapper-configuration-assistant/SKILL.md \
|
|
145
|
+
https://raw.githubusercontent.com/aws/aws-advanced-ruby-driver-wrapper/v1.1.0/skills/ruby-wrapper-configuration-assistant/SKILL.md
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- **Claude Projects**: upload it as a project knowledge document. Claude reads project knowledge in full while it fits in the context window, but when a project's knowledge approaches that limit, Claude switches to searching it for passages that match each question, so the model may miss the instructions and cross-references the skill depends on. Keep the project's other knowledge small, or use a separate project.
|
|
149
|
+
- **ChatGPT custom GPT**: a custom GPT searches its knowledge files and passes the model only the passages that match each question, so the model may miss the instructions and cross-references the skill depends on. Paste the file into a plain chat instead (below).
|
|
150
|
+
- **Amazon Bedrock**: send the file as the system prompt of your `InvokeModel` or `Converse` request. Avoid attaching it to a Bedrock knowledge base: a knowledge base passes the model only the passages that match each question, so the model misses the instructions and cross-references the skill depends on.
|
|
151
|
+
- **Plain chat (ChatGPT, Claude, Gemini)**: paste it at the start of a new conversation, then ask your question. Start a new conversation for each new question: in a long conversation the pasted skill can be pushed out of the model's context, and ChatGPT drops the oldest messages first. In ChatGPT, the file is about 40,000 tokens, which is more than the Free plan's context window and leaves little room on the Go and Plus plans' Instant models, so choose a Thinking model in the model picker or use the Pro plan.
|
|
152
|
+
3. Ask the AI for help. It will interview you when it needs more details, or give you a configuration straight away if you ask it to skip the interview.
|
|
153
|
+
|
|
154
|
+
#### Example prompts
|
|
155
|
+
|
|
156
|
+
The simplest way to start:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
Help me configure the AWS Advanced Ruby Driver Wrapper for my Rails app.
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Skip the interview when you already know what you want:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
Give me a default config/database.yml for Rails on Aurora PostgreSQL with failover and IAM authentication.
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Review an existing configuration:
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
Review this database.yml entry and tell me what to change:
|
|
172
|
+
|
|
173
|
+
<paste your database.yml entry, or the Ruby code that opens the connection>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Diagnose a configuration error:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
My Rails app on aws_postgresql fails at startup with "The failover plugin is not compatible with RDS Proxy endpoints".
|
|
180
|
+
What's wrong with my database.yml?
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The skill targets wrapper version 1.0.1 and later. If it doesn't know something, it says so and points you to the [Ruby wrapper documentation](https://aws.github.io/aws-advanced-wrapper-docs/ruby/overview).
|
|
184
|
+
|
|
185
|
+
### Troubleshooting the Wrapper with AI Tools
|
|
186
|
+
|
|
187
|
+
A second skill, the troubleshooting assistant, helps an AI assistant find out why the wrapper isn't doing what you expect: installation and load errors, connection setup errors, IAM, Secrets Manager, AD FS and Okta authentication failures, failover that doesn't happen or fails, Active Record integration problems, the trilogy driver, Blue/Green, custom endpoints, Global Database, KMS encryption, telemetry, and performance. It works out whether the cause is your configuration, your environment (network, AWS permissions, TLS), a wrapper bug, or something outside the wrapper, helps you narrow it down and read the wrapper's logs, and drafts an issue report when the problem needs one.
|
|
188
|
+
|
|
189
|
+
The skill is [`skills/ruby-wrapper-troubleshooting-assistant/SKILL.md`](https://github.com/aws/aws-advanced-ruby-driver-wrapper/blob/v1.1.0/skills/ruby-wrapper-troubleshooting-assistant/SKILL.md) (link to the latest release), about 30,000 tokens on Claude Opus 5.5 and Sonnet 5.5 (about 20,000 in ChatGPT). The two skills are independent: install either one or both. Add it to your AI tool the same way as the configuration assistant (see [Quick start](#quick-start)), using the folder name `ruby-wrapper-troubleshooting-assistant`. For example, for Claude Code:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
mkdir -p .claude/skills/ruby-wrapper-troubleshooting-assistant
|
|
193
|
+
curl -fsSL -o .claude/skills/ruby-wrapper-troubleshooting-assistant/SKILL.md \
|
|
194
|
+
https://raw.githubusercontent.com/aws/aws-advanced-ruby-driver-wrapper/v1.1.0/skills/ruby-wrapper-troubleshooting-assistant/SKILL.md
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Then describe the problem, and include the error message and backtrace if you have one. Remove passwords and other secrets from anything you paste.
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
My Rails app on Aurora PostgreSQL gets AwsAdvancedRubyDriverWrapper::Errors::FailoverSuccessError
|
|
201
|
+
a few times a day, but there's no failover in the RDS events. What's going on?
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
Failover fails with "The request to discover the new topology timed out or was unsuccessful".
|
|
206
|
+
Here are the wrapper's debug logs:
|
|
207
|
+
|
|
208
|
+
<paste the logs>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The skill targets wrapper version 1.0.1 and later.
|
|
212
|
+
|
|
109
213
|
## Documentation
|
|
110
214
|
|
|
111
215
|
Technical documentation regarding the functionality of the AWS Advanced Ruby Driver Wrapper is published at the [AWS Advanced Wrapper documentation site](https://aws.github.io/aws-advanced-wrapper-docs/ruby/overview). Since the wrapper requires an underlying Ruby driver, please refer to the individual driver's documentation for driver-specific information.
|
|
@@ -128,6 +232,11 @@ Technical documentation regarding the functionality of the AWS Advanced Ruby Dri
|
|
|
128
232
|
|
|
129
233
|
### Known Limitations
|
|
130
234
|
|
|
235
|
+
#### Trilogy MySQL Driver
|
|
236
|
+
|
|
237
|
+
- The KMS Encryption Plugin is not supported with `trilogy`, which has no prepared statements, so a bind parameter could only reach the server in plaintext. The plugin refuses to start on a `trilogy` connection.
|
|
238
|
+
- To authenticate with an IAM token, set `enable_cleartext_plugin: true` (and `ssl_mode`), since `trilogy` only sends the token with `mysql_clear_password` when that option is set.
|
|
239
|
+
|
|
131
240
|
#### Amazon RDS Blue/Green Deployments
|
|
132
241
|
|
|
133
242
|
Support for Blue/Green deployments using the wrapper requires specific metadata tables. Please refer to the plugin documentation for the supported database engine versions.
|
|
@@ -137,7 +246,7 @@ Support for Blue/Green deployments using the wrapper requires specific metadata
|
|
|
137
246
|
If you encounter a bug with the AWS Advanced Ruby Driver Wrapper, we would like to hear about it.
|
|
138
247
|
Please search the [existing issues](https://github.com/aws/aws-advanced-ruby-driver-wrapper/issues) to see if others are also experiencing the issue before reporting the problem in a new issue. GitHub issues are intended for bug reports and feature requests.
|
|
139
248
|
|
|
140
|
-
When opening a new issue, please fill in all required fields in the issue template to help expedite the investigation process.
|
|
249
|
+
When opening a new issue, please fill in all required fields in the issue template to help expedite the investigation process. The [troubleshooting assistant skill](#troubleshooting-the-wrapper-with-ai-tools) can help you find the cause first, and draft the issue if it turns out to be a bug.
|
|
141
250
|
|
|
142
251
|
For all other questions, please use [GitHub discussions](https://github.com/aws/aws-advanced-ruby-driver-wrapper/discussions).
|
|
143
252
|
|
data/THIRD-PARTY-LICENSES
CHANGED
|
@@ -3,10 +3,10 @@ following third-party software. The applicable licenses and notices are
|
|
|
3
3
|
reproduced below. Each dependency remains under its own license; nothing in
|
|
4
4
|
this file modifies those terms.
|
|
5
5
|
|
|
6
|
-
The underlying database drivers (pg, mysql2), ActiveRecord, pg_query,
|
|
7
|
-
AWS SDK gems are optional dependencies that are
|
|
8
|
-
they are listed here because the wrapper is
|
|
9
|
-
them.
|
|
6
|
+
The underlying database drivers (pg, mysql2, trilogy), ActiveRecord, pg_query,
|
|
7
|
+
the OpenTelemetry gems, and the AWS SDK gems are optional dependencies that are
|
|
8
|
+
installed by the user as needed; they are listed here because the wrapper is
|
|
9
|
+
designed to load and run on top of them.
|
|
10
10
|
|
|
11
11
|
===============================================================================
|
|
12
12
|
|
|
@@ -40,6 +40,19 @@ SOFTWARE.
|
|
|
40
40
|
|
|
41
41
|
-----------
|
|
42
42
|
|
|
43
|
+
The following Ruby gems are required runtime dependencies of this product.
|
|
44
|
+
Ruby no longer installs them by default from Ruby 3.4 (bigdecimal) and 4.0
|
|
45
|
+
(logger) on, so the wrapper declares them explicitly:
|
|
46
|
+
|
|
47
|
+
- bigdecimal@4.1.3
|
|
48
|
+
- logger@1.7.0
|
|
49
|
+
|
|
50
|
+
These packages are each distributed under the same Ruby license reproduced
|
|
51
|
+
below for the `pg` gem (the Ruby license or, at your option, the 2-clause
|
|
52
|
+
BSDL).
|
|
53
|
+
|
|
54
|
+
-----------
|
|
55
|
+
|
|
43
56
|
The following Ruby gem may be used with this product (ActiveRecord adapters):
|
|
44
57
|
|
|
45
58
|
- activerecord@8.1.4
|
|
@@ -131,9 +144,41 @@ SOFTWARE.
|
|
|
131
144
|
|
|
132
145
|
-----------
|
|
133
146
|
|
|
147
|
+
The following Ruby gem may be used with this product (alternative MySQL driver;
|
|
148
|
+
the KMS Encryption plugin is not supported with trilogy):
|
|
149
|
+
|
|
150
|
+
- trilogy@2.13.2
|
|
151
|
+
|
|
152
|
+
This package contains the following license and notice below:
|
|
153
|
+
|
|
154
|
+
Copyright (c) 2012-2021 GitHub, Inc.
|
|
155
|
+
|
|
156
|
+
Permission is hereby granted, free of charge, to any person
|
|
157
|
+
obtaining a copy of this software and associated documentation
|
|
158
|
+
files (the "Software"), to deal in the Software without
|
|
159
|
+
restriction, including without limitation the rights to use,
|
|
160
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
161
|
+
copies of the Software, and to permit persons to whom the
|
|
162
|
+
Software is furnished to do so, subject to the following
|
|
163
|
+
conditions:
|
|
164
|
+
|
|
165
|
+
The above copyright notice and this permission notice shall be
|
|
166
|
+
included in all copies or substantial portions of the Software.
|
|
167
|
+
|
|
168
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
169
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
170
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
171
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
172
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
173
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
174
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
175
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
176
|
+
|
|
177
|
+
-----------
|
|
178
|
+
|
|
134
179
|
The following Ruby gem may be used with this product (PostgreSQL driver):
|
|
135
180
|
|
|
136
|
-
- pg@1.
|
|
181
|
+
- pg@1.7.0
|
|
137
182
|
|
|
138
183
|
This package contains the following license and notice below:
|
|
139
184
|
|
|
@@ -224,7 +269,7 @@ SUCH DAMAGE.
|
|
|
224
269
|
The following Ruby gem may be used with this product (SQL statement parsing
|
|
225
270
|
for the KMS Encryption plugin):
|
|
226
271
|
|
|
227
|
-
- pg_query@6.2.
|
|
272
|
+
- pg_query@6.2.5
|
|
228
273
|
|
|
229
274
|
This package contains the following license and notice below:
|
|
230
275
|
|
|
@@ -259,13 +304,27 @@ POSSIBILITY OF SUCH DAMAGE.
|
|
|
259
304
|
|
|
260
305
|
-----------
|
|
261
306
|
|
|
307
|
+
The following OpenTelemetry for Ruby gems may be used with this product
|
|
308
|
+
(telemetry, when `enable_telemetry` is set). The wrapper loads these API gems;
|
|
309
|
+
the OpenTelemetry SDK and exporters that actually emit the traces and metrics
|
|
310
|
+
are supplied by the application:
|
|
311
|
+
|
|
312
|
+
- opentelemetry-api@1.11.1
|
|
313
|
+
- opentelemetry-metrics-api@0.10.0
|
|
314
|
+
|
|
315
|
+
These packages are each licensed under the Apache License, Version 2.0,
|
|
316
|
+
reproduced below (following the AWS SDK gems).
|
|
317
|
+
|
|
318
|
+
-----------
|
|
319
|
+
|
|
262
320
|
The following AWS SDK for Ruby gems may be used with this product (AWS IAM
|
|
263
|
-
Authentication, AWS Secrets Manager, Custom Endpoint,
|
|
264
|
-
plugins):
|
|
321
|
+
Authentication, AWS Secrets Manager, Custom Endpoint, Federated Authentication,
|
|
322
|
+
Okta Authentication, and KMS Encryption plugins):
|
|
265
323
|
|
|
266
|
-
- aws-sdk-
|
|
267
|
-
- aws-sdk-
|
|
268
|
-
- aws-sdk-
|
|
324
|
+
- aws-sdk-core@3.263.0
|
|
325
|
+
- aws-sdk-kms@1.138.0
|
|
326
|
+
- aws-sdk-rds@1.329.0
|
|
327
|
+
- aws-sdk-secretsmanager@1.141.0
|
|
269
328
|
|
|
270
329
|
These packages are each licensed under the Apache License, Version 2.0,
|
|
271
330
|
reproduced below:
|
|
@@ -53,7 +53,12 @@ Gem::Specification.new do |spec|
|
|
|
53
53
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
54
54
|
spec.require_paths = ['lib']
|
|
55
55
|
|
|
56
|
+
# The wrapper requires bigdecimal and logger, and Ruby no longer installs them by default from 3.4
|
|
57
|
+
# (bigdecimal) and 4.0 (logger) on. Declaring them keeps a bundle that does not otherwise include
|
|
58
|
+
# them, such as an app using the drivers without Active Record, from failing to load the wrapper.
|
|
59
|
+
spec.add_dependency 'bigdecimal'
|
|
56
60
|
spec.add_dependency 'concurrent-ruby', '~> 1.3', '>= 1.3.7'
|
|
61
|
+
spec.add_dependency 'logger'
|
|
57
62
|
|
|
58
63
|
spec.post_install_message = <<~MSG
|
|
59
64
|
═══════════════════════════════════════════════════════════════
|
|
@@ -63,6 +68,10 @@ Gem::Specification.new do |spec|
|
|
|
63
68
|
gem install mysql2
|
|
64
69
|
require 'aws_advanced_ruby_driver_wrapper/mysql'
|
|
65
70
|
|
|
71
|
+
To use with MySQL through trilogy:
|
|
72
|
+
gem install trilogy
|
|
73
|
+
require 'aws_advanced_ruby_driver_wrapper/trilogy'
|
|
74
|
+
|
|
66
75
|
To use with PostgreSQL:
|
|
67
76
|
gem install pg
|
|
68
77
|
require 'aws_advanced_ruby_driver_wrapper/postgresql'
|
|
@@ -63,23 +63,37 @@ module ActiveRecord
|
|
|
63
63
|
superclass.native_database_types.merge(datetime: NATIVE_DATABASE_TYPES[datetime_type])
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
# SQLSTATEs and FATAL-message signals for an authentication/authorization rejection (invalid
|
|
67
|
+
# password, PAM failure, pg_hba.conf rejection). A failed *connect* usually carries no result, so
|
|
68
|
+
# the message text is the reliable signal and the SQLSTATE is only a bonus when one is present.
|
|
69
|
+
AUTH_REJECTION_SQLSTATES = %w[28P01 28000].freeze
|
|
70
|
+
AUTH_REJECTION_MESSAGE = /password authentication failed|PAM authentication failed|pg_hba\.conf/
|
|
71
|
+
|
|
66
72
|
# Note that this config includes wrapper properties.
|
|
67
73
|
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
74
|
+
# Mirrors the parent PostgreSQLAdapter.new_client so ActiveRecord can tell a missing database
|
|
75
|
+
# (which db:prepare creates) or rejected credentials from other failures.
|
|
70
76
|
def self.new_client(config)
|
|
71
77
|
AwsAdvancedRubyDriverWrapper::WrapperPgConnection.new(**config)
|
|
72
78
|
rescue ::PG::Error => e
|
|
73
79
|
dbname, user, host = config.values_at(:dbname, :user, :host)
|
|
74
80
|
# The postgres maintenance database always exists, so a failure there is not a missing database.
|
|
75
81
|
raise ActiveRecord::ConnectionNotEstablished, e.message if dbname == 'postgres'
|
|
76
|
-
raise ActiveRecord::NoDatabaseError.db_error(dbname) if dbname && e.message.include?(dbname)
|
|
82
|
+
raise ActiveRecord::NoDatabaseError.db_error(dbname) if dbname && e.message.include?(dbname) && !auth_rejection?(e)
|
|
77
83
|
raise ActiveRecord::DatabaseConnectionError.username_error(user) if user && e.message.include?(user)
|
|
78
84
|
raise ActiveRecord::DatabaseConnectionError.hostname_error(host) if host && e.message.include?(host)
|
|
79
85
|
|
|
80
86
|
raise ActiveRecord::ConnectionNotEstablished, e.message
|
|
81
87
|
end
|
|
82
88
|
|
|
89
|
+
# @return [Boolean] whether the PG error is an authentication/authorization rejection, by SQLSTATE
|
|
90
|
+
# when the error carries a result and otherwise by its canonical FATAL text.
|
|
91
|
+
def self.auth_rejection?(error)
|
|
92
|
+
sqlstate = error.result&.error_field(PG::PG_DIAG_SQLSTATE)
|
|
93
|
+
AUTH_REJECTION_SQLSTATES.include?(sqlstate) || error.message.match?(AUTH_REJECTION_MESSAGE)
|
|
94
|
+
end
|
|
95
|
+
private_class_method :auth_rejection?
|
|
96
|
+
|
|
83
97
|
def connect
|
|
84
98
|
@connection_broken = false
|
|
85
99
|
# Override @connection_parameters with the full config so the parent's
|
|
@@ -0,0 +1,80 @@
|
|
|
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 'active_record/connection_adapters/trilogy_adapter'
|
|
18
|
+
require_relative '../trilogy'
|
|
19
|
+
require_relative '../errors'
|
|
20
|
+
require_relative 'type_adapter_alias'
|
|
21
|
+
require_relative 'aws_connection_handler'
|
|
22
|
+
|
|
23
|
+
module ActiveRecord
|
|
24
|
+
module ConnectionAdapters
|
|
25
|
+
class AwsTrilogyAdapter < TrilogyAdapter
|
|
26
|
+
# Connects as the parent adapter does, through the wrapper instead of trilogy itself: the ssl_mode
|
|
27
|
+
# name is turned into the constant trilogy reads, and the whole config is passed on, since the
|
|
28
|
+
# wrapper takes its own properties out and trilogy ignores the ActiveRecord-only keys.
|
|
29
|
+
#
|
|
30
|
+
# Translates connection errors the same way the parent adapter does, so ActiveRecord can tell a
|
|
31
|
+
# missing database (which db:prepare creates) or rejected credentials from other failures.
|
|
32
|
+
def self.new_client(config)
|
|
33
|
+
config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
|
|
34
|
+
AwsAdvancedRubyDriverWrapper::WrapperTrilogyClient.new(config)
|
|
35
|
+
rescue ::Trilogy::Error => e
|
|
36
|
+
raise translate_connect_error(config, e)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def connect
|
|
40
|
+
@connection_broken = false
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reconnect
|
|
45
|
+
@connection_broken = false
|
|
46
|
+
super
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def active?
|
|
50
|
+
return false if @connection_broken
|
|
51
|
+
|
|
52
|
+
super
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def translate_exception(exception, message:, sql:, binds:)
|
|
56
|
+
return super unless exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::AwsError)
|
|
57
|
+
|
|
58
|
+
if exception.needs_reconfiguration
|
|
59
|
+
# The wrapper has reconnected this connection object to a new physical connection, where the
|
|
60
|
+
# session ActiveRecord configured on the old one does not exist. Forget what was cached about
|
|
61
|
+
# that connection and configure the new one.
|
|
62
|
+
clear_cache!(new_connection: true)
|
|
63
|
+
configure_connection
|
|
64
|
+
exception
|
|
65
|
+
elsif exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::FailoverFailedError)
|
|
66
|
+
@connection_broken = true
|
|
67
|
+
ActiveRecord::ConnectionFailed.new(message, sql:, binds:, connection_pool: @pool)
|
|
68
|
+
else
|
|
69
|
+
exception
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
ActiveRecord::ConnectionAdapters.register(
|
|
77
|
+
'aws_trilogy',
|
|
78
|
+
'ActiveRecord::ConnectionAdapters::AwsTrilogyAdapter',
|
|
79
|
+
'aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter'
|
|
80
|
+
)
|
|
@@ -37,7 +37,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
37
37
|
# type explicitly registered for :aws_postgresql is normalized to :postgresql and so also applies
|
|
38
38
|
# to the plain postgresql connections (and vice versa). This is documented in the CHANGELOG.
|
|
39
39
|
module TypeAdapterAlias
|
|
40
|
-
ADAPTER_ALIASES = { aws_postgresql: :postgresql, aws_mysql2: :mysql2 }.freeze
|
|
40
|
+
ADAPTER_ALIASES = { aws_postgresql: :postgresql, aws_mysql2: :mysql2, aws_trilogy: :trilogy }.freeze
|
|
41
41
|
|
|
42
42
|
# Prepended onto ActiveRecord::Type::AdapterSpecificRegistry. Normalizing the adapter in lookup
|
|
43
43
|
# covers both the framework path and a direct Type.lookup(..., adapter: :aws_postgresql); any
|
|
@@ -33,6 +33,17 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
33
33
|
|
|
34
34
|
DEFAULT_MONITORING_TIMEOUT_SEC = 5
|
|
35
35
|
|
|
36
|
+
# @return [String] the name of the Ruby driver gem this dialect drives
|
|
37
|
+
def name
|
|
38
|
+
raise NotImplementedError
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# The database engine the driver talks to, which decides the database dialects that apply.
|
|
42
|
+
# @return [Symbol] +:mysql+ or +:postgresql+
|
|
43
|
+
def database_engine
|
|
44
|
+
raise NotImplementedError
|
|
45
|
+
end
|
|
46
|
+
|
|
36
47
|
def connect(host_info, config)
|
|
37
48
|
raise NotImplementedError
|
|
38
49
|
end
|
|
@@ -138,6 +149,29 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
138
149
|
:user
|
|
139
150
|
end
|
|
140
151
|
|
|
152
|
+
# Returns the property key the underlying driver expects for the TLS CA certificate file.
|
|
153
|
+
# Used by Blue/Green substitute routing for drivers that overload the host for both the socket
|
|
154
|
+
# address and the TLS server name (mysql2, trilogy): it tells whether TLS is active before
|
|
155
|
+
# deciding to connect by hostname rather than raw IP, avoiding a certificate-name mismatch.
|
|
156
|
+
# Drivers that can pin the socket separately (see #props_pinned_to_ip) do not use this.
|
|
157
|
+
# mysql2 names it +:sslca+ (the default); override where it differs (trilogy uses +:ssl_ca+).
|
|
158
|
+
def tls_ca_property_key
|
|
159
|
+
:sslca
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Blue/Green substitute routing must connect to a specific instance IP — so a DNS lookup during
|
|
163
|
+
# the switchover window cannot resolve to the old instance — while still presenting the original
|
|
164
|
+
# hostname for TLS certificate verification and IAM token generation. A driver that can pin the
|
|
165
|
+
# socket address separately from the TLS/auth server name returns a copy of +driver_props+ that
|
|
166
|
+
# connects to +ip+ but keeps the hostname for verification; a driver that overloads the host for
|
|
167
|
+
# both returns +nil+, and the routing falls back to the #tls_ca_property_key hostname check.
|
|
168
|
+
# @param driver_props [Hash]
|
|
169
|
+
# @param ip [String] the instance IP to pin the socket to
|
|
170
|
+
# @return [Hash, nil] props pinned to +ip+, or +nil+ when the driver cannot split socket from TLS name
|
|
171
|
+
def props_pinned_to_ip(_driver_props, _ip)
|
|
172
|
+
nil
|
|
173
|
+
end
|
|
174
|
+
|
|
141
175
|
# Applies default socket/connect timeouts to monitoring connection driver props.
|
|
142
176
|
# These ensure that a query or close on a dead connection raises a timeout error
|
|
143
177
|
# rather than hanging indefinitely or segfaulting.
|
|
@@ -154,6 +188,15 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
154
188
|
def reported_in_transaction(_connection)
|
|
155
189
|
nil
|
|
156
190
|
end
|
|
191
|
+
|
|
192
|
+
# The server version that decides which versioned /*!80023 ... */ executable comments the server
|
|
193
|
+
# runs, as MySQL numbers it (8.0.39 is 80039). Only MySQL has executable comments.
|
|
194
|
+
# @param connection [Object]
|
|
195
|
+
# @return [Integer, nil] nil when the driver's SQL has no executable comments, or the version
|
|
196
|
+
# cannot be read
|
|
197
|
+
def executable_comment_version(_connection)
|
|
198
|
+
nil
|
|
199
|
+
end
|
|
157
200
|
end
|
|
158
201
|
end
|
|
159
202
|
end
|
|
@@ -14,26 +14,33 @@
|
|
|
14
14
|
# See the License for the specific language governing permissions and
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
|
|
17
|
-
require_relative '
|
|
17
|
+
require_relative 'mysql2_driver_dialect'
|
|
18
18
|
require_relative 'pg_driver_dialect'
|
|
19
|
+
require_relative 'trilogy_driver_dialect'
|
|
19
20
|
require_relative '../errors'
|
|
20
21
|
require_relative '../errors/mysql_error_handler'
|
|
21
22
|
require_relative '../errors/pg_error_handler'
|
|
23
|
+
require_relative '../errors/trilogy_error_handler'
|
|
22
24
|
|
|
23
25
|
module AwsAdvancedRubyDriverWrapper
|
|
24
26
|
module DriverDialects
|
|
25
27
|
module DriverDialectManager
|
|
26
|
-
|
|
28
|
+
MYSQL2_DIALECT = Mysql2DriverDialect.new.freeze
|
|
27
29
|
PG_DIALECT = PgDriverDialect.new.freeze
|
|
30
|
+
TRILOGY_DIALECT = TrilogyDriverDialect.new.freeze
|
|
28
31
|
|
|
29
32
|
REGISTRY = {
|
|
30
33
|
mysql2: {
|
|
31
|
-
driver_dialect:
|
|
32
|
-
error_handler: Errors::MysqlErrorHandler.new(
|
|
34
|
+
driver_dialect: MYSQL2_DIALECT,
|
|
35
|
+
error_handler: Errors::MysqlErrorHandler.new(MYSQL2_DIALECT)
|
|
33
36
|
},
|
|
34
37
|
postgresql: {
|
|
35
38
|
driver_dialect: PG_DIALECT,
|
|
36
39
|
error_handler: Errors::PgErrorHandler.new(PG_DIALECT)
|
|
40
|
+
},
|
|
41
|
+
trilogy: {
|
|
42
|
+
driver_dialect: TRILOGY_DIALECT,
|
|
43
|
+
error_handler: Errors::TrilogyErrorHandler.new(TRILOGY_DIALECT)
|
|
37
44
|
}
|
|
38
45
|
}.freeze
|
|
39
46
|
|