Skip to content

Commit

Permalink
Detect repository types when mirroring repositories
Browse files Browse the repository at this point in the history
  • Loading branch information
felixsch committed Dec 20, 2023
1 parent a4ed301 commit 659d0e0
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 18 deletions.
13 changes: 13 additions & 0 deletions lib/rmt/mirror.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,18 @@ def initialize(repository:, base_dir:, logger:, mirror_sources: false, is_airgap
end

def detect_repository_type
search = {
repomd: File.join(repository.external_url, RPM_FILE_NEEDLE),
debian: File.join(repository.external_url, DEB_FILE_NEEDLE)
}

search.each do |key, url|
request = RMT::HttpRequest.new(url, method: :head, followlocation: true)
request.on_success do
return key
end
request.run
end
nil
end
end
6 changes: 3 additions & 3 deletions lib/rmt/mirror/repomd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class RMT::Mirror::Repomd::Exception < RuntimeError
include RMT::Deduplicator
include RMT::FileValidator

def initialize(mirroring_base_dir: RMT::DEFAULT_MIRROR_DIR, logger:, mirror_src: false, airgap_mode: false)
def initialize(logger:, mirroring_base_dir: RMT::DEFAULT_MIRROR_DIR, mirror_src: false, airgap_mode: false)
@mirroring_base_dir = mirroring_base_dir
@logger = logger
@mirror_src = mirror_src
Expand Down Expand Up @@ -153,8 +153,8 @@ def mirror_packages(metadata_files, repository_dir, repository_url)

package_file_references = package_references.map do |reference|
RMT::Mirror::FileReference.build_from_metadata(reference,
base_dir: repository_dir,
base_url: repository_url)
base_dir: repository_dir,
base_url: repository_url)
end

failed_downloads = download_package_files(package_file_references)
Expand Down
32 changes: 22 additions & 10 deletions spec/lib/rmt/mirror/repomd_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
before do
expect(logger).to receive(:info).with(/Mirroring repository/).once
expect(logger).to receive(:info).with('Repository metadata signatures are missing').once
expect(logger).to receive(:info).with(/↓/).at_least(1).times
expect(logger).to receive(:info).with(/↓/).at_least(:once)
rmt_mirror.mirror(**mirror_params)
end

Expand Down Expand Up @@ -234,7 +234,7 @@

before do
expect(logger).to receive(:info).with(/Mirroring repository/).once
expect(logger).to receive(:info).with(/↓/).at_least(1).times
expect(logger).to receive(:info).with(/↓/).at_least(:once)
rmt_mirror.mirror(**mirror_params)
end

Expand Down Expand Up @@ -289,6 +289,7 @@

context "when can't create tmp dir", vcr: { cassette_name: 'mirroring_product' } do
before { allow(Dir).to receive(:mktmpdir).and_raise('mktmpdir exception') }

it 'handles the exception' do
expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception)
end
Expand All @@ -302,6 +303,7 @@
.with([file_reference_containing_path('repodata/repomd.xml')])
.and_raise(RMT::Downloader::Exception, "418 - I'm a teapot")
end

it 'handles RMT::Downloader::Exception' do
expect { rmt_mirror.mirror(**mirror_params) }
.to raise_error(RMT::Mirror::Repomd::Exception, "Error while mirroring metadata: 418 - I'm a teapot")
Expand Down Expand Up @@ -343,17 +345,20 @@
context "when can't download some of the license files" do
before do
allow_any_instance_of(RMT::Downloader).to receive(:download_multi).and_wrap_original do |klass, *args|
raise RMT::Downloader::Exception.new('') if args[0][0].local_path =~ /license/
raise RMT::Downloader::Exception.new('') if /license/.match?(args[0][0].local_path)

klass.call(*args)
end
end

it 'handles RMT::Downloader::Exception', vcr: { cassette_name: 'mirroring_product' } do
expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception, /Error while mirroring license files:/)
end
end

context "when can't parse metadata", vcr: { cassette_name: 'mirroring_product' } do
before { allow_any_instance_of(RepomdParser::RepomdXmlParser).to receive(:parse).and_raise('Parse error') }

it 'removes the temporary metadata directory' do
expect { rmt_mirror.mirror(**mirror_params) }
.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring metadata: Parse error')
Expand All @@ -365,6 +370,7 @@

