From e4ea997399732427fb59dcbb4194fdba55bfe9c0 Mon Sep 17 00:00:00 2001 From: Mathieu Parent <math.parent@gmail.com> Date: Sun, 28 Mar 2021 22:53:28 +0200 Subject: [PATCH] Add Packages::Helm::ExtractFileMetadataService Item 2.3 of https://gitlab.com/gitlab-org/gitlab/-/issues/18997#note_530270349 --- .../helm/extract_file_metadata_service.rb | 53 +++++++++++++++++ .../extract_file_metadata_service_spec.rb | 59 +++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 app/services/packages/helm/extract_file_metadata_service.rb create mode 100644 spec/services/packages/helm/extract_file_metadata_service_spec.rb diff --git a/app/services/packages/helm/extract_file_metadata_service.rb b/app/services/packages/helm/extract_file_metadata_service.rb new file mode 100644 index 00000000000..e7373d8ea8f --- /dev/null +++ b/app/services/packages/helm/extract_file_metadata_service.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'rubygems/package' + +module Packages + module Helm + class ExtractFileMetadataService + ExtractionError = Class.new(StandardError) + + def initialize(package_file) + @package_file = package_file + end + + def execute + raise ExtractionError, 'invalid package file' unless valid_package_file? + + metadata + end + + private + + def valid_package_file? + @package_file && + @package_file.package&.helm? && + @package_file.file.size > 0 # rubocop:disable Style/ZeroLengthPredicate + end + + def metadata + YAML.safe_load(chart_yaml_content) + rescue Psych::Exception => e + raise ExtractionError, "Error while parsing Chart.yaml: #{e.message}" + end + + def chart_yaml_content + @package_file.file.use_open_file do |file| + tar_reader = Gem::Package::TarReader.new(Zlib::GzipReader.new(file)) + + chart_yaml = tar_reader.find do |entry| + next unless entry.file? + + entry.full_name.end_with?('/Chart.yaml') + end + + raise ExtractionError, 'Chart.yaml not found within a directory' unless chart_yaml + + chart_yaml.read + ensure + tar_reader.close + end + end + end + end +end diff --git a/spec/services/packages/helm/extract_file_metadata_service_spec.rb b/spec/services/packages/helm/extract_file_metadata_service_spec.rb new file mode 100644 index 00000000000..ea196190e24 --- /dev/null +++ b/spec/services/packages/helm/extract_file_metadata_service_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe Packages::Helm::ExtractFileMetadataService do + let_it_be(:package_file) { create(:helm_package_file) } + + let(:service) { described_class.new(package_file) } + + let(:expected) do + { + 'apiVersion' => 'v2', + 'description' => 'File, Block, and Object Storage Services for your Cloud-Native Environment', + 'icon' => 'https://rook.io/images/rook-logo.svg', + 'name' => 'rook-ceph', + 'sources' => ['https://github.com/rook/rook'], + 'version' => 'v1.5.8' + } + end + + subject { service.execute } + + context 'with a valid file' do + it { is_expected.to eq(expected) } + end + + context 'without Chart.yaml' do + before do + expect_next_instances_of(Gem::Package::TarReader::Entry, 14) do |entry| + expect(entry).to receive(:full_name).exactly(:once).and_wrap_original do |m, *args| + m.call(*args) + '_suffix' + end + end + end + + it { expect { subject }.to raise_error(described_class::ExtractionError, 'Chart.yaml not found within a directory') } + end + + context 'with Chart.yaml at root' do + before do + expect_next_instances_of(Gem::Package::TarReader::Entry, 14) do |entry| + expect(entry).to receive(:full_name).exactly(:once) do + 'Chart.yaml' + end + end + end + + it { expect { subject }.to raise_error(described_class::ExtractionError, 'Chart.yaml not found within a directory') } + end + + context 'with an invalid YAML' do + before do + expect_next_instance_of(Gem::Package::TarReader::Entry) do |entry| + expect(entry).to receive(:read).and_return('{') + end + end + + it { expect { subject }.to raise_error(described_class::ExtractionError, 'Error while parsing Chart.yaml: (<unknown>): did not find expected node content while parsing a flow node at line 2 column 1') } + end +end -- 2.30.9