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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# frozen_string_literal: true
require 'resolv'
module QA
module Service
module DockerRun
class GitlabRunner < Base
attr_reader :tags
attr_accessor :token, :address, :image, :run_untagged
attr_writer :config, :executor, :executor_image
CONFLICTING_VARIABLES_MESSAGE = <<~MSG
There are conflicting options preventing the runner from starting.
%s cannot be specified if %s is %s
MSG
def initialize(name)
@image = 'gitlab/gitlab-runner:alpine'
@name = name || "qa-runner-#{SecureRandom.hex(4)}"
@run_untagged = true
@executor = :shell
@executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
super()
end
def config
@config ||= <<~CONFIG
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
CONFIG
end
def register!
raise("Missing runner token value!") unless token
cmd = <<~CMD.tr("\n", ' ')
docker run -d --rm --network #{runner_network} --name #{@name}
#{'-v /var/run/docker.sock:/var/run/docker.sock' if @executor == :docker}
--privileged
#{@image} #{add_gitlab_tls_cert if @address.include? 'https'}
&& docker exec --detach #{@name} sh -c "#{register_command}"
CMD
shell(cmd, mask_secrets: [@token])
wait_until_running_and_configured
# Prove airgappedness
shell("docker exec #{@name} sh -c '#{prove_airgap}'") if runner_network == 'airgapped'
end
def tags=(tags)
@tags = tags
@run_untagged = false
end
def restart
super
wait_until_shell_command_matches("docker logs #{@name}", /Configuration loaded/)
end
private
def register_command
args = []
args << '--non-interactive'
args << "--name #{@name}"
args << "--url #{@address}"
args << "--registration-token #{@token}"
args << if run_untagged
raise format(CONFLICTING_VARIABLES_MESSAGE, :tags=, :run_untagged, run_untagged) if @tags&.any?
'--run-untagged=true'
else
raise 'You must specify tags to run!' unless @tags&.any?
"--tag-list #{@tags.join(',')}"
end
args << "--executor #{@executor}"
if @executor == :docker
args << "--docker-image #{@executor_image}"
args << '--docker-tlsverify=false'
args << '--docker-privileged=true'
args << "--docker-network-mode=#{network}"
args << "--docker-volumes=/certs/client"
end
<<~CMD.strip
printf '#{config.chomp.gsub(/\n/, '\\n').gsub('"', '\"')}' > /etc/gitlab-runner/config.toml &&
gitlab-runner register \
#{args.join(' ')} &&
gitlab-runner run
CMD
end
# Ping Cloudflare DNS, should fail
# Ping Registry, should fail to resolve
def prove_airgap
gitlab_ip = Resolv.getaddress 'registry.gitlab.com'
<<~CMD
echo "Checking airgapped connectivity..."
nc -zv -w 10 #{gitlab_ip} 80 && (echo "Airgapped network faulty. Connectivity netcat check failed." && exit 1) || (echo "Connectivity netcat check passed." && exit 0)
wget --retry-connrefused --waitretry=1 --read-timeout=15 --timeout=10 -t 2 http://registry.gitlab.com > /dev/null 2>&1 && (echo "Airgapped network faulty. Connectivity wget check failed." && exit 1) || (echo "Airgapped network confirmed. Connectivity wget check passed." && exit 0)
CMD
end
def add_gitlab_tls_cert
gitlab_tls_certificate = Tempfile.new('gitlab-cert')
gitlab_tls_certificate.write(Runtime::Env.gitlab_tls_certificate)
gitlab_tls_certificate.close
<<~CMD
&& docker cp #{gitlab_tls_certificate.path} #{@name}:/etc/gitlab-runner/certs/gitlab.test.crt
CMD
end
def wait_until_running_and_configured
wait_until_shell_command_matches("docker logs #{@name}", /Configuration loaded/)
end
end
end
end
end
|