context 'when Interrupt is raised', vcr: { cassette_name: 'mirroring_product' } do
before { allow_any_instance_of(RepomdParser::RepomdXmlParser).to receive(:parse).and_raise(Interrupt.new) }

it 'removes the temporary metadata directory' do
expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(Interrupt)

Expand All @@ -377,21 +383,27 @@
it 'handles RMT::Downloader::Exception' do
allow_any_instance_of(RMT::Downloader).to receive(:make_request).and_wrap_original do |klass, *args|
# raise the exception only for the RPMs/DRPMs
raise(RMT::Downloader::Exception, "418 - I'm a teapot") if args[0].local_path =~ /rpm$/
raise(RMT::Downloader::Exception, "418 - I'm a teapot") if /rpm$/.match?(args[0].local_path)

klass.call(*args)
end

expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files')
expect do
rmt_mirror.mirror(**mirror_params)
end.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files')
end

it 'handles RMT::ChecksumVerifier::Exception' do
allow_any_instance_of(RMT::Downloader).to receive(:make_request).and_wrap_original do |klass, *args|
# raise the exception only for the RPMs/DRPMs
raise(RMT::ChecksumVerifier::Exception, "Checksum doesn't match") if args[0].local_path =~ /rpm$/
raise(RMT::ChecksumVerifier::Exception, "Checksum doesn't match") if /rpm$/.match?(args[0].local_path)

klass.call(*args)
end

expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files')
expect do
rmt_mirror.mirror(**mirror_params)
end.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files')
end
end
end
Expand Down Expand Up @@ -795,7 +807,7 @@
it 'mirrors as normal' do
expect(logger).to receive(:info).with(/Mirroring repository/).once
expect(logger).to receive(:info).with('Repository metadata signatures are missing').once
expect(logger).to receive(:info).with(/↓/).at_least(1).times
expect(logger).to receive(:info).with(/↓/).at_least(:once)

allow_any_instance_of(RMT::Downloader).to receive(:finalize_download).and_wrap_original do |klass, *args|
if args[1].local_path.include?('repodata/repomd.xml.key')
Expand All @@ -817,7 +829,7 @@

it 'raises RMT::Mirror::Repomd::Exception' do
expect(logger).to receive(:info).with(/Mirroring repository/).once
expect(logger).to receive(:info).with(/↓/).at_least(1).times
expect(logger).to receive(:info).with(/↓/).at_least(:once)

expect_any_instance_of(described_class).to(
receive(:mirror_metadata).and_call_original
Expand All @@ -833,7 +845,7 @@

expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(
RMT::Mirror::Repomd::Exception,
'Error while mirroring metadata: Downloading repo signature/key failed with: HTTP request failed, HTTP code 502'
'Error while mirroring metadata: Downloading repo signature/key failed with: HTTP request failed, HTTP code 502'
)
end
end
Expand Down
19 changes: 14 additions & 5 deletions spec/lib/rmt/mirror_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,33 @@
end

describe '#detect_repository_type' do
let(:repomd_url) { 'http://some.test.us/path/directory/repodata/repomd.xml' }
let(:debian_url) { 'http://some.test.us/path/directory/Release' }

context 'repomd repository' do
it 'detects a repomd repository' do
stub_request(:head, repomd_url).to_return(status: 200, body: '', headers: {})

expect(mirror.detect_repository_type).to eq(:repomd)
end
end

context 'debian flat repository' do
it 'detects a flat debian repository' do
stub_request(:head, repomd_url).to_return(status: 404, body: '', headers: {})
stub_request(:head, debian_url).to_return(status: 200, body: '', headers: {})

expect(mirror.detect_repository_type).to eq(:debian)
end
end

context 'debian repository' do
it 'detects a full blown debian repository and raises'
end

context 'unknown repository type' do
it 'raises if a unknown repository type is detected'
it 'raises if a unknown repository type is detected' do
stub_request(:head, repomd_url).to_return(status: 404, body: '', headers: {})
stub_request(:head, debian_url).to_return(status: 404, body: '', headers: {})

expect(mirror.detect_repository_type).to be_nil
end
end
end
end

0 comments on commit 659d0e0

Please sign in to comment.