# frozen_string_literal: true RSpec.describe QA::Support::SSH do let(:key) { Struct.new(:private_key).new('private_key') } let(:known_hosts_file) { Tempfile.new('known_hosts_file') } let(:private_key_file) { Tempfile.new('private_key_file') } let(:result) { QA::Support::Run::Result.new('', 0, '') } let(:ssh) do described_class.new.tap do |ssh| ssh.uri = uri ssh.key = key ssh.private_key_file = private_key_file ssh.known_hosts_file = known_hosts_file end end shared_examples 'providing correct ports' do context 'when no port specified in uri' do let(:uri) { 'http://foo.com' } it 'does not provide port in ssh command' do expect(ssh).to receive(:run).with(expected_ssh_command_no_port, any_args).and_return(result) call_method end end context 'when no port specified in https uri' do let(:uri) { 'https://foo.com' } it 'does not provide port in ssh command' do expect(ssh).to receive(:run).with(expected_ssh_command_no_port, any_args).and_return(result) call_method end end context 'when port 80 specified in uri' do let(:uri) { 'http://foo.com:80' } it 'does not provide port in ssh command' do expect(ssh).to receive(:run).with(expected_ssh_command_no_port, any_args).and_return(result) call_method end end context 'when other port is specified in uri' do let(:port) { 1234 } let(:uri) { "http://foo.com:#{port}" } it "provides other port in ssh command" do expect(ssh).to receive(:run).with(expected_ssh_command_port, any_args).and_return(result) call_method end end end describe '#setup' do let(:expected_ssh_command_no_port) { "ssh-keyscan -T 60 -H foo.com >> #{known_hosts_file.path}" } let(:expected_ssh_command_port) { "ssh-keyscan -T 60 -H -p #{port} foo.com >> #{known_hosts_file.path}" } let(:call_method) { ssh.setup } before do allow(File).to receive(:binwrite).with(private_key_file, key.private_key) allow(File).to receive(:chmod).with(0700, private_key_file) end it_behaves_like 'providing correct ports' end describe '#reset_2fa_codes' do let(:expected_ssh_command_no_port) { "echo yes | ssh -i #{private_key_file.path} -o UserKnownHostsFile=#{known_hosts_file.path} git@foo.com 2fa_recovery_codes" } let(:expected_ssh_command_port) { "echo yes | ssh -i #{private_key_file.path} -o UserKnownHostsFile=#{known_hosts_file.path} git@foo.com -p #{port} 2fa_recovery_codes" } let(:call_method) { ssh.reset_2fa_codes } before do allow(ssh).to receive(:git_user).and_return('git') end it_behaves_like 'providing correct ports' end describe '#git_user' do context 'when running on CI' do let(:uri) { 'http://gitlab.com' } before do allow(QA::Runtime::Env).to receive(:running_in_ci?).and_return(true) end it 'returns git user' do expect(ssh.send(:git_user)).to eq('git') end end context 'when running on a review app in CI' do let(:uri) { 'https://gitlab-review.app' } before do allow(QA::Runtime::Env).to receive(:running_in_ci?).and_return(true) end it 'returns git user' do expect(ssh.send(:git_user)).to eq('git') end end context 'when running against environment on a port other than 80 or 443' do let(:uri) { 'http://localhost:3000' } before do allow(Etc).to receive(:getlogin).and_return('dummy_username') allow(QA::Runtime::Env).to receive(:running_in_ci?).and_return(false) end it 'returns the local user' do expect(ssh.send(:git_user)).to eq('dummy_username') end end context 'when running against environment on port 80 and not on CI (docker)' do let(:uri) { 'http://localhost' } before do allow(QA::Runtime::Env).to receive(:running_in_ci?).and_return(false) end it 'returns git user' do expect(ssh.send(:git_user)).to eq('git') end end end end