summaryrefslogtreecommitdiff
path: root/lib/gitlab/setup_helper.rb
blob: 3f36725cb662d351cb4c10937a937e2047b0d4c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# frozen_string_literal: true

require 'toml-rb'

module Gitlab
  module SetupHelper
    def create_configuration(dir, storage_paths, force: false)
      generate_configuration(
        configuration_toml(dir, storage_paths),
        get_config_path(dir),
        force: force
      )
    end

    # rubocop:disable Rails/Output
    def generate_configuration(toml_data, config_path, force: false)
      FileUtils.rm_f(config_path) if force

      File.open(config_path, File::WRONLY | File::CREAT | File::EXCL) do |f|
        f.puts toml_data
      end
    rescue Errno::EEXIST
      puts 'Skipping config.toml generation:'
      puts 'A configuration file already exists.'
    rescue ArgumentError => e
      puts 'Skipping config.toml generation:'
      puts e.message
    end
    # rubocop:enable Rails/Output

    module Gitaly
      extend Gitlab::SetupHelper
      class << self
        # We cannot create config.toml files for all possible Gitaly configuations.
        # For instance, if Gitaly is running on another machine then it makes no
        # sense to write a config.toml file on the current machine. This method will
        # only generate a configuration for the most common and simplest case: when
        # we have exactly one Gitaly process and we are sure it is running locally
        # because it uses a Unix socket.
        # For development and testing purposes, an extra storage is added to gitaly,
        # which is not known to Rails, but must be explicitly stubbed.
        def configuration_toml(gitaly_dir, storage_paths, gitaly_ruby: true)
          storages = []
          address = nil

          Gitlab.config.repositories.storages.each do |key, val|
            if address
              if address != val['gitaly_address']
                raise ArgumentError, "Your gitlab.yml contains more than one gitaly_address."
              end
            elsif URI(val['gitaly_address']).scheme != 'unix'
              raise ArgumentError, "Automatic config.toml generation only supports 'unix:' addresses."
            else
              address = val['gitaly_address']
            end

            storages << { name: key, path: storage_paths[key] }
          end

          config = { socket_path: address.sub(/\Aunix:/, '') }

          if Rails.env.test?
            storage_path = Rails.root.join('tmp', 'tests', 'second_storage').to_s
            storages << { name: 'test_second_storage', path: storage_path }

            config[:auth] = { token: 'secret' }
            # Compared to production, tests run in constrained environments. This
            # number is meant to grow with the number of concurrent rails requests /
            # sidekiq jobs, and concurrency will be low anyway in test.
            config[:git] = { catfile_cache_size: 5 }
          end

          config[:storage] = storages

          internal_socket_dir = File.join(gitaly_dir, 'internal_sockets')
          FileUtils.mkdir(internal_socket_dir) unless File.exist?(internal_socket_dir)
          config[:internal_socket_dir] = internal_socket_dir

          config[:'gitaly-ruby'] = { dir: File.join(gitaly_dir, 'ruby') } if gitaly_ruby
          config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
          config[:bin_dir] = Gitlab.config.gitaly.client_path

          TomlRB.dump(config)
        end

        private

        def get_config_path(dir)
          File.join(dir, 'config.toml')
        end
      end
    end

    module Praefect
      extend Gitlab::SetupHelper
      class << self
        def configuration_toml(gitaly_dir, storage_paths)
          nodes = [{ storage: 'default', address: "unix:#{gitaly_dir}/gitaly.socket", primary: true, token: 'secret' }]
          storages = [{ name: 'default', node: nodes }]
          config = { socket_path: "#{gitaly_dir}/praefect.socket", virtual_storage: storages }
          config[:token] = 'secret' if Rails.env.test?

          TomlRB.dump(config)
        end

        private

        def get_config_path(dir)
          File.join(dir, 'praefect.config.toml')
        end
      end
    end
  end
end