gitlab-qa 8.13.1 → 8.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eff4fd2e6e9b9ab05a26c87b04de43cc2724ff6bbfcdfa55309f6ea4dd6ca22f
4
- data.tar.gz: f7c23ec439a8d5bbbcffac5942f9af3bd11761df457d6bd5316dcc2accb14d2e
3
+ metadata.gz: 222f774a1b76d96311b8f50d198073376ec3a1c3728a85c181df3c7334635cc2
4
+ data.tar.gz: 76038a8e5fb395209798fae12d58b29b297d4ea7b62b1227867b48547fa832e8
5
5
  SHA512:
6
- metadata.gz: a796e6144671878b4940c6cd529abe4bff1f2b38fe06914c069c4291932d27c2b7527603a625d5a6631f42131e87d48bd63773b7abc62a55628f006863f3acab
7
- data.tar.gz: eab90710e729b81e2ba9716462327bf770289c17c197f7743b79fb88023c6711e84751f1bb02fd62414f2ff1ec327b0e318eac060fba28f3ebaade42ee0b5847
6
+ metadata.gz: b52cf9e0f2e4ac6b7650c08cbbdc20428cf97dcb8ec4425c10d5b20c5b0b60c324336f6b39c82c01ff6ccb3a0ecc934204288dc76ceb1f677dfb7f55da73fca5
7
+ data.tar.gz: e315e743dfd37f56cde0e7eff20ae757a7bb8f254cdea861871f22fffb36e58061bbe93a213036207efc685899ad04886374e7fd497ea4bf4b31251d1b1c0071
@@ -0,0 +1,23 @@
1
+ ce:airgapped:
2
+ extends:
3
+ - .rules:ce-never-when-triggered-by-feature-flag-definition-change
4
+ - .test
5
+ - .high-capacity
6
+ - .ce-variables
7
+ - .rspec-report-opts
8
+ variables:
9
+ QA_SCENARIO: "Test::Instance::Airgapped"
10
+ QA_RSPEC_TAGS: "--tag smoke"
11
+
12
+ ee:airgapped:
13
+ extends:
14
+ - .rules:ee-never-when-triggered-by-feature-flag-definition-change
15
+ - .test
16
+ - .high-capacity
17
+ - .ee-variables
18
+ - .rspec-report-opts
19
+ variables:
20
+ QA_SCENARIO: "Test::Instance::Airgapped"
21
+ QA_RSPEC_TAGS: "--tag smoke"
22
+
23
+
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (8.13.1)
4
+ gitlab-qa (8.14.0)
5
5
  activesupport (~> 6.1)
6
6
  gitlab (~> 4.18.0)
7
7
  http (~> 5.0)
