Commit 8f36323a authored by Ash McKenzie's avatar Ash McKenzie

Merge branch 'debian_update_distributionservice' into 'master'

Add Packages::Debian::UpdateDistributionService

See merge request gitlab-org/gitlab!51893
parents 222de8d5 1ed56ba8
# frozen_string_literal: true
module Packages
module Debian
class UpdateDistributionService
def initialize(distribution, params)
@distribution, @params = distribution, params
@components = params.delete(:components)
@architectures = params.delete(:architectures)
@architectures += ['all'] unless @architectures.nil?
@errors = []
end
def execute
update_distribution
end
private
attr_reader :distribution, :params, :components, :architectures, :errors
def append_errors(record, prefix = '')
return if record.valid?
prefix = "#{prefix} " unless prefix.empty?
@errors += record.errors.full_messages.map { |message| "#{prefix}#{message}" }
end
def update_distribution
distribution.transaction do
if distribution.update(params)
update_components if components
update_architectures if architectures
success
else
append_errors(distribution)
error
end
end || error
end
def update_components
update_objects(distribution.components, components, error_label: 'Component')
end
def update_architectures
update_objects(distribution.architectures, architectures, error_label: 'Architecture')
end
def update_objects(objects, object_names_from_params, error_label: )
current_object_names = objects.map(&:name)
missing_object_names = object_names_from_params - current_object_names
extra_object_names = current_object_names - object_names_from_params
missing_object_names.each do |name|
new_object = objects.create(name: name)
append_errors(new_object, error_label)
raise ActiveRecord::Rollback unless new_object.persisted?
end
extra_object_names.each do |name|
object = objects.with_name(name).first
raise ActiveRecord::Rollback unless object.destroy
end
end
def success
ServiceResponse.success(payload: { distribution: distribution })
end
def error
ServiceResponse.error(message: errors.to_sentence, payload: { distribution: distribution })
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Packages::Debian::UpdateDistributionService do
RSpec.shared_examples 'Update Debian Distribution' do |expected_message, expected_components, expected_architectures|
it 'returns ServiceResponse', :aggregate_failures do
expect(distribution).to receive(:update).with(simple_params).and_call_original if expected_message.nil?
expect { response }
.to not_change { container.debian_distributions.klass.all.count }
.and not_change { container.debian_distributions.count }
.and not_change { component1.class.all.count }
.and not_change { architecture1.class.all.count }
expect(response).to be_a(ServiceResponse)
expect(response.success?).to eq(expected_message.nil?)
expect(response.error?).to eq(!expected_message.nil?)
expect(response.message).to eq(expected_message)
expect(response.payload).to eq(distribution: distribution)
distribution.reload
distribution.components.reload
distribution.architectures.reload
if expected_message.nil?
simple_params.each_pair do |name, value|
expect(distribution.send(name)).to eq(value)
end
else
original_params.each_pair do |name, value|
expect(distribution.send(name)).to eq(value)
end
end
expect(distribution.components.map(&:name)).to contain_exactly(*expected_components)
expect(distribution.architectures.map(&:name)).to contain_exactly(*expected_architectures)
end
end
RSpec.shared_examples 'Debian Update Distribution Service' do |container_type, can_freeze|
context "with a Debian #{container_type} distribution" do
let_it_be(:container, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
let_it_be(:distribution, reload: true) { create("debian_#{container_type}_distribution", container: container) }
let_it_be(:component1) { create("debian_#{container_type}_component", distribution: distribution, name: 'component1') }
let_it_be(:component2) { create("debian_#{container_type}_component", distribution: distribution, name: 'component2') }
let_it_be(:architecture0) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
let_it_be(:architecture1) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture1') }
let_it_be(:architecture2) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture2') }
let(:original_params) do
{
suite: nil,
origin: nil,
label: nil,
version: nil,
description: nil,
valid_time_duration_seconds: nil,
automatic: true,
automatic_upgrades: false
}
end
let(:params) { {} }
let(:simple_params) { params.except(:components, :architectures) }
subject { described_class.new(distribution, params) }
let(:response) { subject.execute }
context 'with valid simple params' do
let(:params) do
{
suite: 'my-suite',
origin: 'my-origin',
label: 'my-label',
version: '42.0',
description: 'my-description',
valid_time_duration_seconds: 7.days,
automatic: false,
automatic_upgrades: true
}
end
it_behaves_like 'Update Debian Distribution', nil, %w[component1 component2], %w[all architecture1 architecture2]
end
context 'with invalid simple params' do
let(:params) do
{
suite: 'suite erronée',
origin: 'origin erronée',
label: 'label erronée',
version: 'version erronée',
description: 'description erronée',
valid_time_duration_seconds: 1.hour
}
end
it_behaves_like 'Update Debian Distribution', 'Suite is invalid, Origin is invalid, Label is invalid, Version is invalid, and Valid time duration seconds must be greater than or equal to 86400', %w[component1 component2], %w[all architecture1 architecture2]
end
context 'with valid components and architectures' do
let(:params) do
{
suite: 'my-suite',
components: %w[component2 component3],
architectures: %w[architecture2 architecture3]
}
end
it_behaves_like 'Update Debian Distribution', nil, %w[component2 component3], %w[all architecture2 architecture3]
end
context 'with invalid components' do
let(:params) do
{
suite: 'my-suite',
components: %w[component2 erroné],
architectures: %w[architecture2 architecture3]
}
end
it_behaves_like 'Update Debian Distribution', 'Component Name is invalid', %w[component1 component2], %w[all architecture1 architecture2]
end
context 'with invalid architectures' do
let(:params) do
{
suite: 'my-suite',
components: %w[component2 component3],
architectures: %w[architecture2 erroné]
}
end
it_behaves_like 'Update Debian Distribution', 'Architecture Name is invalid', %w[component1 component2], %w[all architecture1 architecture2]
end
end
end
it_behaves_like 'Debian Update Distribution Service', :project, true
it_behaves_like 'Debian Update Distribution Service', :group, false
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment