# HG changeset patch
# User Robert Marshall <rmarshall@gitlab.com>
# Date 1650083482 0
#      Sat Apr 16 04:31:22 2022 +0000
# Node ID 6bcfd36ed5ea797b95c6a7a069f2c346c49d451a
# Parent  2065749a61608d09b92fba03ac79cf145c82c86a
Enable multi-Patroni services support in PGBouncer

- When the database command is specified, only update the options for
  that specific database.
- Self managed users may have depended on the default behaviors, so
  retain the default rails database behavior for now to support
  administrators who may depend on it with their scripts until a proper
  deprecation notice has been published.

Closes https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6757

Related https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6587

Changelog: added

Signed-off-by: Robert Marshall <rmarshall@gitlab.com>

diff --git a/files/gitlab-ctl-commands-ee/lib/pgbouncer.rb b/files/gitlab-ctl-commands-ee/lib/pgbouncer.rb
--- a/files/gitlab-ctl-commands-ee/lib/pgbouncer.rb
+++ b/files/gitlab-ctl-commands-ee/lib/pgbouncer.rb
@@ -9,10 +9,22 @@
 end
 
 module Pgbouncer
+  DEFAULT_RAILS_DATABASE = 'gitlabhq_production'.freeze
+
   class Databases
     attr_accessor :install_path, :databases, :options, :ini_file, :json_file, :template_file, :attributes, :userinfo, :groupinfo, :database
     attr_reader :data_path
 
+    def self.rails_database(attributes: nil)
+      attributes = GitlabCtl::Util.get_public_node_attributes if attributes.nil?
+
+      if attributes.key?('gitlab')
+        attributes['gitlab']['gitlab-rails']['db_database']
+      else
+        DEFAULT_RAILS_DATABASE
+      end
+    end
+
     def initialize(options, install_path, base_data_path)
       self.data_path = base_data_path
       @attributes = GitlabCtl::Util.get_public_node_attributes
@@ -21,36 +33,42 @@
       @ini_file = options['databases_ini'] || database_ini
       @json_file = options['databases_json'] || database_json
       @template_file = "#{@install_path}/embedded/cookbooks/gitlab-ee/templates/default/databases.ini.erb"
-      @database = if attributes.key?('gitlab')
-                    attributes['gitlab']['gitlab-rails']['db_database']
-                  else
-                    'gitlabhq_production'
-                  end
+      @database = options['database'] || Databases.rails_database(attributes: @attributes)
       @databases = update_databases(JSON.parse(File.read(@json_file))) if File.exist?(@json_file)
       @userinfo = GitlabCtl::Util.userinfo(options['host_user']) if options['host_user']
       @groupinfo = GitlabCtl::Util.groupinfo(options['host_group']) if options['host_group']
     end
 
-    def update_databases(original)
+    def update_databases(original = {})
+      updated = {}
+
       if original.empty?
         original = {
           database => {}
         }
       end
-      updated = Chef::Mixin::DeepMerge.merge(updated, original)
+
       original.each do |db, settings|
         settings.delete('password')
+
         updated[db] = ''
-        settings['host'] = options['newhost'] if options['newhost']
-        settings['port'] = options['port'] if options['port']
+
         settings['auth_user'] = settings.delete('user') if settings.key?('user')
-        settings['auth_user'] = options['user'] if options['user']
-        settings['dbname'] = options['pg_database'] if options['pg_database']
+
+        if db == @database
+          settings['host'] = options['newhost'] if options['newhost']
+          settings['port'] = options['port'] if options['port']
+          settings['auth_user'] = options['user'] if options['user']
+          settings['dbname'] = options['pg_database'] if options['pg_database']
+        end
+
         settings.each do |setting, value|
           updated[db] << " #{setting}=#{value}"
         end
+
         updated[db].strip!
       end
+
       updated
     end
 
diff --git a/files/gitlab-ctl-commands-ee/pgbouncer.rb b/files/gitlab-ctl-commands-ee/pgbouncer.rb
--- a/files/gitlab-ctl-commands-ee/pgbouncer.rb
+++ b/files/gitlab-ctl-commands-ee/pgbouncer.rb
@@ -59,7 +59,7 @@
   pgpass = GitlabCtl::PostgreSQL::Pgpass.new(
     hostname: options['host'],
     port: options['port'],
-    database: options['database'],
+    database: options['database'] || Pgbouncer::Databases.rails_database,
     username: options['user'],
     password: password,
     host_user: options['host_user'],
@@ -70,7 +70,7 @@
 
 def get_pg_options
   options = {
-    'database' => 'gitlabhq_production',
+    'database' => nil,
     'databases_ini' => nil,
     'databases_json' => nil,
     'host' => nil,
diff --git a/spec/chef/gitlab-ctl-commands-ee/lib/pgbouncer_spec.rb b/spec/chef/gitlab-ctl-commands-ee/lib/pgbouncer_spec.rb
--- a/spec/chef/gitlab-ctl-commands-ee/lib/pgbouncer_spec.rb
+++ b/spec/chef/gitlab-ctl-commands-ee/lib/pgbouncer_spec.rb
@@ -66,7 +66,8 @@
         'databases_ini' => '/another/databases.ini',
         'databases_json' => '/another/databases.json',
         'port' => 8888,
-        'user' => 'fakeuser'
+        'user' => 'fakeuser',
+        'database' => 'fakedb'
       }
       allow(File).to receive(:exist?).with('/another/databases.json').and_return(true)
       allow(File).to receive(:read).with('/another/databases.json').and_return(fake_databases_json)
@@ -91,7 +92,7 @@
       @obj = Pgbouncer::Databases.new({}, '/fakeinstall', '/fakedata')
     end
 
-    it 'should generate an databases.ini with sane defaults' do
+    it 'should generate an databases.ini with the default rails database' do
       expect(@obj.render).to eq(
         "[databases]\n\nfake_database = \n\n"
       )