@@ -95,12 +95,13 @@ All environment variables used by GitLab QA should be defined in [`lib/gitlab/qa
95
95
  | `JIRA_ADMIN_PASSWORD` |- | Password for authenticating with Jira server as admin. | No|
96
96
  | `CACHE_NAMESPACE_NAME` | `true` | Cache namespace name for groups. | No|
97
97
  | `DEPLOY_VERSION` |- | The version of GitLab being tested against. | No|
98
- | `GITLAB_QA_USER_AGENT` |- | The browser user-agent to use instead of the default Chrome user-agent. | No|
98
+ | `GITLAB_QA_USER_AGENT` |- | The browser user-agent to use instead of the default Chrome user-agent. When set to the appropriate value (stored in 1Password), this allows tests to bypass certain login challenges (e.g., reCAPTCHA and ArkoseLabs). | No|
99
99
  | `GEO_FAILOVER` | `false` | Set to `true` when a Geo secondary site has been promoted to a Geo primary site. | No|
100
100
  | `GITLAB_INITIAL_ROOT_PASSWORD` | `5iveL!fe` | Initial root password for Omnibus installations | No|
101
101
  | `COLORIZED_LOGS` | `false` | Colors GitLab QA and test logs to improve readability | No|
102
102
  | `QA_DOCKER_ADD_HOSTS` |- | Comma separated list of hosts to add to /etc/hosts in docker container | No|
103
103
  | `FIPS` |- | Set to `1` or `true` to indicate that the test is running under FIPS mode | No|
104
+ | `JH_ENV` | `false` | Set to `true` to indicate tests or scenarios are running under JH env | No|
104
105
 
105
106
  ## [Supported Remote Grid environment variables](./running_against_remote_grid.md)
106
107
 
@@ -7,7 +7,7 @@ module Gitlab
7
7
  include Scenario::Actable
8
8
 
9
9
  attr_reader :docker
10
- attr_accessor :volumes, :ports, :network, :environment, :runner_network
10
+ attr_accessor :volumes, :ports, :network, :environment, :runner_network, :airgapped_network
11
11
  attr_writer :name, :exec_commands
12
12
 
13
13
  def initialize
@@ -72,15 +72,22 @@ module Gitlab
72
72
  end
73
73
 
74
74
  def prepare_network
75
- if runner_network && !docker.network_exists?(runner_network) # rubocop:disable Style/IfUnlessModifier
76
- docker.network_create("--driver=bridge --internal #{runner_network}")
77
- end
75
+ prepare_airgapped_network
76
+ prepare_runner_network
78
77
 
79
78
  return if docker.network_exists?(network)
80
79
 
81
80
  docker.network_create(network)
82
81
  end
83
82
 
83
+ def prepare_airgapped_network
84
+ docker.network_create("--driver=bridge --internal #{network}") if airgapped_network && !docker.network_exists?(network)
85
+ end
86
+
87
+ def prepare_runner_network
88
+ docker.network_create("--driver=bridge --internal #{runner_network}") if runner_network && !docker.network_exists?(runner_network)
89
+ end
90
+
84
91
  def prepare_docker_container
85
92
  return unless docker.container_exists?(name)
86
93
 
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class Gitaly < Base
7
+ extend Forwardable
8
+ using Rainbow
9
+ attr_reader :release
10
+ attr_accessor :gitaly_port, :gitlab_name, :cluster_config
11
+ attr_writer :name
12
+
13
+ def_delegators :release, :tag, :image, :edition
14
+
15
+ def initialize
16
+ super
17
+ self.release = 'EE'
18
+ @cluster_config = Component::GitalyCluster::GitalyClusterConfig.new
19
+ @gitaly_port = 8075
20
+ @ports = [gitaly_port]
21
+ end
22
+
23
+ def name
24
+ @name || "gitaly-#{SecureRandom.hex(4)}"
25
+ end
26
+
27
+ def release=(release)
28
+ @release = QA::Release.new(release)
29
+ end
30
+
31
+ def reconfigure
32
+ setup_omnibus
33
+ @docker.attach(name) do |line, wait|
34
+ # TODO, workaround which allows to detach from the container
35
+ break if /gitlab Reconfigured!/.match?(line)
36
+ end
37
+ end
38
+
39
+ def setup_omnibus
40
+ @docker.write_files(name) do |f|
41
+ f.write('/etc/gitlab/gitlab.rb', gitaly_omnibus_configuration)
42
+ end
43
+ end
44
+
45
+ def process_exec_commands
46
+ exec_commands << Support::ConfigScripts.add_git_server_hooks(docker, name)
47
+
48
+ commands = exec_commands.flatten.uniq
49
+ return if commands.empty?
50
+
51
+ Runtime::Logger.info("Running exec_commands...")
52
+ commands.each { |command| docker.exec(name, command) }
53
+ end
54
+
55
+ def gitaly_omnibus_configuration
56
+ <<~OMNIBUS
57
+ #{GitalyCluster.disable_other_omnibus_services}
58
+ praefect['enable'] = false;
59
+ prometheus['enable'] = true;
60
+ gitaly['enable'] = true;
61
+ gitaly['listen_addr'] = '0.0.0.0:#{gitaly_port}';
62
+ gitaly['prometheus_listen_addr'] = '0.0.0.0:9236';
63
+ gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN';
64
+ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
65
+ gitlab_rails['internal_api_url'] = 'http://#{cluster_config.gitlab_name}.#{cluster_config.network}';
66
+ git_data_dirs({
67
+ '#{cluster_config.primary_node_name}' => {
68
+ 'path' => '/var/opt/gitlab/git-data'
69
+ },
70
+ '#{cluster_config.secondary_node_name}' => {
71
+ 'path' => '/var/opt/gitlab/git-data'
72
+ },
73
+ '#{cluster_config.tertiary_node_name}' => {
74
+ 'path' => '/var/opt/gitlab/git-data'
75
+ }
76
+ });
77
+ OMNIBUS
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class GitalyCluster
7
+ class GitalyClusterConfig
8
+ attr_accessor :gitlab_name, :network, :airgapped_network,
9
+ :praefect_node_name, :praefect_port,
10
+ :primary_node_name, :primary_node_port,
11
+ :secondary_node_name, :secondary_node_port,
12
+ :tertiary_node_name, :tertiary_node_port,
13
+ :database_node_name, :database_port
14
+
15
+ attr_reader :praefect_addr, :primary_node_addr, :secondary_node_addr, :tertiary_node_addr, :database_node_addr
16
+
17
+ def initialize(params = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
18
+ @gitlab_name = params[:gitlab_name] || 'gitlab-gitaly-cluster'
19
+ @network = params[:network] || 'test'
20
+ @airgapped_network = params[:airgapped_network] || false
21
+
22
+ @praefect_node_name = params[:praefect_node_name] || 'praefect'
23
+ @praefect_port = params[:praefect_port] || 2305
24
+
25
+ @primary_node_name = params[:primary_node_name] || 'gitaly1'
26
+ @primary_node_port = params[:primary_node_port] || 8075
27
+
28
+ @secondary_node_name = params[:secondary_node_name] || 'gitaly2'
29
+ @secondary_node_port = params[:secondary_node_port] || 8075
30
+
31
+ @tertiary_node_name = params[:tertiary_node_name] || 'gitaly3'
32
+ @tertiary_node_port = params[:tertiary_node_port] || 8075
33
+
34
+ @database_node_name = params[:database_node_name] || 'postgres'
35
+ @database_port = params[:database_port] || 5432
36
+
37
+ @praefect_addr = "#{praefect_node_name}.#{network}"
38
+ @primary_node_addr = "#{primary_node_name}.#{network}"
39
+ @secondary_node_addr = "#{secondary_node_name}.#{network}"
40
+ @tertiary_node_addr = "#{tertiary_node_name}.#{network}"
41
+ @database_node_addr = "#{database_node_name}.#{network}"
42
+ end
43
+ end
44
+
45
+ include Scenario::Actable
46
+ using Rainbow
47
+
48
+ attr_accessor :release, :exec_commands, :gitlab_name, :config
49
+ attr_reader :gitaly_primary_node, :gitaly_secondary_node, :gitaly_tertiary_node, :praefect_node, :database_node
50
+
51
+ def initialize(config = GitalyClusterConfig.new)
52
+ @spec_suite = 'Test::Instance::All'
53
+ @env = {}
54
+ @tag = 'gitaly_cluster'
55
+ @release = 'EE'
56
+ @config = config
57
+ end
58
+
59
+ # @param [Boolean] parallel_gitaly controls whether we start gitaly nodes in parallel to improve startup time
60
+ def instance(parallel_gitaly = false)
61
+ run_gitaly_cluster(QA::Release.new(release), parallel_gitaly)
62
+ end
63
+
64
+ # @param [Boolean] parallel_gitaly controls whether we start gitaly nodes in parallel to improve startup time
65
+ def run_gitaly_cluster(release, parallel_gitaly = false)
66
+ # This also ensure that the docker network is created here, avoiding any potential race conditions later
67
+ # if the gitaly-cluster and GitLab containers attempt to create a network in parallel
68
+ @database_node = postgres
69
+
70
+ Thread.new do
71
+ Thread.current.abort_on_exception = true
72
+ start_gitaly_cluster(release, parallel_gitaly)
73
+ end
74
+ end
75
+
76
+ # @param [Boolean] parallel_gitaly controls whether we start gitaly nodes in parallel to improve startup time
77
+ def start_gitaly_cluster(release, parallel_gitaly = false) # rubocop:disable Metrics/AbcSize
78
+ Runtime::Logger.info("Starting Gitaly Cluster")
79
+
80
+ if parallel_gitaly
81
+ threads = []
82
+ threads << Thread.new { @gitaly_primary_node = gitaly(config.primary_node_name, config.primary_node_port, release) }
83
+ threads << Thread.new { @gitaly_secondary_node = gitaly(config.secondary_node_name, config.secondary_node_port, release) }
84
+ threads << Thread.new { @gitaly_tertiary_node = gitaly(config.tertiary_node_name, config.tertiary_node_port, release) }
85
+ threads.each(&:join)
86
+ else
87
+ @gitaly_primary_node = gitaly(config.primary_node_name, config.primary_node_port, release)
88
+ @gitaly_secondary_node = gitaly(config.secondary_node_name, config.secondary_node_port, release)
89
+ @gitaly_tertiary_node = gitaly(config.tertiary_node_name, config.tertiary_node_port, release)
90
+ end
91
+
92
+ @praefect_node = praefect(release)
93
+ Runtime::Logger.info("Gitaly Cluster Ready")
94
+ end
95
+
96
+ def postgres
97
+ Component::PostgreSQL.new.tap do |sql|
98
+ sql.name = config.database_node_name
99
+ sql.airgapped_network = config.airgapped_network
100
+ sql.network = config.network
101
+ sql.instance(skip_teardown: true) do
102
+ sql.run_psql '-d template1 -c "CREATE DATABASE praefect_production OWNER postgres"'
103
+ end
104
+ end
105
+ end
106
+
107
+ def gitaly(gitaly_name, port, release) # rubocop:disable Metrics/AbcSize
108
+ Component::Gitaly.new.tap do |gitaly|
109
+ gitaly.cluster_config = config
110
+ gitaly.release = release
111
+ gitaly.name = gitaly_name
112
+ gitaly.gitaly_port = port
113
+ gitaly.airgapped_network = config.airgapped_network
114
+ gitaly.network = config.network
115
+ gitaly.gitlab_name = config.gitlab_name
116
+ gitaly.instance(skip_teardown: true)
117
+ end
118
+ end
119
+
120
+ def praefect(release)
121
+ Component::Praefect.new.tap do |praefect|
122
+ praefect.cluster_config = config
123
+ praefect.name = config.praefect_node_name
124
+ praefect.airgapped_network = config.airgapped_network
125
+ praefect.network = config.network
126
+ praefect.release = release
127
+ praefect.instance(skip_teardown: true)
128
+ end
129
+ end
130
+
131
+ # Helper configuration for omnibus config to disable all non GitalyCluster related omnibus services
132
+ def self.disable_other_omnibus_services
133
+ <<~OMNIBUS
134
+ postgresql['enable'] = false;
135
+ redis['enable'] = false;
136
+ nginx['enable'] = false;
137
+ grafana['enable'] = false;
138
+ puma['enable'] = false;
139
+ sidekiq['enable'] = false;
140
+ gitlab_workhorse['enable'] = false;
141
+ gitlab_rails['rake_cache_clear'] = false;
142
+ gitlab_rails['auto_migrate'] = false;
143
+ gitlab_exporter['enable'] = false;
144
+ OMNIBUS
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -202,7 +202,7 @@ module Gitlab
202
202
  exec_commands << seed_admin_token_command if seed_admin_token
203
203
  exec_commands << seed_test_data_command if seed_db
204
204
  exec_commands << Runtime::Scenario.omnibus_exec_commands
205
- exec_commands << add_git_server_hooks unless skip_server_hooks
205
+ exec_commands << Support::ConfigScripts.add_git_server_hooks(docker, name) unless skip_server_hooks
206
206
 
207
207
  commands = exec_commands.flatten.uniq
208
208
  return if commands.empty?
@@ -280,28 +280,6 @@ module Gitlab
280
280
  ["gitlab-rails runner #{DATA_PATH}/admin_access_token_seed.rb"]
281
281
  end
282
282
 
283
- def add_git_server_hooks
284
- global_server_prereceive_hook = <<~SCRIPT
285
- #!/usr/bin/env bash
286
-
287
- if [[ \\\$GL_PROJECT_PATH =~ 'reject-prereceive' ]]; then
288
- echo 'GL-HOOK-ERR: Custom error message rejecting prereceive hook for projects with GL_PROJECT_PATH matching pattern reject-prereceive'
289
- exit 1
290
- fi
291
- SCRIPT
292
-
293
- [
294
- @docker.exec(name, 'mkdir -p /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d'),
295
- @docker.write_files(name) do |f|
296
- f.write(
297
- '/opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/pre-receive.d',
298
- global_server_prereceive_hook, false
299
- )
300
- end,
301
- @docker.exec(name, 'chmod +x /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/*')
302
- ]
303
- end
304
-
305
283
  class Availability
306
284
  def initialize(name, relative_path: '', scheme: 'http', protocol_port: 80)
307
285
  @docker = Docker::Engine.new
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class Praefect < Base
7
+ extend Forwardable
8
+ using Rainbow
9
+ attr_reader :release
10
+ attr_accessor :cluster_config
11
+ attr_writer :name
12
+
13
+ def_delegators :release, :tag, :image, :edition
14
+
15
+ def initialize
16
+ super
17
+ self.release = 'EE'
18
+ @cluster_config = Component::GitalyCluster::GitalyClusterConfig.new
19
+ @ports = [cluster_config.praefect_port]
20
+ end
21
+
22
+ def name
23
+ @name || "praefect-#{SecureRandom.hex(4)}"
24
+ end
25
+
26
+ def release=(release)
27
+ @release = QA::Release.new(release)
28
+ end
29
+
30
+ def reconfigure
31
+ setup_omnibus
32
+ @docker.attach(name) do |line|
33
+ # TODO, workaround which allows to detach from the container
34
+ break if /gitlab Reconfigured!/.match?(line)
35
+ end
36
+ end
37
+
38
+ def setup_omnibus
39
+ @docker.write_files(name) do |f|
40
+ f.write('/etc/gitlab/gitlab.rb', praefect_omnibus_configuration)
41
+ end
42
+ end
43
+
44
+ def wait_until_ready
45
+ @docker.exec(name, 'praefect -config /var/opt/gitlab/praefect/cluster_config.toml check || true') do |resp|
46
+ Runtime::Logger.info(resp)
47
+ break if /All checks passed/.match?(line)
48
+ end
49
+ end
50
+
51
+ def praefect_omnibus_configuration # rubocop:disable Metrics/AbcSize
52
+ <<~OMNIBUS
53
+ #{GitalyCluster.disable_other_omnibus_services}
54
+ gitaly['enable'] = false;
55
+ prometheus['enable'] = true;
56
+ praefect['enable'] = true;
57
+ praefect['listen_addr'] = '0.0.0.0:#{cluster_config.praefect_port}';
58
+ praefect['prometheus_listen_addr'] = '0.0.0.0:9652';
59
+ praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN';
60
+ praefect['reconciliation_scheduling_interval'] = '10s';
61
+ praefect['database_host'] = '#{cluster_config.database_node_addr}';
62
+ praefect['database_user'] = 'postgres';
63
+ praefect['database_port'] = #{cluster_config.database_port};
64
+ praefect['database_password'] = 'SQL_PASSWORD';
65
+ praefect['database_dbname'] = 'praefect_production';
66
+ praefect['database_sslmode'] = 'disable';
67
+ praefect['database_direct_host'] = '#{cluster_config.database_node_addr}';
68
+ praefect['database_direct_port'] = #{cluster_config.database_port};
69
+ praefect['virtual_storages'] = {
70
+ 'default' => {
71
+ 'nodes' => {
72
+ '#{cluster_config.primary_node_name}' => {
73
+ 'address' => 'tcp://#{cluster_config.primary_node_addr}:#{cluster_config.primary_node_port}',
74
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
75
+ },
76
+ '#{cluster_config.secondary_node_name}' => {
77
+ 'address' => 'tcp://#{cluster_config.secondary_node_addr}:#{cluster_config.secondary_node_port}',
78
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
79
+ },
80
+ '#{cluster_config.tertiary_node_name}' => {
81
+ 'address' => 'tcp://#{cluster_config.tertiary_node_addr}:#{cluster_config.tertiary_node_port}',
82
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
83
+ }
84
+ }
85
+ }
86
+ };
87
+ OMNIBUS
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -7,7 +7,7 @@ module Gitlab
7
7
  class Release
8
8
  CANONICAL_REGEX = /
9
9
  \A
10
- (?<edition>ce|ee)
10
+ (?<edition>ce|ee|jh)
11
11
  (-qa)?
12
12
  (:(?<tag>.+))?
13
13
  \z
@@ -18,7 +18,7 @@ module Gitlab
18
18
  (?<registry>[^/:]+(:(?<port>\d+))?)
19
19
  (?<project>.+)
20
20
  gitlab-
21
- (?<edition>ce|ee)
21
+ (?<edition>ce|ee|jh)
22
22
  )
23
23
  (-qa)?
24
24
  (:(?<tag>.+))?
@@ -37,7 +37,7 @@ module Gitlab
37
37
  # version
38
38
  DEV_OFFICIAL_TAG_REGEX = /
39
39
  \A
40
- (?<version>\d+\.\d+.\d+(?:-rc\d+)?)-(?<edition>ce|ee)
40
+ (?<version>\d+\.\d+.\d+(?:-rc\d+)?)-(?<edition>ce|ee|jh)
41
41
  \z
42
42
  /xi.freeze
43
43
 
@@ -57,8 +57,8 @@ module Gitlab
57
57
 
58
58
  DEFAULT_TAG = 'latest'
59
59
  DEFAULT_CANONICAL_TAG = 'nightly'
60
- DEV_REGISTRY = 'dev.gitlab.org:5005'
61
- COM_REGISTRY = 'registry.gitlab.com'
60
+ DEV_REGISTRY = Gitlab::QA::Runtime::Env.qa_dev_registry
61
+ COM_REGISTRY = Gitlab::QA::Runtime::Env.qa_com_registry
62
62
 
63
63
  InvalidImageNameError = Class.new(RuntimeError)
64
64
 
@@ -138,7 +138,8 @@ module Gitlab
138
138
  'NO_ADMIN' => :no_admin,
139
139
  'CHROME_DISABLE_DEV_SHM' => :chrome_disable_dev_shm,
140
140
  'COLORIZED_LOGS' => :colorized_logs,
141
- 'FIPS' => :fips
141
+ 'FIPS' => :fips,
142
+ 'JH_ENV' => :jh_env
142
143
  }.freeze
143
144
 
144
145
  ENV_VARIABLES.each do |env_name, method_name|
@@ -357,6 +358,18 @@ module Gitlab
357
358
  (env_var_value_if_defined('QA_DOCKER_ADD_HOSTS') || '').split(',')
358
359
  end
359
360
 
361
+ def jh_env?
362
+ enabled?(env_var_value_if_defined('JH_ENV'), default: false)
363
+ end
364
+
365
+ def qa_dev_registry
366
+ env_var_value_if_defined('QA_DEV_REGISTRY') || 'dev.gitlab.org:5005'
367
+ end
368
+
369
+ def qa_com_registry
370
+ env_var_value_if_defined('QA_COM_REGISTRY') || 'registry.gitlab.com'
371
+ end
372
+
360
373
  private
361
374
 
362
375
  def enabled?(value, default: true)
@@ -7,51 +7,31 @@ module Gitlab
7
7
  module Instance
8
8
  class Airgapped < Scenario::Template
9
9
  require 'resolv'
10
- attr_accessor :commands
10
+ attr_reader :config, :gitlab_air_gap_commands
11
11
 
12
12
  def initialize
13
- gitlab_ip = Resolv.getaddress('registry.gitlab.com')
14
- @commands = <<~AIRGAP_AND_VERIFY_COMMAND.split(/\n+/)
15
- # Should not fail before airgapping due to eg. DNS failure
16
- # Ping and wget check
17
- apt-get update && apt-get install -y iptables nmap
18
- nmap -sT #{gitlab_ip} -p 80 && (echo \"Regular connectivity nmap check passed.\" && exit 0) || (echo \"Regular connectivity nmap check failed.\" && exit 1)
19
- echo "Checking regular connectivity..." \
20
- && wget --retry-connrefused --waitretry=1 --read-timeout=15 --timeout=10 -t 2 http://registry.gitlab.com > /dev/null 2>&1 \
21
- && (echo "Regular connectivity wget check passed." && exit 0) || (echo "Regular connectivity wget check failed." && exit 1)
22
-
23
- iptables -P INPUT DROP && iptables -P OUTPUT DROP
24
- iptables -A INPUT -i lo -j ACCEPT && iptables -A OUTPUT -o lo -j ACCEPT # LOOPBACK
25
- iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
26
- iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
27
-
28
- # Jenkins on port 8080 and 50000
29
- iptables -A OUTPUT -p tcp -m tcp --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT \
30
- && iptables -A OUTPUT -p tcp -m tcp --dport 50000 -m state --state NEW,ESTABLISHED -j ACCEPT
31
- iptables -A OUTPUT -p tcp -m tcp --sport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
32
- iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
33
- iptables -A OUTPUT -p tcp -m tcp --sport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
34
- iptables -A INPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
35
-
36
- # Should now fail to ping and wget, port 80 should be open
37
- nmap -sT #{gitlab_ip} -p 80 && (echo \"Airgapped network faulty. Connectivity nmap check failed.\" && exit 1) || (echo \"Connectivity nmap check passed.\" && exit 0)
38
- nmap -sT 127.0.0.1 -p 22 && (echo "Airgapped connectivity port 22 check passed." && exit 0) || (echo "Airgapped connectivity port 22 check failed." && exit 1)
39
- nmap -sT 10 127.0.0.1 -p 80 && (echo "Airgapped connectivity port 80 check passed." && exit 0) || (echo "Airgapped connectivity port 80 check failed." && exit 1)
40
- echo "Checking airgapped connectivity..." \
41
- && wget --retry-connrefused --waitretry=1 --read-timeout=15 --timeout=10 -t 2 http://registry.gitlab.com > /dev/null 2>&1 \
42
- && (echo "Airgapped network faulty. Connectivity wget check failed." && exit 1) || (echo "Airgapped network confirmed. Connectivity wget check passed." && exit 0)
43
- AIRGAP_AND_VERIFY_COMMAND
13
+ @config = Component::GitalyCluster::GitalyClusterConfig.new(
14
+ airgapped_network: true,
15
+ network: 'airgapped'
16
+ )
44
17
  end
45
18
 
46
19
  def perform(release, *rspec_args)
47
20
  Component::Gitlab.perform do |gitlab|
21
+ cluster = Component::GitalyCluster.perform do |cluster|
22
+ cluster.config = @config
23
+ cluster.instance
24
+ end
25
+ gitlab.name = config.gitlab_name
48
26
  gitlab.release = release
49
- gitlab.network = 'test'
50
- gitlab.runner_network = 'airgapped'
51
- gitlab.exec_commands = @commands
27
+ gitlab.airgapped_network = true
28
+ gitlab.network = config.network
29
+ gitlab.omnibus_configuration << gitlab_omnibus_configuration
30
+ gitlab.skip_availability_check = true # airgapped environment cannot be pinged to check health
52
31
  rspec_args << "--" unless rspec_args.include?('--')
53
32
  rspec_args << %w[--tag ~orchestrated]
54
33
  gitlab.instance do
34
+ cluster.join
55
35
  Component::Specs.perform do |specs|
56
36
  specs.suite = 'Test::Instance::Airgapped'
57
37
  specs.release = gitlab.release
@@ -62,6 +42,45 @@ module Gitlab
62
42
  end
63
43
  end
64
44
  end
45
+
46
+ private
47
+
48
+ def gitlab_omnibus_configuration
49
+ <<~OMNIBUS
50
+ external_url 'http://#{config.gitlab_name}.#{config.network}';
51
+
52
+ git_data_dirs({
53
+ 'default' => {
54
+ 'gitaly_address' => 'tcp://#{config.praefect_addr}:#{config.praefect_port}',
55
+ 'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
56
+ }
57
+ });
58
+ gitaly['enable'] = false;
59
+ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
60
+ prometheus['scrape_configs'] = [
61
+ {
62
+ 'job_name' => 'praefect',
63
+ 'static_configs' => [
64
+ 'targets' => [
65
+ '#{config.praefect_addr}:9652'
66
+ ]
67
+ ]
68
+ },
69
+ {
70
+ 'job_name' => 'praefect-gitaly',
71
+ 'static_configs' => [
72
+ 'targets' => [
73
+ '#{config.primary_node_addr}:9236',
74
+ '#{config.secondary_node_addr}:9236',
75
+ '#{config.tertiary_node_addr}:9236'
76
+ ]
77
+ ]
78
+ }
79
+ ];
80
+ grafana['disable_login_form'] = false;
81
+ grafana['admin_password'] = 'GRAFANA_ADMIN_PASSWORD';
82
+ OMNIBUS
83
+ end
65
84
  end
66
85
  end
67
86
  end
@@ -6,67 +6,24 @@ module Gitlab
6
6
  module Test
7
7
  module Integration
8
8
  class GitalyCluster < Scenario::Template
9
- attr_reader :gitlab_name, :spec_suite
10
-
11
- def initialize # rubocop:disable Metrics/AbcSize
12
- @gitlab_name = 'gitlab-gitaly-cluster'
13
-
14
- @primary_node_name = 'gitaly1'
15
- @primary_node_addr = "#{@primary_node_name}.#{@network}"
16
- @primary_node_port = 8075
17
-
18
- @secondary_node_name = 'gitaly2'
19
- @secondary_node_addr = "#{@secondary_node_name}.#{@network}"
20
- @secondary_node_port = 8075
21
-
22
- @tertiary_node_name = 'gitaly3'
23
- @tertiary_node_addr = "#{@tertiary_node_name}.#{@network}"
24
- @tertiary_node_port = 8075
25
-
26
- @praefect_node_name = 'praefect'
27
- @praefect_port = 2305
28
- @praefect_addr = "#{@praefect_node_name}.#{@network}"
29
-
30
- @database = 'postgres'
31
- @database_port = 5432
32
- @database_addr = "#{@database}.#{@network}"
9
+ attr_reader :gitlab_name, :spec_suite, :name, :config
33
10
 
11
+ def initialize
34
12
  @spec_suite = 'Test::Instance::All'
35
- @network = 'test'
36
13
  @env = {}
37
14
  @tag = 'gitaly_cluster'
15
+ @config = Component::GitalyCluster::GitalyClusterConfig.new
38
16
  end
39
17
 
40
18
  def perform(release, *rspec_args)
41
- run_gitaly_cluster(release, rspec_args)
42
- ensure
43
- @praefect_node&.teardown
44
- @sql_node&.teardown
45
- @gitaly_primary_node&.teardown
46
- @gitaly_secondary_node&.teardown
47
- @gitaly_tertiary_node&.teardown
48
- end
49
-
50
- def run_gitaly_cluster(release, rspec_args) # rubocop:disable Metrics/AbcSize
51
- # The postgres container starts in seconds so not essential to parallelize it
52
- # This also ensure that the docker network is created here, avoiding any potential race conditions later
53
- # if the gitaly-cluster and GitLab containers attempt to create a network in parallel
54
- @sql_node = postgres
55
-
56
- gitaly_cluster = Thread.new do
57
- Thread.current.abort_on_exception = true
58
- start_gitaly_cluster(release)
59
- end
60
-
61
19
  Component::Gitlab.perform do |gitlab|
62
20
  gitlab.release = QA::Release.new(release)
63
- gitlab.name = gitlab_name
64
- gitlab.network = @network
65
-
21
+ gitlab.name = config.gitlab_name
22
+ gitlab.network = config.network
66
23
  gitlab.omnibus_configuration << gitlab_omnibus_configuration
24
+ cluster = Component::GitalyCluster.perform(&:instance)
67
25
  gitlab.instance do
68
- # Wait for gitaly cluster to finish booting, before attempting to run specs
69
- gitaly_cluster.join
26
+ cluster.join
70
27
  Runtime::Logger.info('Running Gitaly Cluster specs!')
71
28
 
72
29
  if @tag
@@ -87,100 +44,13 @@ module Gitlab
87
44
 
88
45
  private
89
46
 
90
- def start_gitaly_cluster(release)
91
- Runtime::Logger.info("Starting Gitaly Cluster")
92
- @gitaly_primary_node = gitaly(@primary_node_name, @primary_node_port, release)
93
- @gitaly_secondary_node = gitaly(@secondary_node_name, @secondary_node_port, release)
94
- @gitaly_tertiary_node = gitaly(@tertiary_node_name, @tertiary_node_port, release)
95
-
96
- @praefect_node = praefect(@praefect_node_name, release)
97
- Runtime::Logger.info("Gitaly Cluster Ready")
98
- end
99
-
100
- def disable_other_services
101
- <<~OMNIBUS
102
- postgresql['enable'] = false;
103
- redis['enable'] = false;
104
- nginx['enable'] = false;
105
- prometheus['enable'] = false;
106
- grafana['enable'] = false;
107
- puma['enable'] = false;
108
- sidekiq['enable'] = false;
109
- gitlab_workhorse['enable'] = false;
110
- gitlab_rails['rake_cache_clear'] = false;
111
- gitlab_rails['auto_migrate'] = false;
112
- OMNIBUS
113
- end
114
-
115
- def praefect_omnibus_configuration
116
- <<~OMNIBUS
117
- #{disable_other_services}
118
- gitaly['enable'] = false;
119
- praefect['enable'] = true;
120
- praefect['listen_addr'] = '0.0.0.0:#{@praefect_port}';
121
- praefect['prometheus_listen_addr'] = '0.0.0.0:9652';
122
- praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN';
123
- praefect['reconciliation_scheduling_interval'] = '10s';
124
- praefect['database_host'] = '#{@database_addr}';
125
- praefect['database_user'] = 'postgres';
126
- praefect['database_port'] = #{@database_port};
127
- praefect['database_password'] = 'SQL_PASSWORD';
128
- praefect['database_dbname'] = 'praefect_production';
129
- praefect['database_sslmode'] = 'disable';
130
- praefect['database_direct_host'] = '#{@database_addr}';
131
- praefect['database_direct_port'] = #{@database_port};
132
- praefect['virtual_storages'] = {
133
- 'default' => {
134
- 'nodes' => {
135
- '#{@primary_node_name}' => {
136
- 'address' => 'tcp://#{@primary_node_addr}:#{@primary_node_port}',
137
- 'token' => 'PRAEFECT_INTERNAL_TOKEN'
138
- },
139
- '#{@secondary_node_name}' => {
140
- 'address' => 'tcp://#{@secondary_node_addr}:#{@secondary_node_port}',
141
- 'token' => 'PRAEFECT_INTERNAL_TOKEN'
142
- },
143
- '#{@tertiary_node_name}' => {
144
- 'address' => 'tcp://#{@tertiary_node_addr}:#{@tertiary_node_port}',
145
- 'token' => 'PRAEFECT_INTERNAL_TOKEN'
146
- }
147
- }
148
- }
149
- };
150
- OMNIBUS
151
- end
152
-
153
- def gitaly_omnibus_configuration(listen_port)
154
- <<~OMNIBUS
155
- #{disable_other_services.sub(/(prometheus\['enable'\]) = false/, '\1 = true')}
156
- prometheus_monitoring['enable'] = false;
157
- gitaly['enable'] = true;
158
- gitaly['listen_addr'] = '0.0.0.0:#{listen_port}';
159
- gitaly['prometheus_listen_addr'] = '0.0.0.0:9236';
160
- gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN';
161
- gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
162
- gitlab_rails['internal_api_url'] = 'http://#{@gitlab_name}.#{@network}';
163
- git_data_dirs({
164
- '#{@primary_node_name}' => {
165
- 'path' => '/var/opt/gitlab/git-data'
166
- },
167
- '#{@secondary_node_name}' => {
168
- 'path' => '/var/opt/gitlab/git-data'
169
- },
170
- '#{@tertiary_node_name}' => {
171
- 'path' => '/var/opt/gitlab/git-data'
172
- }
173
- });
174
- OMNIBUS
175
- end
176
-
177
47
  def gitlab_omnibus_configuration
178
48
  <<~OMNIBUS
179
- external_url 'http://#{@gitlab_name}.#{@network}';
49
+ external_url 'http://#{config.gitlab_name}.#{config.network}';
180
50
 
181
51
  git_data_dirs({
182
52
  'default' => {
183
- 'gitaly_address' => 'tcp://#{@praefect_addr}:#{@praefect_port}',
53
+ 'gitaly_address' => 'tcp://#{config.praefect_addr}:#{config.praefect_port}',
184
54
  'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
185
55
  }
186
56
  });
@@ -191,7 +61,7 @@ module Gitlab
191
61
  'job_name' => 'praefect',
192
62
  'static_configs' => [
193
63
  'targets' => [
194
- '#{@praefect_node_name}.#{@network}:9652'
64
+ '#{config.praefect_addr}:9652'
195
65
  ]
196
66
  ]
197
67
  },
@@ -199,9 +69,9 @@ module Gitlab
199
69
  'job_name' => 'praefect-gitaly',
200
70
  'static_configs' => [
201
71
  'targets' => [
202
- '#{@primary_node_name}.#{@network}:9236',
203
- '#{@secondary_node_name}.#{@network}:9236',
204
- '#{@tertiary_node_name}.#{@network}:9236'
72
+ '#{config.primary_node_addr}:9236',
73
+ '#{config.secondary_node_addr}:9236',
74
+ '#{config.tertiary_node_addr}:9236'
205
75
  ]
206
76
  ]
207
77
  }
@@ -210,42 +80,6 @@ module Gitlab
210
80
  grafana['admin_password'] = 'GRAFANA_ADMIN_PASSWORD';
211
81
  OMNIBUS
212
82
  end
213
-
214
- def praefect(name, release)
215
- Component::Gitlab.new.tap do |praefect|
216
- praefect.release = QA::Release.new(release)
217
- praefect.name = name
218
- praefect.network = @network
219
- praefect.skip_availability_check = true
220
- praefect.seed_admin_token = false
221
-
222
- praefect.omnibus_configuration << praefect_omnibus_configuration
223
-
224
- praefect.instance(skip_teardown: true)
225
- end
226
- end
227
-
228
- def postgres
229
- Component::PostgreSQL.new.tap do |sql|
230
- sql.name = @database
231
- sql.network = @network
232
- sql.instance(skip_teardown: true) do
233
- sql.run_psql '-d template1 -c "CREATE DATABASE praefect_production OWNER postgres"'
234
- end
235
- end
236
- end
237
-
238
- def gitaly(name, port, release)
239
- Component::Gitlab.new.tap do |gitaly|
240
- gitaly.release = QA::Release.new(release)
241
- gitaly.name = name
242
- gitaly.network = @network
243
- gitaly.skip_availability_check = true
244
- gitaly.seed_admin_token = false
245
- gitaly.omnibus_configuration << gitaly_omnibus_configuration(port)
246
- gitaly.instance(skip_teardown: true)
247
- end
248
- end
249
83
  end
250
84
  end
251
85
  end
@@ -15,17 +15,17 @@ module Gitlab
15
15
  @env = { QA_PRAEFECT_REPOSITORY_STORAGE: 'default' }
16
16
  end
17
17
 
18
- def gitlab_omnibus_configuration
18
+ def gitlab_omnibus_configuration # rubocop:disable Metrics/AbcSize
19
19
  <<~OMNIBUS
20
- external_url 'http://#{@gitlab_name}.#{@network}';
20
+ external_url 'http://#{config.gitlab_name}.#{config.network}';
21
21
 
22
22
  git_data_dirs({
23
23
  'default' => {
24
- 'gitaly_address' => 'tcp://#{@praefect_addr}:#{@praefect_port}',
24
+ 'gitaly_address' => 'tcp://#{config.praefect_addr}:#{config.praefect_port}',
25
25
  'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
26
26
  },
27
27
  'gitaly' => {
28
- 'gitaly_address' => 'tcp://#{@gitlab_name}.#{@network}:8075',
28
+ 'gitaly_address' => 'tcp://#{config.gitlab_name}.#{config.network}:8075',
29
29
  'path' => '/var/opt/gitlab/git-data'
30
30
  }
31
31
  });
@@ -45,7 +45,7 @@ module Gitlab
45
45
  'job_name' => 'praefect',
46
46
  'static_configs' => [
47
47
  'targets' => [
48
- '#{@praefect_addr}:9652'
48
+ '#{config.praefect_addr}:9652'
49
49
  ]
50
50
  ]
51
51
  },
@@ -53,9 +53,9 @@ module Gitlab
53
53
  'job_name' => 'praefect-gitaly',
54
54
  'static_configs' => [
55
55
  'targets' => [
56
- '#{@primary_node_addr}:9236',
57
- '#{@secondary_node_addr}:9236',
58
- '#{@tertiary_node_addr}:9236'
56
+ '#{config.primary_node_addr}:9236',
57
+ '#{config.secondary_node_addr}:9236',
58
+ '#{config.tertiary_node_addr}:9236'
59
59
  ]
60
60
  ]
61
61
  }
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Support
6
+ module ConfigScripts
7
+ # Add a git server hooks with a custom error message
8
+ # See https://docs.gitlab.com/ee/administration/server_hooks.html for details
9
+ def self.add_git_server_hooks(docker, name)
10
+ global_server_prereceive_hook = <<~SCRIPT
11
+ #!/usr/bin/env bash
12
+
13
+ if [[ \\\$GL_PROJECT_PATH =~ 'reject-prereceive' ]]; then
14
+ echo 'GL-HOOK-ERR: Custom error message rejecting prereceive hook for projects with GL_PROJECT_PATH matching pattern reject-prereceive'
15
+ exit 1
16
+ fi
17
+ SCRIPT
18
+
19
+ [
20
+ docker.exec(name, 'mkdir -p /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d'),
21
+ docker.write_files(name) do |f|
22
+ f.write(
23
+ '/opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/pre-receive.d',
24
+ global_server_prereceive_hook, false
25
+ )
26
+ end,
27
+ docker.exec(name, 'chmod +x /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/*')
28
+ ]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '8.13.1'
5
+ VERSION = '8.14.0'
6
6
  end
7
7
  end
@@ -23,6 +23,7 @@ class GenerateQAJobs
23
23
  jobs.merge!(load_yml_contents('update', should_automatically_run?('test_instance_all')))
24
24
  jobs.merge!(load_yml_contents('omnibus_upgrade'))
25
25
  jobs.merge!(load_yml_contents('ee_previous_to_ce_update'))
26
+ jobs.merge!(load_yml_contents('airgapped', should_automatically_run?('test_instance_all')))
26
27
  jobs.merge!(load_yml_contents('mattermost', should_automatically_run?('test_integration_mattermost')))
27
28
  jobs.merge!(load_yml_contents('service_ping_disabled', should_automatically_run?('test_integration_servicepingdisabled')))
28
29
  jobs.merge!(load_yml_contents('ldap_no_tls', should_automatically_run?('test_integration_ldapnotls')))
@@ -24,7 +24,7 @@ class LicenseUsageSeed
24
24
 
25
25
  User.create!(
26
26
  email: "#{name}@test.com",
27
- password: 'password',
27
+ password: SecureRandom.hex.slice(0, 16),
28
28
  username: name,
29
29
  name: "User #{name}",
30
30
  confirmed_at: Time.current
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-qa
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.13.1
4
+ version: 8.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-23 00:00:00.000000000 Z
11
+ date: 2022-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -244,6 +244,7 @@ files:
244
244
  - ".dockerignore"
245
245
  - ".gitignore"
246
246
  - ".gitlab-ci.yml"
247
+ - ".gitlab/ci/jobs/airgapped.gitlab-ci.yml"
247
248
  - ".gitlab/ci/jobs/base.gitlab-ci.yml"
248
249
  - ".gitlab/ci/jobs/chaos.gitlab-ci.yml"
249
250
  - ".gitlab/ci/jobs/cloud_activation.gitlab-ci.yml"
@@ -328,6 +329,8 @@ files:
328
329
  - lib/gitlab/qa/component/base.rb
329
330
  - lib/gitlab/qa/component/chaos.rb
330
331
  - lib/gitlab/qa/component/elasticsearch.rb
332
+ - lib/gitlab/qa/component/gitaly.rb
333
+ - lib/gitlab/qa/component/gitaly_cluster.rb
331
334
  - lib/gitlab/qa/component/gitlab.rb
332
335
  - lib/gitlab/qa/component/jira.rb
333
336
  - lib/gitlab/qa/component/ldap.rb
@@ -336,6 +339,7 @@ files:
336
339
  - lib/gitlab/qa/component/mock_server.rb
337
340
  - lib/gitlab/qa/component/opensearch.rb
338
341
  - lib/gitlab/qa/component/postgresql.rb
342
+ - lib/gitlab/qa/component/praefect.rb
339
343
  - lib/gitlab/qa/component/preprod.rb
340
344
  - lib/gitlab/qa/component/production.rb
341
345
  - lib/gitlab/qa/component/release.rb
@@ -436,6 +440,7 @@ files:
436
440
  - lib/gitlab/qa/service/cluster_provider/k3d.rb
437
441
  - lib/gitlab/qa/service/kubernetes_cluster.rb
438
442
  - lib/gitlab/qa/slack/post_to_slack.rb
443
+ - lib/gitlab/qa/support/config_scripts.rb
439
444
  - lib/gitlab/qa/support/get_request.rb
440
445
  - lib/gitlab/qa/support/gitlab_upgrade_path.rb
441
446
  - lib/gitlab/qa/support/gitlab_version_info.rb