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