1require 'socket'
2require 'spec_helper'
3
4SOCKET_PATH = 'gitaly.socket'.freeze
5
6module GitalyConfig
7  def self.set_dynamic_ports
8    tcp_sock = Socket.new(:INET, :STREAM)
9    tls_sock = Socket.new(:INET, :STREAM)
10    tcp_sock.bind(Addrinfo.tcp('127.0.0.1', 0))
11    tls_sock.bind(Addrinfo.tcp('127.0.0.1', 0))
12
13    @dynamic_tcp_port = tcp_sock.local_address.ip_port
14    @dynamic_tls_port = tls_sock.local_address.ip_port
15  ensure
16    tcp_sock.close
17    tls_sock.close
18  end
19
20  def self.dynamic_port(type)
21    set_dynamic_ports unless @dynamic_tcp_port && @dynamic_tls_port
22
23    case type
24    when 'tcp'
25      @dynamic_tcp_port
26    when 'tls'
27      @dynamic_tls_port
28    end
29  end
30end
31
32module IntegrationClient
33  def gitaly_stub(service, type = 'unix')
34    klass = Gitaly.const_get(service).const_get(:Stub)
35    addr = case type
36           when 'unix'
37             "unix:#{File.join(TMP_DIR_NAME, SOCKET_PATH)}"
38           when 'tcp', 'tls'
39             "#{type}://localhost:#{GitalyConfig.dynamic_port(type)}"
40           end
41    klass.new(addr, creds)
42  end
43
44  def creds
45    :this_channel_is_insecure
46  end
47
48  def gitaly_repo(storage, relative_path)
49    Gitaly::Repository.new(storage_name: storage, relative_path: relative_path)
50  end
51
52  def get_client(addr)
53    servers = Base64.strict_encode64({
54      default: {
55        address: addr,
56        token: 'the-secret-token'
57      }
58    }.to_json)
59
60    call = double(metadata: { 'gitaly-servers' => servers })
61    Gitlab::Git::GitalyRemoteRepository.new(repository.gitaly_repository, call)
62  end
63end
64
65def start_gitaly
66  build_dir = File.expand_path(File.join(GITALY_RUBY_DIR, '../_build'))
67  cert_path = File.join(File.dirname(__FILE__), "/certs")
68
69  FileUtils.mkdir_p([TMP_DIR, File.join(GITLAB_SHELL_DIR, 'hooks')])
70  File.write(File.join(GITLAB_SHELL_DIR, '.gitlab_shell_secret'), 'test_gitlab_shell_token')
71
72  config_toml = <<~CONFIG
73    socket_path = "#{SOCKET_PATH}"
74    listen_addr = "localhost:#{GitalyConfig.dynamic_port('tcp')}"
75    tls_listen_addr = "localhost:#{GitalyConfig.dynamic_port('tls')}"
76    bin_dir = "#{build_dir}/bin"
77
78    [tls]
79    certificate_path = "#{cert_path}/gitalycert.pem"
80    key_path = "#{cert_path}/gitalykey.pem"
81
82    [gitlab-shell]
83    dir = "#{GITLAB_SHELL_DIR}"
84
85    [gitlab]
86    url = 'http://gitlab_url'
87
88    [gitaly-ruby]
89    dir = "#{GITALY_RUBY_DIR}"
90
91    [[storage]]
92    name = "#{DEFAULT_STORAGE_NAME}"
93    path = "#{DEFAULT_STORAGE_DIR}"
94  CONFIG
95  config_path = File.join(TMP_DIR, 'gitaly-rspec-config.toml')
96  File.write(config_path, config_toml)
97
98  test_log = File.join(TMP_DIR, 'gitaly-rspec-test.log')
99  options = { out: test_log, err: test_log, chdir: TMP_DIR }
100
101  gitaly_pid = spawn(File.join(build_dir, 'bin/gitaly'), config_path, options)
102  at_exit { Process.kill('KILL', gitaly_pid) }
103
104  wait_ready!(File.join(TMP_DIR_NAME, SOCKET_PATH))
105end
106
107def wait_ready!(socket)
108  last_exception = StandardError.new('wait_ready! has not made any connection attempts')
109
110  print('Booting gitaly for integration tests')
111  100.times do |_i|
112    sleep 0.1
113    printf('.')
114    begin
115      UNIXSocket.new(socket).close
116      puts ' ok'
117      return
118    rescue => ex
119      last_exception = ex
120    end
121  end
122
123  puts
124  raise last_exception
125end
126
127start_gitaly
128