# frozen_string_literal: true

module Gitlab
  module QA
    module Component
      class RunnerOps < Base
        include Support::Shellout

        RUNNER_DESCRIPTION = "QA Runner"
        DOCKER_IMAGE = "registry.gitlab.com/gitlab-org/gitlab-runner:alpine"
        BUILD_IMAGE = "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7"

        def setup_runner(gitlab)
          token = SecureRandom.hex(15)
          add_runner_to_gitlab(gitlab, token)
          register_docker_runner(gitlab, token)
        end

        private

        def add_runner_to_gitlab(gitlab, token)
          gitlab.docker.exec(
            gitlab.name,
            create_runner_command(token),
            mask_secrets: token
          )
        end

        def create_runner_command(token)
          <<~RUBY.strip.gsub(/\s+/, ' ')
            gitlab-rails runner '
              Ci::Runner.create!(
                description: "#{RUNNER_DESCRIPTION}",
                run_untagged: true,
                active: true,
                token: "#{token}",
                runner_type: :instance_type
              );
              puts "Runner created"
            '
          RUBY
        end

        def register_docker_runner(gitlab, token)
          runner_name = generate_runner_name
          docker_command = build_docker_command(
            runner_name: runner_name,
            network: gitlab.network,
            address: gitlab.address,
            token: token
          )

          shell(docker_command, mask_secrets: [token])
        end

        def generate_runner_name
          "test-runner-#{SecureRandom.hex(4)}"
        end

        def build_docker_command(runner_name:, network:, address:, token:)
          <<~CMD.tr("\n", ' ')
            docker run -d --rm --network #{network} --name #{runner_name}
            -v /var/run/docker.sock:/var/run/docker.sock
            --privileged
            #{DOCKER_IMAGE}
            && docker exec --detach #{runner_name} sh -c "#{register_command(runner_name, address, token, network)}"
          CMD
        end

        def runner_config
          <<~CONFIG
            concurrent = 1
            check_interval = 0

            [session_server]
              session_timeout = 1800
          CONFIG
        end

        def register_command(name, address, token, network)
          registration_args = build_registration_args(
            name: name,
            address: address,
            token: token,
            network: network
          )

          <<~CMD.strip
            printf '#{runner_config.chomp.gsub(/\n/, '\\n').gsub('"', '\"')}' > /etc/gitlab-runner/config.toml  &&
            gitlab-runner register #{registration_args} &&
            gitlab-runner run
          CMD
        end

        def build_registration_args(name:, address:, token:, network:)
          [
            '--non-interactive',
            "--name #{name}",
            "--url #{address}",
            "--token #{token}",
            '--run-untagged=true',
            '--executor docker',
            "--docker-image #{BUILD_IMAGE}",
            '--docker-tlsverify=false',
            '--docker-privileged=true',
            "--docker-network-mode=#{network}",
            '--docker-volumes=/certs/client'
          ].join(' ')
        end
      end
    end
  end
end
