Skip to content
Snippets Groups Projects
Verified Commit 5f5dd466 authored by Mohamed Hamda's avatar Mohamed Hamda :four:
Browse files

Introduce ExcludedNamespace model/table

Add a new model for LimitExclusion
Add the new model under Namespaces::Storage
Add the storage_limit_exclusion/namespace relation
Cover changes with specs
Document the new table

Changelog: added
MR: !108449
parent e5f22e6a
No related branches found
No related tags found
1 merge request!108449Introduce StorageLimit::ExcludedNamespace model/table
---
table_name: namespaces_storage_limit_exclusions
classes:
- Namespaces::Storage::LimitExclusion
feature_categories:
- subscription_cost_management
description: |
Stores namespaces that are excluded from the storage limit.
Any namespaces that are included in this table will not have storage limitations applied.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108449
milestone: '15.8'
gitlab_schema: gitlab_main
# frozen_string_literal: true
class CreateNamespacesStorageLimitExclusions < Gitlab::Database::Migration[2.1]
enable_lock_retries!
def up
create_table :namespaces_storage_limit_exclusions do |t|
t.references :namespace,
foreign_key: { on_delete: :cascade },
index: true,
null: false
t.text :reason, null: false, limit: 255
t.timestamps_with_timezone null: false
end
end
def down
drop_table :namespaces_storage_limit_exclusions
end
end
98252d08d480287f1014d7b7c46eafdaa53b9582607e87d5169ec7c314b56ccc
\ No newline at end of file
......@@ -18342,6 +18342,24 @@ CREATE SEQUENCE namespaces_id_seq
 
ALTER SEQUENCE namespaces_id_seq OWNED BY namespaces.id;
 
CREATE TABLE namespaces_storage_limit_exclusions (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
reason text NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
CONSTRAINT check_81640b2ee2 CHECK ((char_length(reason) <= 255))
);
CREATE SEQUENCE namespaces_storage_limit_exclusions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE namespaces_storage_limit_exclusions_id_seq OWNED BY namespaces_storage_limit_exclusions.id;
CREATE TABLE namespaces_sync_events (
id bigint NOT NULL,
namespace_id bigint NOT NULL
......@@ -24381,6 +24399,8 @@ ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('names
 
ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
 
ALTER TABLE ONLY namespaces_storage_limit_exclusions ALTER COLUMN id SET DEFAULT nextval('namespaces_storage_limit_exclusions_id_seq'::regclass);
ALTER TABLE ONLY namespaces_sync_events ALTER COLUMN id SET DEFAULT nextval('namespaces_sync_events_id_seq'::regclass);
 
ALTER TABLE ONLY note_diff_files ALTER COLUMN id SET DEFAULT nextval('note_diff_files_id_seq'::regclass);
......@@ -26504,6 +26524,9 @@ ALTER TABLE ONLY namespace_statistics
ALTER TABLE ONLY namespaces
ADD CONSTRAINT namespaces_pkey PRIMARY KEY (id);
 
ALTER TABLE ONLY namespaces_storage_limit_exclusions
ADD CONSTRAINT namespaces_storage_limit_exclusions_pkey PRIMARY KEY (id);
ALTER TABLE ONLY namespaces_sync_events
ADD CONSTRAINT namespaces_sync_events_pkey PRIMARY KEY (id);
 
......@@ -30275,6 +30298,8 @@ CREATE INDEX index_namespaces_on_type_and_visibility_and_parent_id ON namespaces
 
CREATE INDEX index_namespaces_public_groups_name_id ON namespaces USING btree (name, id) WHERE (((type)::text = 'Group'::text) AND (visibility_level = 20));
 
CREATE INDEX index_namespaces_storage_limit_exclusions_on_namespace_id ON namespaces_storage_limit_exclusions USING btree (namespace_id);
CREATE INDEX index_namespaces_sync_events_on_namespace_id ON namespaces_sync_events USING btree (namespace_id);
 
CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
......@@ -34255,6 +34280,9 @@ ALTER TABLE ONLY diff_note_positions
ALTER TABLE ONLY analytics_cycle_analytics_aggregations
ADD CONSTRAINT fk_rails_13c8374c7a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
 
ALTER TABLE ONLY namespaces_storage_limit_exclusions
ADD CONSTRAINT fk_rails_14e8f7b0e0 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY users_security_dashboard_projects
ADD CONSTRAINT fk_rails_150cd5682c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
 
......@@ -27,6 +27,7 @@ module Namespace
has_one :gitlab_subscription
has_one :elasticsearch_indexed_namespace
has_one :upcoming_reconciliation, inverse_of: :namespace, class_name: "GitlabSubscriptions::UpcomingReconciliation"
has_one :storage_limit_exclusion, class_name: 'Namespaces::Storage::LimitExclusion'
has_many :compliance_management_frameworks, class_name: "ComplianceManagement::Framework"
......
# frozen_string_literal: true
module Namespaces
module Storage
class LimitExclusion < ApplicationRecord
self.table_name = "namespaces_storage_limit_exclusions"
belongs_to :namespace, optional: false
validates :reason, presence: true, length: { maximum: 255 }
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :storage_limit_excluded_namespace, class: 'Namespaces::Storage::LimitExclusion' do
namespace
reason { 'Excluded for testing purposes' }
end
end
......@@ -18,6 +18,7 @@
it { is_expected.to have_one(:security_orchestration_policy_configuration).class_name('Security::OrchestrationPolicyConfiguration').with_foreign_key(:namespace_id) }
it { is_expected.to have_one :upcoming_reconciliation }
it { is_expected.to have_many(:ci_minutes_additional_packs) }
it { is_expected.to have_one(:storage_limit_exclusion) }
it { is_expected.to delegate_method(:trial?).to(:gitlab_subscription) }
it { is_expected.to delegate_method(:trial_ends_on).to(:gitlab_subscription) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Namespaces::Storage::LimitExclusion, feature_category: :subscription_cost_management, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:namespace).required }
end
describe 'check constraints' do
it 'enforces the reason and namespace NOT NULL constraint' do
expect do
ApplicationRecord.connection
.execute('INSERT INTO namespaces_storage_limit_exclusions (reason, namespace_id) VALUES (NULL, NULL)')
end.to raise_error(ActiveRecord::NotNullViolation)
end
end
describe 'validations' do
it { is_expected.to belong_to(:namespace).optional(false) }
it { is_expected.to validate_presence_of(:reason) }
it { is_expected.to validate_length_of(:reason).is_at_most(255) }
end
describe 'dependent destroy' do
let(:namespace) { create(:namespace) }
let!(:excluded_namespace) { create(:storage_limit_excluded_namespace, namespace: namespace) }
it 'destroys the excluded namespace when the namespace is destroyed' do
expect { namespace.destroy! }.to change { described_class.count }.by(-1)
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment