class Gitlab::QA::Scenario::Test::Integration::GitalyCluster

def disable_other_services

def disable_other_services
  <<~OMNIBUS
    postgresql['enable'] = false;
    redis['enable'] = false;
    nginx['enable'] = false;
    prometheus['enable'] = false;
    grafana['enable'] = false;
    puma['enable'] = false;
    sidekiq['enable'] = false;
    gitlab_workhorse['enable'] = false;
    gitlab_rails['rake_cache_clear'] = false;
    gitlab_rails['auto_migrate'] = false;
  OMNIBUS
end

def gitaly(name, release)

def gitaly(name, release)
  Component::Gitlab.new.tap do |gitaly|
    gitaly.release = QA::Release.new(release)
    gitaly.name = name
    gitaly.network = @network
    gitaly.skip_availability_check = true
    gitaly.omnibus_config = gitaly_omnibus_configuration
    gitaly.instance(skip_teardown: true)
  end
end

def gitaly_omnibus_configuration

def gitaly_omnibus_configuration
  <<~OMNIBUS
    #{disable_other_services}
    prometheus['enable'] = true;
    prometheus_monitoring['enable'] = false;
    gitaly['enable'] = true;
    gitaly['listen_addr'] = '0.0.0.0:8075';
    gitaly['prometheus_listen_addr'] = '0.0.0.0:9236';
    gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN';
    gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
    gitlab_rails['internal_api_url'] = 'http://#{@gitlab_name}.#{@network}';
    git_data_dirs({
      '#{@primary_node_name}' => {
        'path' => '/var/opt/gitlab/git-data'
      },
      '#{@secondary_node_name}' => {
        'path' => '/var/opt/gitlab/git-data'
      },
      '#{@tertiary_node_name}' => {
        'path' => '/var/opt/gitlab/git-data'
      }
    });
  OMNIBUS
end

def gitlab_omnibus_configuration

def gitlab_omnibus_configuration
  <<~OMNIBUS
    external_url 'http://#{@gitlab_name}.#{@network}';
    git_data_dirs({
      'default' => {
        'gitaly_address' => 'tcp://#{@praefect_node_name}.#{@network}:2305',
        'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    });
    gitaly['listen_addr'] = '0.0.0.0:8075';
    gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
    prometheus['scrape_configs'] = [
      {
        'job_name' => 'praefect',
        'static_configs' => [
          'targets' => [
            '#{@praefect_node_name}.#{@network}:9652'
          ]
        ]
      },
      {
        'job_name' => 'praefect-gitaly',
        'static_configs' => [
          'targets' => [
            '#{@primary_node_name}.#{@network}:9236',
            '#{@secondary_node_name}.#{@network}:9236',
            '#{@tertiary_node_name}.#{@network}:9236'
          ]
        ]
      }
    ];
    grafana['disable_login_form'] = false;
    grafana['admin_password'] = 'GRAFANA_ADMIN_PASSWORD';
  OMNIBUS
end

def initialize

def initialize
  @gitlab_name = 'gitlab-gitaly-cluster'
  @primary_node_name = 'gitaly1'
  @secondary_node_name = 'gitaly2'
  @tertiary_node_name = 'gitaly3'
  @praefect_node_name = 'praefect'
  @database = 'postgres'
  @spec_suite = 'Test::Instance::All'
  @network = 'test'
  @env = {}
  @tag = 'gitaly_cluster'
end

def perform(release, *rspec_args)

rubocop:disable Metrics/AbcSize
def perform(release, *rspec_args)
  gitaly_primary_node = gitaly(@primary_node_name, release)
  gitaly_secondary_node = gitaly(@secondary_node_name, release)
  gitaly_tertiary_node = gitaly(@tertiary_node_name, release)
  sql_node = Component::PostgreSQL.new.tap do |sql|
    sql.name = @database
    sql.network = @network
    sql.instance(skip_teardown: true) do
      sql.run_psql '-d template1 -c "CREATE DATABASE praefect_production OWNER postgres"'
    end
  end
  praefect_node = Component::Gitlab.new.tap do |praefect|
    praefect.release = QA::Release.new(release)
    praefect.name = @praefect_node_name
    praefect.network = @network
    praefect.skip_availability_check = true
    praefect.omnibus_config = praefect_omnibus_configuration
    praefect.instance(skip_teardown: true)
  end
  Component::Gitlab.perform do |gitlab|
    gitlab.release = QA::Release.new(release)
    gitlab.name = gitlab_name
    gitlab.network = @network
    gitlab.omnibus_config = gitlab_omnibus_configuration
    gitlab.instance do
      puts "Running Gitaly Cluster specs!"
      if @tag
        rspec_args << "--" unless rspec_args.include?('--')
        rspec_args << "--tag" << @tag
      end
      Component::Specs.perform do |specs|
        specs.suite = spec_suite
        specs.release = gitlab.release
        specs.network = gitlab.network
        specs.args = [gitlab.address, *rspec_args]
        specs.env = @env
      end
    end
  end
ensure
  praefect_node&.teardown
  sql_node&.teardown
  gitaly_primary_node&.teardown
  gitaly_secondary_node&.teardown
  gitaly_tertiary_node&.teardown
end

def praefect_omnibus_configuration

def praefect_omnibus_configuration
  <<~OMNIBUS
    #{disable_other_services}
    gitaly['enable'] = false;
    praefect['enable'] = true;
    praefect['listen_addr'] = '0.0.0.0:2305';
    praefect['prometheus_listen_addr'] = '0.0.0.0:9652';
    praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN';
    praefect['database_host'] = '#{@database}.#{@network}';
    praefect['database_user'] = 'postgres';
    praefect['database_port'] = 5432;
    praefect['database_password'] = 'SQL_PASSWORD';
    praefect['database_dbname'] = 'praefect_production';
    praefect['database_sslmode'] = 'disable';
    praefect['postgres_queue_enabled'] = true;
    praefect['failover_enabled'] = true;
    praefect['virtual_storages'] = {
      'default' => {
        '#{@primary_node_name}' => {
          'address' => 'tcp://#{@primary_node_name}.#{@network}:8075',
          'token'   => 'PRAEFECT_INTERNAL_TOKEN',
          'primary' => true
        },
        '#{@secondary_node_name}' => {
          'address' => 'tcp://#{@secondary_node_name}.#{@network}:8075',
          'token'   => 'PRAEFECT_INTERNAL_TOKEN'
        },
        '#{@tertiary_node_name}' => {
          'address' => 'tcp://#{@tertiary_node_name}.#{@network}:8075',
          'token'   => 'PRAEFECT_INTERNAL_TOKEN'
        }
      }
    };
  OMNIBUS
end