spec/gitlab/qa/runtime/env_spec.rb (275 lines of code) (raw):
# frozen_string_literal: true
describe Gitlab::QA::Runtime::Env do
around do |example|
# Reset any already defined env variables (e.g. on CI)
ClimateControl.modify described_class::ENV_VARIABLES.keys.zip([nil]).to_h do
example.run
end
end
shared_examples 'boolean method' do |**kwargs|
it_behaves_like 'boolean method with parameter', kwargs
end
shared_examples 'boolean method with parameter' do |method:, env_key:, default:, param: nil|
context 'when there is an env variable set' do
it 'returns false when falsey values specified' do
ClimateControl.modify(env_key => 'false') do
expect(described_class.public_send(method, *param)).to be_falsey
end
ClimateControl.modify(env_key => 'no') do
expect(described_class.public_send(method, *param)).to be_falsey
end
ClimateControl.modify(env_key => '0') do
expect(described_class.public_send(method, *param)).to be_falsey
end
end
it 'returns true when anything else specified' do
ClimateControl.modify(env_key => 'true') do
expect(described_class.public_send(method, *param)).to be_truthy
end
ClimateControl.modify(env_key => '1') do
expect(described_class.public_send(method, *param)).to be_truthy
end
ClimateControl.modify(env_key => 'anything') do
expect(described_class.public_send(method, *param)).to be_truthy
end
end
end
context 'when there is no env variable set' do
it "returns the default, #{default}" do
ClimateControl.modify(env_key => nil) do
expect(described_class.public_send(method, *param)).to be(default)
end
end
end
end
describe '.skip_pull?' do
it_behaves_like 'boolean method',
method: :skip_pull?,
env_key: 'QA_SKIP_PULL',
default: false
end
describe '.geo_failover?' do
it_behaves_like 'boolean method',
method: :geo_failover?,
env_key: 'GEO_FAILOVER',
default: false
end
describe '.run_id' do
around do |example|
described_class.instance_variable_set(:@run_id, nil)
example.run
described_class.instance_variable_set(:@run_id, nil)
end
it 'returns a unique run id' do
now = Time.now
allow(Time).to receive(:now).and_return(now)
allow(SecureRandom).to receive(:hex).and_return('abc123')
expect(described_class.run_id).to eq "gitlab-qa-run-#{now.strftime('%Y-%m-%d-%H-%M-%S')}-abc123"
expect(described_class.run_id).to eq "gitlab-qa-run-#{now.strftime('%Y-%m-%d-%H-%M-%S')}-abc123"
end
end
describe '.dev_access_token_variable' do
context 'when there is an env variable set' do
around do |example|
ClimateControl.modify(GITLAB_QA_DEV_ACCESS_TOKEN: 'abc123') { example.run }
end
it 'returns directory defined in environment variable' do
expect(described_class.dev_access_token_variable).to eq '$GITLAB_QA_DEV_ACCESS_TOKEN'
end
end
context 'when there is no env variable set' do
around do |example|
ClimateControl.modify(GITLAB_QA_DEV_ACCESS_TOKEN: nil) { example.run }
end
it 'returns a default screenshots directory' do
expect(described_class.dev_access_token_variable).to be_nil
end
end
end
describe '.host_artifacts_dir' do
around do |example|
described_class.instance_variable_set(:@host_artifacts_dir, nil)
example.run
described_class.instance_variable_set(:@host_artifacts_dir, nil)
end
context 'when there is an env variable set' do
around do |example|
ClimateControl.modify(QA_ARTIFACTS_DIR: '/tmp') { example.run }
end
it 'returns directory defined in environment variable' do
expect(described_class.host_artifacts_dir).to eq "/tmp/#{described_class.run_id}"
end
end
context 'when there is no env variable set' do
around do |example|
ClimateControl.modify(QA_ARTIFACTS_DIR: nil) { example.run }
end
it 'returns a default screenshots directory' do
expect(described_class.host_artifacts_dir)
.to eq "/tmp/gitlab-qa/#{described_class.run_id}"
end
end
end
describe '.variables' do
around do |example|
ClimateControl.modify(
GITLAB_USERNAME: 'root',
GITLAB_QA_ACCESS_TOKEN: nil,
EE_LICENSE: nil) { example.run }
end
before do
described_class.user_username = nil
described_class.user_password = nil
described_class.user_type = nil
described_class.gitlab_url = nil
described_class.ee_license = nil
end
context 'with undefined QA_ variables' do
around do |example|
ClimateControl.modify(QA_SOME_TEST_VAR: 'var') { example.run }
end
it 'returns QA_ prefixed variables that are not explicitly defined' do
expect(described_class.variables).to include('QA_SOME_TEST_VAR' => '$QA_SOME_TEST_VAR')
end
end
it 'returns only these delegated variables that are set' do
expect(described_class.variables).to include({ 'GITLAB_USERNAME' => '$GITLAB_USERNAME' })
end
it 'prefers environment variables to defined values' do
described_class.user_username = 'tanuki'
expect(described_class.variables).to include({ 'GITLAB_USERNAME' => '$GITLAB_USERNAME' })
end
it 'returns values that have been overriden' do
described_class.user_password = 'tanuki'
described_class.user_type = 'ldap'
described_class.gitlab_url = 'http://localhost:9999'
expect(described_class.variables).to include({ 'GITLAB_USERNAME' => '$GITLAB_USERNAME',
'GITLAB_PASSWORD' => 'tanuki',
'GITLAB_USER_TYPE' => 'ldap',
'GITLAB_URL' => 'http://localhost:9999' })
end
end
describe '.require_gcs_with_cdn_environment!' do
around do |example|
ClimateControl.modify(
GOOGLE_CDN_JSON_KEY: nil,
GCS_CDN_BUCKET_NAME: nil,
GOOGLE_CDN_LB: nil,
GOOGLE_CDN_SIGNURL_KEY: nil,
GOOGLE_CDN_SIGNURL_KEY_NAME: nil
) { example.run }
end
it 'raises an error when required variables are not present' do
expect { described_class.require_gcs_with_cdn_environment! }.to raise_error(ArgumentError)
end
it 'raises an error with detailed message when one required element is not present' do
ClimateControl.modify(
# GOOGLE_CDN_JSON_KEY: nil,
GCS_CDN_BUCKET_NAME: 'testbucket',
GOOGLE_CDN_LB: 'http://123.4.5.67',
GOOGLE_CDN_SIGNURL_KEY: 'asdf1234',
GOOGLE_CDN_SIGNURL_KEY_NAME: 'arandomkey'
) do
expect { described_class.require_gcs_with_cdn_environment! }.to raise_error(/GOOGLE_CDN_JSON_KEY/)
end
end
it 'doesnt raise an error when all variables are present' do
ClimateControl.modify(
GOOGLE_CDN_JSON_KEY: '{"jsonkey"}',
GCS_CDN_BUCKET_NAME: 'testbucket',
GOOGLE_CDN_LB: 'http://123.4.5.67',
GOOGLE_CDN_SIGNURL_KEY: 'asdf1234',
GOOGLE_CDN_SIGNURL_KEY_NAME: 'arandomkey'
) do
expect { described_class.require_gcs_with_cdn_environment! }.not_to raise_error
end
end
end
describe '.log_level' do
let(:log_level) { nil }
around do |example|
ClimateControl.modify(QA_LOG_LEVEL: log_level) { example.run }
end
context 'without explicitly set log level' do
it 'return INFO log level' do
expect(described_class.log_level).to eq('INFO')
end
end
context 'with explicitly set log level' do
let(:log_level) { 'debug' }
it 'returns correct upcased log level' do
expect(described_class.log_level).to eq(log_level.upcase)
end
end
end
describe '.log_path' do
let(:log_path) { nil }
around do |example|
ClimateControl.modify(QA_LOG_PATH: log_path) { example.run }
end
context 'without explicitly set log path' do
it 'returns default log path' do
expect(described_class.log_path).to eq(described_class.host_artifacts_dir)
end
end
context 'with explicitly set log level' do
let(:log_path) { '/tmp/custom/log' }
it 'returns configured log path' do
expect(described_class.log_path).to eq(log_path)
end
end
end
describe '.docker_add_hosts' do
context 'when there is an env variable set' do
around do |example|
ClimateControl.modify(QA_DOCKER_ADD_HOSTS: 'docker:10.0.0.1,google.com:1.1.1.1') { example.run }
end
it 'returns hosts defined in environment variable' do
expect(described_class.docker_add_hosts).to eq %w[docker:10.0.0.1 google.com:1.1.1.1]
end
end
context 'when there is no env variable set' do
around do |example|
ClimateControl.modify(QA_DOCKER_ADD_HOSTS: nil) { example.run }
end
it 'returns a empty array' do
expect(described_class.docker_add_hosts).to eq []
end
end
end
describe '.variables_to_mask' do
context 'when there is an env variable set' do
let(:var_name) { 'WORKSPACES_DOMAIN_CERT' }
let(:file_var) { '/path/to/file_var' }
let(:secret) { 'secret' }
it 'returns the variable and value to mask' do
ClimateControl.modify(var_name => file_var) do
stub_const(
'Gitlab::QA::Runtime::Env::ENV_VARIABLES',
var_name => { name: :workspaces_domain_cert, type: :file }
)
expect(File).to receive(:exist?).and_return(true)
expect(File).to receive(:read).and_return(secret)
expect(described_class.variables_to_mask).to include(secret)
end
end
end
context 'when there is no env variable set' do
it 'returns a empty array' do
expect(described_class.variables_to_mask).to eq []
end
end
end
describe '.docker_network' do
context 'when there is an env variable set' do
around do |example|
ClimateControl.modify(QA_DOCKER_NETWORK: 'custom') { example.run }
end
it 'returns network defined in environment variable' do
expect(described_class.docker_network).to eq 'custom'
end
end
context 'when there is no env variable set' do
it 'returns a default network name' do
expect(described_class.docker_network).to eq 'test'
end
end
end
end