active_postgres 0.9.7 → 0.9.8
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 +7 -0
- data/README.md +6 -0
- data/lib/active_postgres/components/repmgr.rb +11 -9
- data/lib/active_postgres/configuration/node_identity.rb +22 -0
- data/lib/active_postgres/configuration.rb +4 -0
- data/lib/active_postgres/version.rb +1 -1
- data/templates/repmgr.conf.erb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c3d6f986ee2ac96f5cdd8b69541a5acae87733f506b10efb94c1046082b990a9
|
|
4
|
+
data.tar.gz: f64bb049c6601cf853de16c6cfeff8293ebb06d622db9633330298f02ef82135
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b07c93095ab642d39d6d658e93ef82c7ca993a30cf06b3f320d02e20dc5f45a546ffcdb2196f5bae0d1ab2051fb3a453a0a445e3e3f49b89ec1e3be9ee19f042
|
|
7
|
+
data.tar.gz: aeae944d32c7ee5f661470eaee9f66c01ef47c1bb4f578bbae0fd8d3e50f81044d24ddf49f85304a5aa6437de207aa22600cd3cc6cf7167713c5f87204e3cee9
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.9.8 - 2026-10-02
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Support explicit node IDs so repmgr identities survive primary changes and standby reordering.
|
|
15
|
+
- Reject duplicate or invalid node IDs before deployment.
|
|
16
|
+
|
|
10
17
|
## 0.9.7 - 2026-09-01
|
|
11
18
|
|
|
12
19
|
### Added
|
data/README.md
CHANGED
|
@@ -76,6 +76,12 @@ manual-promotion while the ordinary standby retains automatic failover.
|
|
|
76
76
|
settings before repmgr registration, avoiding a full base-backup stream from
|
|
77
77
|
the primary. The `pgbackrest` component must be enabled.
|
|
78
78
|
|
|
79
|
+
Set a unique positive integer `node_id` on every primary and standby entry
|
|
80
|
+
before permanently changing their roles or reordering standbys. Match the
|
|
81
|
+
existing IDs in `repmgr cluster show`, and keep each ID with its host after a
|
|
82
|
+
switchover. Without explicit IDs, the primary defaults to 1 and standbys use
|
|
83
|
+
their list position starting at 2. Duplicate or invalid IDs are rejected.
|
|
84
|
+
|
|
79
85
|
Add credentials (`rails credentials:edit`):
|
|
80
86
|
|
|
81
87
|
```yaml
|
|
@@ -28,7 +28,7 @@ module ActivePostgres
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def uninstall_from(host)
|
|
31
|
-
node_id =
|
|
31
|
+
node_id = config.node_id_for(host)
|
|
32
32
|
|
|
33
33
|
ssh_executor.execute_on_host(host) do
|
|
34
34
|
cluster_output = begin
|
|
@@ -98,6 +98,7 @@ module ActivePostgres
|
|
|
98
98
|
puts ' Setting up primary with repmgr...'
|
|
99
99
|
|
|
100
100
|
host = config.primary_host
|
|
101
|
+
primary_node_id = config.node_id_for(host)
|
|
101
102
|
repmgr_config = config.repmgr_config_for(host)
|
|
102
103
|
version = config.version
|
|
103
104
|
repmgr_password = normalize_repmgr_password(secrets.resolve('repmgr_password'))
|
|
@@ -208,7 +209,7 @@ module ActivePostgres
|
|
|
208
209
|
unless cluster_show&.match?(/primary/i)
|
|
209
210
|
# Fallback: verify via repmgr metadata in the repmgr database
|
|
210
211
|
db_check = executor.run_sql_on_backend(self,
|
|
211
|
-
|
|
212
|
+
"SELECT type FROM repmgr.nodes WHERE node_id = #{primary_node_id};",
|
|
212
213
|
postgres_user: 'postgres',
|
|
213
214
|
database: repmgr_db,
|
|
214
215
|
tuples_only: true,
|
|
@@ -250,7 +251,7 @@ module ActivePostgres
|
|
|
250
251
|
_ = repmgr_config
|
|
251
252
|
_ = secrets_obj
|
|
252
253
|
|
|
253
|
-
node_id = config.
|
|
254
|
+
node_id = config.node_id_for(standby_host)
|
|
254
255
|
repmgr_password = normalize_repmgr_password(secrets_obj.resolve('repmgr_password'))
|
|
255
256
|
replication_password = normalize_replication_password(secrets_obj.resolve('replication_password'))
|
|
256
257
|
if replication_user == repmgr_user && replication_password != repmgr_password
|
|
@@ -679,6 +680,7 @@ module ActivePostgres
|
|
|
679
680
|
puts 'Verifying PostgreSQL HA cluster health...'
|
|
680
681
|
|
|
681
682
|
primary_host = config.primary_host
|
|
683
|
+
primary_node_id = config.node_id_for(primary_host)
|
|
682
684
|
standby_hosts = config.standby_hosts
|
|
683
685
|
version = config.version
|
|
684
686
|
postgres_user = config.postgres_user
|
|
@@ -709,12 +711,12 @@ module ActivePostgres
|
|
|
709
711
|
cluster_output = capture(:sudo, '-u', 'postgres',
|
|
710
712
|
'repmgr', '-f', '/etc/repmgr.conf', 'cluster', 'show',
|
|
711
713
|
raise_on_non_zero_exit: false).to_s
|
|
712
|
-
#
|
|
713
|
-
if cluster_output.match?(/\s
|
|
714
|
+
# Check the configured node identity, which survives role changes.
|
|
715
|
+
if cluster_output.match?(/\s+#{primary_node_id}\s+\|.*primary.*\*\s+running/i)
|
|
714
716
|
info '✓ Primary is registered with repmgr'
|
|
715
717
|
else
|
|
716
718
|
db_check = executor.run_sql_on_backend(self,
|
|
717
|
-
|
|
719
|
+
"SELECT type FROM repmgr.nodes WHERE node_id = #{primary_node_id} AND active IS TRUE;",
|
|
718
720
|
postgres_user: postgres_user,
|
|
719
721
|
database: repmgr_db,
|
|
720
722
|
tuples_only: true,
|
|
@@ -951,7 +953,7 @@ module ActivePostgres
|
|
|
951
953
|
|
|
952
954
|
def ensure_primary_registered
|
|
953
955
|
host = config.primary_host
|
|
954
|
-
config.
|
|
956
|
+
primary_node_id = config.node_id_for(host)
|
|
955
957
|
is_registered = false
|
|
956
958
|
|
|
957
959
|
ssh_executor.execute_on_host(host) do
|
|
@@ -965,8 +967,8 @@ module ActivePostgres
|
|
|
965
967
|
''
|
|
966
968
|
end
|
|
967
969
|
|
|
968
|
-
if cluster_output.
|
|
969
|
-
info
|
|
970
|
+
if cluster_output.match?(/\b#{primary_node_id}\s+\|.*primary/)
|
|
971
|
+
info "✓ Primary is registered (node_id=#{primary_node_id})"
|
|
970
972
|
else
|
|
971
973
|
warn "⚠ Primary not found in cluster, assuming it's registered"
|
|
972
974
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ActivePostgres
|
|
2
|
+
class Configuration
|
|
3
|
+
module NodeIdentity
|
|
4
|
+
def node_id_for(host)
|
|
5
|
+
node = node_config_for(host)
|
|
6
|
+
raise Error, "Unknown PostgreSQL host: #{host}" unless node
|
|
7
|
+
|
|
8
|
+
value = node.fetch('node_id') { host == primary_host ? 1 : standby_hosts.index(host) + 2 }
|
|
9
|
+
raise Error, "node_id for #{host} must be a positive 32-bit integer" unless value.is_a?(Integer) && value.between?(1, 2_147_483_647)
|
|
10
|
+
|
|
11
|
+
value
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def validate_node_ids!
|
|
17
|
+
node_ids = all_hosts.map { |host| node_id_for(host) }
|
|
18
|
+
raise Error, 'PostgreSQL node_id values must be unique' unless node_ids.uniq.size == node_ids.size
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
require 'yaml'
|
|
2
2
|
require_relative 'configuration/pgbackrest_policy'
|
|
3
3
|
require_relative 'configuration/standby_policy'
|
|
4
|
+
require_relative 'configuration/node_identity'
|
|
4
5
|
|
|
5
6
|
module ActivePostgres
|
|
6
7
|
class Configuration
|
|
7
8
|
include PgBackRestPolicy
|
|
8
9
|
include StandbyPolicy
|
|
10
|
+
include NodeIdentity
|
|
9
11
|
|
|
10
12
|
attr_reader :environment, :version, :user, :ssh_key, :ssh_known_hosts_file, :ssh_host_key_verification,
|
|
11
13
|
:primary, :standbys, :jump_hosts, :components, :secrets_config, :database_config
|
|
@@ -147,6 +149,8 @@ module ActivePostgres
|
|
|
147
149
|
def validate!
|
|
148
150
|
raise Error, 'No primary host defined' unless primary_host
|
|
149
151
|
|
|
152
|
+
validate_node_ids!
|
|
153
|
+
|
|
150
154
|
# Validate required secrets if components are enabled
|
|
151
155
|
raise Error, 'Missing replication_password secret' if component_enabled?(:repmgr) && !secrets_config['replication_password']
|
|
152
156
|
raise Error, 'Missing monitoring_password secret' if component_enabled?(:monitoring) && !secrets_config['monitoring_password']
|
data/templates/repmgr.conf.erb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_postgres
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- BoringCache
|
|
@@ -126,6 +126,7 @@ files:
|
|
|
126
126
|
- lib/active_postgres/components/repmgr.rb
|
|
127
127
|
- lib/active_postgres/components/ssl.rb
|
|
128
128
|
- lib/active_postgres/configuration.rb
|
|
129
|
+
- lib/active_postgres/configuration/node_identity.rb
|
|
129
130
|
- lib/active_postgres/configuration/pgbackrest_policy.rb
|
|
130
131
|
- lib/active_postgres/configuration/standby_policy.rb
|
|
131
132
|
- lib/active_postgres/connection_pooler.rb
|