Class: ActivePostgres::Configuration
- Inherits:
-
Object
- Object
- ActivePostgres::Configuration
- Defined in:
- lib/active_postgres/configuration.rb
Instance Attribute Summary collapse
-
#components ⇒ Object
readonly
Returns the value of attribute components.
-
#database_config ⇒ Object
readonly
Returns the value of attribute database_config.
-
#environment ⇒ Object
readonly
Returns the value of attribute environment.
-
#primary ⇒ Object
readonly
Returns the value of attribute primary.
-
#secrets_config ⇒ Object
readonly
Returns the value of attribute secrets_config.
-
#ssh_host_key_verification ⇒ Object
readonly
Returns the value of attribute ssh_host_key_verification.
-
#ssh_key ⇒ Object
readonly
Returns the value of attribute ssh_key.
-
#standbys ⇒ Object
readonly
Returns the value of attribute standbys.
-
#user ⇒ Object
readonly
Returns the value of attribute user.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
Instance Method Summary collapse
- #all_hosts ⇒ Object
- #app_database ⇒ Object
- #app_user ⇒ Object
- #component_config(name) ⇒ Object
- #component_enabled?(name) ⇒ Boolean
-
#connection_host_for(host) ⇒ Object
Returns the host to use for direct PostgreSQL connections (private_ip preferred).
-
#initialize(config_hash, environment = 'development') ⇒ Configuration
constructor
A new instance of Configuration.
- #node_label_for(host) ⇒ Object
- #pgbouncer_app_hosts ⇒ Object
- #pgbouncer_primary_record ⇒ Object
- #pgbouncer_user ⇒ Object
-
#postgres_user ⇒ Object
Database and user configuration helpers from components.
- #primary_connection_host ⇒ Object
- #primary_host ⇒ Object
- #primary_replication_host ⇒ Object
- #replication_host_for(host) ⇒ Object
- #replication_user ⇒ Object
- #repmgr_database ⇒ Object
- #repmgr_user ⇒ Object
- #skip_deployment? ⇒ Boolean
- #standby_config_for(host) ⇒ Object
- #standby_hosts ⇒ Object
- #validate! ⇒ Object
Constructor Details
#initialize(config_hash, environment = 'development') ⇒ Configuration
Returns a new instance of Configuration.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/active_postgres/configuration.rb', line 8 def initialize(config_hash, environment = 'development') @environment = environment env_config = config_hash[environment] || {} @skip_deployment = env_config['skip_deployment'] == true @version = env_config['version'] || 18 @user = env_config['user'] || 'ubuntu' @ssh_key = File.(env_config['ssh_key'] || '~/.ssh/id_rsa') @ssh_host_key_verification = normalize_ssh_host_key_verification( env_config['ssh_host_key_verification'] || env_config['ssh_verify_host_key'] ) @primary = env_config['primary'] || {} @standbys = env_config['standby'] || [] @standbys = [@standbys] unless @standbys.is_a?(Array) @components = parse_components(env_config['components'] || {}) @secrets_config = env_config['secrets'] || {} end |
Instance Attribute Details
#components ⇒ Object (readonly)
Returns the value of attribute components.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def components @components end |
#database_config ⇒ Object (readonly)
Returns the value of attribute database_config.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def database_config @database_config end |
#environment ⇒ Object (readonly)
Returns the value of attribute environment.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def environment @environment end |
#primary ⇒ Object (readonly)
Returns the value of attribute primary.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def primary @primary end |
#secrets_config ⇒ Object (readonly)
Returns the value of attribute secrets_config.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def secrets_config @secrets_config end |
#ssh_host_key_verification ⇒ Object (readonly)
Returns the value of attribute ssh_host_key_verification.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def ssh_host_key_verification @ssh_host_key_verification end |
#ssh_key ⇒ Object (readonly)
Returns the value of attribute ssh_key.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def ssh_key @ssh_key end |
#standbys ⇒ Object (readonly)
Returns the value of attribute standbys.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def standbys @standbys end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def user @user end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
5 6 7 |
# File 'lib/active_postgres/configuration.rb', line 5 def version @version end |
Class Method Details
.load(config_path = 'config/postgres.yml', environment = nil) ⇒ Object
29 30 31 32 33 34 35 36 |
# File 'lib/active_postgres/configuration.rb', line 29 def self.load(config_path = 'config/postgres.yml', environment = nil) environment ||= ENV['BORING_ENVIRONMENT'] || ENV['RAILS_ENV'] || 'development' raise Error, "Config file not found: #{config_path}" unless File.exist?(config_path) config_hash = YAML.load_file(config_path, aliases: true) new(config_hash, environment) end |
Instance Method Details
#all_hosts ⇒ Object
38 39 40 |
# File 'lib/active_postgres/configuration.rb', line 38 def all_hosts [primary_host] + standby_hosts end |
#app_database ⇒ Object
204 205 206 207 |
# File 'lib/active_postgres/configuration.rb', line 204 def app_database value = component_config(:core)[:app_database] value.nil? || value.to_s.strip.empty? ? "app_#{environment}" : value end |
#app_user ⇒ Object
199 200 201 202 |
# File 'lib/active_postgres/configuration.rb', line 199 def app_user value = component_config(:core)[:app_user] value.nil? || value.to_s.strip.empty? ? 'app' : value end |
#component_config(name) ⇒ Object
83 84 85 |
# File 'lib/active_postgres/configuration.rb', line 83 def component_config(name) @components[name] || {} end |
#component_enabled?(name) ⇒ Boolean
79 80 81 |
# File 'lib/active_postgres/configuration.rb', line 79 def component_enabled?(name) @components[name]&.[](:enabled) == true end |
#connection_host_for(host) ⇒ Object
Returns the host to use for direct PostgreSQL connections (private_ip preferred)
101 102 103 104 |
# File 'lib/active_postgres/configuration.rb', line 101 def connection_host_for(host) node = node_config_for(host) private_ip_for(node) || host end |
#node_label_for(host) ⇒ Object
114 115 116 117 118 119 120 |
# File 'lib/active_postgres/configuration.rb', line 114 def node_label_for(host) if host == primary_host @primary['label'] else standby_config_for(host)&.dig('label') end end |
#pgbouncer_app_hosts ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/active_postgres/configuration.rb', line 42 def pgbouncer_app_hosts hosts = component_config(:pgbouncer)[:app_hosts] || component_config(:pgbouncer)['app_hosts'] || [] hosts = [hosts] unless hosts.is_a?(Array) hosts.filter_map do |entry| case entry when String entry.strip.empty? ? nil : { 'host' => entry.strip } when Hash host = entry['host'] || entry[:host] || entry['ip'] || entry[:ip] next if host.to_s.strip.empty? entry.merge('host' => host.to_s.strip) end end end |
#pgbouncer_primary_record ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/active_postgres/configuration.rb', line 59 def pgbouncer_primary_record pgbouncer = component_config(:pgbouncer) explicit = pgbouncer[:primary_record] || pgbouncer['primary_record'] return explicit.to_s.strip unless explicit.to_s.strip.empty? dns_failover = component_config(:repmgr)[:dns_failover] || component_config(:repmgr)['dns_failover'] || {} record = dns_failover[:primary_record] || dns_failover['primary_record'] return record.to_s.strip unless record.to_s.strip.empty? primary_replication_host end |
#pgbouncer_user ⇒ Object
195 196 197 |
# File 'lib/active_postgres/configuration.rb', line 195 def pgbouncer_user component_config(:pgbouncer)[:user] || 'pgbouncer' end |
#postgres_user ⇒ Object
Database and user configuration helpers from components
179 180 181 |
# File 'lib/active_postgres/configuration.rb', line 179 def postgres_user component_config(:core)[:postgres_user] || 'postgres' end |
#primary_connection_host ⇒ Object
106 107 108 |
# File 'lib/active_postgres/configuration.rb', line 106 def primary_connection_host connection_host_for(primary_host) end |
#primary_host ⇒ Object
71 72 73 |
# File 'lib/active_postgres/configuration.rb', line 71 def primary_host @primary['host'] end |
#primary_replication_host ⇒ Object
91 92 93 |
# File 'lib/active_postgres/configuration.rb', line 91 def primary_replication_host replication_host_for(primary_host) end |
#replication_host_for(host) ⇒ Object
95 96 97 98 |
# File 'lib/active_postgres/configuration.rb', line 95 def replication_host_for(host) node = node_config_for(host) private_ip_for(node) || host end |
#replication_user ⇒ Object
191 192 193 |
# File 'lib/active_postgres/configuration.rb', line 191 def replication_user component_config(:repmgr)[:replication_user] || 'replication' end |
#repmgr_database ⇒ Object
187 188 189 |
# File 'lib/active_postgres/configuration.rb', line 187 def repmgr_database component_config(:repmgr)[:database] || 'repmgr' end |
#repmgr_user ⇒ Object
183 184 185 |
# File 'lib/active_postgres/configuration.rb', line 183 def repmgr_user component_config(:repmgr)[:user] || 'repmgr' end |
#skip_deployment? ⇒ Boolean
87 88 89 |
# File 'lib/active_postgres/configuration.rb', line 87 def skip_deployment? @skip_deployment end |
#standby_config_for(host) ⇒ Object
110 111 112 |
# File 'lib/active_postgres/configuration.rb', line 110 def standby_config_for(host) @standbys.find { |s| s['host'] == host } end |
#standby_hosts ⇒ Object
75 76 77 |
# File 'lib/active_postgres/configuration.rb', line 75 def standby_hosts @standbys.map { |s| s['host'] } end |
#validate! ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/active_postgres/configuration.rb', line 122 def validate! raise Error, 'No primary host defined' unless primary_host # Validate required secrets if components are enabled raise Error, 'Missing replication_password secret' if component_enabled?(:repmgr) && !secrets_config['replication_password'] raise Error, 'Missing monitoring_password secret' if component_enabled?(:monitoring) && !secrets_config['monitoring_password'] if component_enabled?(:monitoring) grafana_config = component_config(:monitoring)[:grafana] || {} if grafana_config[:enabled] && !secrets_config['grafana_admin_password'] raise Error, 'Missing grafana_admin_password secret' end if grafana_config[:enabled] && grafana_config[:host].to_s.strip.empty? raise Error, 'monitoring.grafana.host is required when grafana is enabled' end end if component_enabled?(:pgbackrest) pg_config = component_config(:pgbackrest) retention_full = pg_config[:retention_full] retention_archive = pg_config[:retention_archive] if retention_full && retention_archive && retention_archive.to_i < retention_full.to_i raise Error, 'pgbackrest.retention_archive must be >= retention_full for PITR safety' end end if component_enabled?(:pgbouncer) pgbouncer_app_hosts.each do |app_host| host = app_host['host'] || app_host[:host] raise Error, 'pgbouncer.app_hosts entries must include host' if host.to_s.strip.empty? end end if component_enabled?(:repmgr) dns_failover = component_config(:repmgr)[:dns_failover] if dns_failover && dns_failover[:enabled] domains = Array(dns_failover[:domains] || dns_failover[:domain]).map(&:to_s).map(&:strip).reject(&:empty?) servers = Array(dns_failover[:dns_servers]) provider = (dns_failover[:provider] || 'dnsmasq').to_s.strip raise Error, 'dns_failover.domain or dns_failover.domains is required when enabled' if domains.empty? raise Error, 'dns_failover.dns_servers is required when enabled' if servers.empty? raise Error, "Unsupported dns_failover provider '#{provider}'" unless provider == 'dnsmasq' servers.each do |server| next unless server.is_a?(Hash) ssh_host = server['ssh_host'] || server[:ssh_host] || server['host'] || server[:host] private_ip = server['private_ip'] || server[:private_ip] || server['ip'] || server[:ip] raise Error, 'dns_failover.dns_servers entries must include host/ssh_host or private_ip' if (ssh_host.nil? || ssh_host.to_s.strip.empty?) && (private_ip.nil? || private_ip.to_s.strip.empty?) end end end true end |