Commit c5e729f6 authored by Nicolas Dular's avatar Nicolas Dular Committed by James Lopez

Use plan and purchased storage for limit

parent 028e1fd1
...@@ -8,7 +8,6 @@ import NotificationsForm from '~/notifications_form'; ...@@ -8,7 +8,6 @@ import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GroupTabs from './group_tabs'; import GroupTabs from './group_tabs';
import initNamespaceStorageLimitAlert from '~/namespace_storage_limit_alert';
export default function initGroupDetails(actionName = 'show') { export default function initGroupDetails(actionName = 'show') {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup'); const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
...@@ -28,6 +27,4 @@ export default function initGroupDetails(actionName = 'show') { ...@@ -28,6 +27,4 @@ export default function initGroupDetails(actionName = 'show') {
if (newGroupChildWrapper) { if (newGroupChildWrapper) {
new NewGroupChild(newGroupChildWrapper); new NewGroupChild(newGroupChildWrapper);
} }
initNamespaceStorageLimitAlert();
} }
...@@ -8,13 +8,11 @@ import initReadMore from '~/read_more'; ...@@ -8,13 +8,11 @@ import initReadMore from '~/read_more';
import leaveByUrl from '~/namespaces/leave_by_url'; import leaveByUrl from '~/namespaces/leave_by_url';
import Star from '../../../star'; import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown'; import notificationsDropdown from '../../../notifications_dropdown';
import initNamespaceStorageLimitAlert from '~/namespace_storage_limit_alert';
import { showLearnGitLabProjectPopover } from '~/onboarding_issues'; import { showLearnGitLabProjectPopover } from '~/onboarding_issues';
import initTree from 'ee_else_ce/repository'; import initTree from 'ee_else_ce/repository';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initReadMore(); initReadMore();
initNamespaceStorageLimitAlert();
new Star(); // eslint-disable-line no-new new Star(); // eslint-disable-line no-new
notificationsDropdown(); notificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
......
...@@ -27,9 +27,6 @@ module Types ...@@ -27,9 +27,6 @@ module Types
description: 'Indicates if Large File Storage (LFS) is enabled for namespace' description: 'Indicates if Large File Storage (LFS) is enabled for namespace'
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true, field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if users can request access to namespace' description: 'Indicates if users can request access to namespace'
field :storage_size_limit, GraphQL::FLOAT_TYPE, null: true,
description: 'Total storage limit of the root namespace in bytes',
resolve: -> (obj, _args, _ctx) { Namespace::RootStorageSize.new(obj).limit }
field :root_storage_statistics, Types::RootStorageStatisticsType, field :root_storage_statistics, Types::RootStorageStatisticsType,
null: true, null: true,
...@@ -41,3 +38,5 @@ module Types ...@@ -41,3 +38,5 @@ module Types
resolver: ::Resolvers::NamespaceProjectsResolver resolver: ::Resolvers::NamespaceProjectsResolver
end end
end end
Types::NamespaceType.prepend_if_ee('EE::Types::NamespaceType')
...@@ -56,45 +56,6 @@ module NamespacesHelper ...@@ -56,45 +56,6 @@ module NamespacesHelper
namespaces_options(selected, options) namespaces_options(selected, options)
end end
def namespace_storage_alert(namespace)
return {} if current_user.nil?
payload = Namespaces::CheckStorageSizeService.new(namespace, current_user).execute.payload
return {} if payload.empty?
alert_level = payload[:alert_level]
root_namespace = payload[:root_namespace]
return {} if cookies["hide_storage_limit_alert_#{root_namespace.id}_#{alert_level}"] == 'true'
payload
end
def namespace_storage_alert_style(alert_level)
if alert_level == :error || alert_level == :alert
'danger'
else
alert_level.to_s
end
end
def namespace_storage_alert_icon(alert_level)
if alert_level == :error || alert_level == :alert
'error'
elsif alert_level == :info
'information-o'
else
alert_level.to_s
end
end
def namespace_storage_usage_link(namespace)
# The usage quota page is only available in EE. This will be changed in
# the future, see https://gitlab.com/gitlab-org/gitlab/-/issues/220042.
nil
end
private private
# Many importers create a temporary Group, so use the real # Many importers create a temporary Group, so use the real
......
# frozen_string_literal: true
class Namespace::RootStorageSize
def initialize(root_namespace)
@root_namespace = root_namespace
end
def above_size_limit?
return false if limit == 0
usage_ratio > 1
end
def usage_ratio
return 0 if limit == 0
current_size.to_f / limit.to_f
end
def current_size
@current_size ||= root_namespace.root_storage_statistics&.storage_size
end
def limit
@limit ||= Gitlab::CurrentSettings.namespace_storage_size_limit.megabytes
end
private
attr_reader :root_namespace
end
...@@ -29,8 +29,6 @@ class PostReceiveService ...@@ -29,8 +29,6 @@ class PostReceiveService
response.add_alert_message(message) response.add_alert_message(message)
end end
response.add_alert_message(storage_size_limit_alert)
broadcast_message = BroadcastMessage.current_banner_messages&.last&.message broadcast_message = BroadcastMessage.current_banner_messages&.last&.message
response.add_alert_message(broadcast_message) response.add_alert_message(broadcast_message)
...@@ -76,19 +74,6 @@ class PostReceiveService ...@@ -76,19 +74,6 @@ class PostReceiveService
::MergeRequests::GetUrlsService.new(project).execute(params[:changes]) ::MergeRequests::GetUrlsService.new(project).execute(params[:changes])
end end
private
def storage_size_limit_alert
return unless repository&.repo_type&.project?
payload = Namespaces::CheckStorageSizeService.new(project.namespace, user).execute.payload
return unless payload.present?
alert_level = "##### #{payload[:alert_level].to_s.upcase} #####"
[alert_level, payload[:usage_message], payload[:explanation_message]].join("\n")
end
end end
PostReceiveService.prepend_if_ee('EE::PostReceiveService') PostReceiveService.prepend_if_ee('EE::PostReceiveService')
= content_for :flash_message do = content_for :flash_message do
= render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)] = render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)]
= render 'shared/namespace_storage_limit_alert', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)] = render_if_exists 'shared/namespace_storage_limit_alert', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)]
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
= render 'shared/auto_devops_implicitly_enabled_banner', project: project = render 'shared/auto_devops_implicitly_enabled_banner', project: project
= render_if_exists 'projects/above_size_limit_warning', project: project = render_if_exists 'projects/above_size_limit_warning', project: project
= render_if_exists 'shared/shared_runners_minutes_limit', project: project, classes: [container_class, ("limit-container-width" unless fluid_layout)] = render_if_exists 'shared/shared_runners_minutes_limit', project: project, classes: [container_class, ("limit-container-width" unless fluid_layout)]
= render 'shared/namespace_storage_limit_alert', namespace: project.namespace, classes: [container_class, ("limit-container-width" unless fluid_layout)] = render_if_exists 'shared/namespace_storage_limit_alert', namespace: project.namespace, classes: [container_class, ("limit-container-width" unless fluid_layout)]
...@@ -3,6 +3,7 @@ import leaveByUrl from '~/namespaces/leave_by_url'; ...@@ -3,6 +3,7 @@ import leaveByUrl from '~/namespaces/leave_by_url';
import initGroupDetails from '~/pages/groups/shared/group_details'; import initGroupDetails from '~/pages/groups/shared/group_details';
import initGroupAnalytics from 'ee/analytics/group_analytics/group_analytics_bundle'; import initGroupAnalytics from 'ee/analytics/group_analytics/group_analytics_bundle';
import initVueAlerts from '~/vue_alerts'; import initVueAlerts from '~/vue_alerts';
import initNamespaceStorageLimitAlert from 'ee/namespace_storage_limit_alert';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
leaveByUrl('group'); leaveByUrl('group');
...@@ -15,4 +16,5 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -15,4 +16,5 @@ document.addEventListener('DOMContentLoaded', () => {
initGroupAnalytics(); initGroupAnalytics();
initVueAlerts(); initVueAlerts();
initNamespaceStorageLimitAlert();
}); });
import '~/pages/projects/show/index'; import '~/pages/projects/show/index';
import initVueAlerts from '~/vue_alerts'; import initVueAlerts from '~/vue_alerts';
import initNamespaceStorageLimitAlert from 'ee/namespace_storage_limit_alert';
document.addEventListener('DOMContentLoaded', initVueAlerts); document.addEventListener('DOMContentLoaded', () => {
initVueAlerts();
initNamespaceStorageLimitAlert();
});
# frozen_string_literal: true
module EE
module Types
module NamespaceType
extend ActiveSupport::Concern
prepended do
field :storage_size_limit,
GraphQL::FLOAT_TYPE, null: true,
description: 'Total storage limit of the root namespace in bytes',
resolve: -> (obj, _args, _ctx) { EE::Namespace::RootStorageSize.new(obj).limit }
end
end
end
end
...@@ -32,7 +32,39 @@ module EE ...@@ -32,7 +32,39 @@ module EE
end end
end end
override :namespace_storage_usage_link def namespace_storage_alert(namespace)
return {} if current_user.nil?
payload = Namespaces::CheckStorageSizeService.new(namespace, current_user).execute.payload
return {} if payload.empty?
alert_level = payload[:alert_level]
root_namespace = payload[:root_namespace]
return {} if cookies["hide_storage_limit_alert_#{root_namespace.id}_#{alert_level}"] == 'true'
payload
end
def namespace_storage_alert_style(alert_level)
if alert_level == :error || alert_level == :alert
'danger'
else
alert_level.to_s
end
end
def namespace_storage_alert_icon(alert_level)
if alert_level == :error || alert_level == :alert
'error'
elsif alert_level == :info
'information-o'
else
alert_level.to_s
end
end
def namespace_storage_usage_link(namespace) def namespace_storage_usage_link(namespace)
if namespace.group? if namespace.group?
group_usage_quotas_path(namespace, anchor: 'storage-quota-tab') group_usage_quotas_path(namespace, anchor: 'storage-quota-tab')
......
# frozen_string_literal: true
module EE
class Namespace::RootStorageSize
def initialize(root_namespace)
@root_namespace = root_namespace
end
def above_size_limit?
usage_ratio > 1
end
def usage_ratio
return 0 if limit == 0
current_size.to_f / limit.to_f
end
def current_size
@current_size ||= root_namespace.root_storage_statistics&.storage_size
end
def limit
@limit ||= root_namespace.actual_limits.storage_size_limit.megabytes +
root_namespace.additional_purchased_storage_size.megabytes
end
private
attr_reader :root_namespace
end
end
...@@ -13,6 +13,8 @@ module EE ...@@ -13,6 +13,8 @@ module EE
response.add_basic_message(geo_redirect_to_primary_message) if display_geo_redirect_to_primary_message? response.add_basic_message(geo_redirect_to_primary_message) if display_geo_redirect_to_primary_message?
response.add_basic_message(geo_secondary_lag_message) if geo_display_secondary_lag_message? response.add_basic_message(geo_secondary_lag_message) if geo_display_secondary_lag_message?
response.add_alert_message(storage_size_limit_alert)
response response
end end
...@@ -50,5 +52,16 @@ module EE ...@@ -50,5 +52,16 @@ module EE
def geo_display_secondary_lag_message? def geo_display_secondary_lag_message?
::Gitlab::Geo.primary? && geo_current_replication_lag.to_i > 0 ::Gitlab::Geo.primary? && geo_current_replication_lag.to_i > 0
end end
def storage_size_limit_alert
return unless repository&.repo_type&.project?
payload = Namespaces::CheckStorageSizeService.new(project.namespace, user).execute.payload
return unless payload.present?
alert_level = "##### #{payload[:alert_level].to_s.upcase} #####"
[alert_level, payload[:usage_message], payload[:explanation_message]].join("\n")
end
end end
end end
...@@ -8,7 +8,7 @@ module Namespaces ...@@ -8,7 +8,7 @@ module Namespaces
def initialize(namespace, user) def initialize(namespace, user)
@root_namespace = namespace.root_ancestor @root_namespace = namespace.root_ancestor
@root_storage_size = Namespace::RootStorageSize.new(root_namespace) @root_storage_size = EE::Namespace::RootStorageSize.new(root_namespace)
@user = user @user = user
end end
......
= content_for :flash_message do
= render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)]
= render_if_exists 'shared/namespace_storage_limit_alert', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)]
...@@ -11,6 +11,14 @@ RSpec.describe GroupsController do ...@@ -11,6 +11,14 @@ RSpec.describe GroupsController do
let_it_be(:subgroup) { create(:group, :private, parent: group) } let_it_be(:subgroup) { create(:group, :private, parent: group) }
let_it_be(:subgroup2) { create(:group, :private, parent: subgroup) } let_it_be(:subgroup2) { create(:group, :private, parent: subgroup) }
describe 'GET #show' do
let(:namespace) { group }
subject { get :show, params: { id: group.to_param } }
it_behaves_like 'namespace storage limit alert'
end
describe 'GET #activity' do describe 'GET #activity' do
render_views render_views
......
...@@ -16,22 +16,34 @@ RSpec.describe ProjectsController do ...@@ -16,22 +16,34 @@ RSpec.describe ProjectsController do
render_views render_views
subject { get :show, params: { namespace_id: public_project.namespace.path, id: public_project.path } }
it 'shows the over size limit warning message if above_size_limit' do it 'shows the over size limit warning message if above_size_limit' do
allow_next_instance_of(Gitlab::RepositorySizeChecker) do |checker| allow_next_instance_of(Gitlab::RepositorySizeChecker) do |checker|
expect(checker).to receive(:above_size_limit?).and_return(true) expect(checker).to receive(:above_size_limit?).and_return(true)
end end
allow(controller).to receive(:current_user).and_return(user) allow(controller).to receive(:current_user).and_return(user)
get :show, params: { namespace_id: public_project.namespace.path, id: public_project.path } subject
expect(response.body).to match(/The size of this repository.+exceeds the limit/) expect(response.body).to match(/The size of this repository.+exceeds the limit/)
end end
it 'does not show an over size warning if not above_size_limit' do it 'does not show an over size warning if not above_size_limit' do
get :show, params: { namespace_id: public_project.namespace.path, id: public_project.path } subject
expect(response.body).not_to match(/The size of this repository.+exceeds the limit/) expect(response.body).not_to match(/The size of this repository.+exceeds the limit/)
end end
context 'namespace storage limit' do
let(:namespace) { public_project.namespace }
before do
allow(controller).to receive(:current_user).and_return(user)
end
it_behaves_like 'namespace storage limit alert'
end
end end
describe 'GET edit' do describe 'GET edit' do
......
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import initNamespaceStorageLimitAlert from '~/namespace_storage_limit_alert'; import initNamespaceStorageLimitAlert from 'ee/namespace_storage_limit_alert';
describe('broadcast message on dismiss', () => { describe('broadcast message on dismiss', () => {
const dismiss = () => { const dismiss = () => {
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['Namespace'] do
it { expect(described_class).to have_graphql_field(:storage_size_limit) }
end
...@@ -147,4 +147,96 @@ RSpec.describe EE::NamespacesHelper do ...@@ -147,4 +147,96 @@ RSpec.describe EE::NamespacesHelper do
it { is_expected.to be_nil } it { is_expected.to be_nil }
end end
end end
describe '#namespace_storage_alert' do
subject { helper.namespace_storage_alert(namespace) }
let(:namespace) { build(:namespace) }
let(:payload) do
{
alert_level: :info,
usage_message: "Usage",
explanation_message: "Explanation",
root_namespace: namespace
}
end
before do
allow(helper).to receive(:current_user).and_return(admin)
allow_next_instance_of(Namespaces::CheckStorageSizeService, namespace, admin) do |check_storage_size_service|
expect(check_storage_size_service).to receive(:execute).and_return(ServiceResponse.success(payload: payload))
end
end
context 'when payload is not empty and no cookie is set' do
it { is_expected.to eq(payload) }
end
context 'when there is no current_user' do
before do
allow(helper).to receive(:current_user).and_return(nil)
end
it { is_expected.to eq({}) }
end
context 'when payload is empty' do
let(:payload) { {} }
it { is_expected.to eq({}) }
end
context 'when cookie is set' do
before do
helper.request.cookies["hide_storage_limit_alert_#{namespace.id}_info"] = 'true'
end
it { is_expected.to eq({}) }
end
context 'when payload is empty and cookie is set' do
let(:payload) { {} }
before do
helper.request.cookies["hide_storage_limit_alert_#{namespace.id}_info"] = 'true'
end
it { is_expected.to eq({}) }
end
end
describe '#namespace_storage_alert_style' do
using RSpec::Parameterized::TableSyntax
subject { helper.namespace_storage_alert_style(alert_level) }
where(:alert_level, :result) do
:info | 'info'
:warning | 'warning'
:error | 'danger'
:alert | 'danger'
end
with_them do
it { is_expected.to eq(result) }
end
end
describe '#namespace_storage_alert_icon' do
using RSpec::Parameterized::TableSyntax
subject { helper.namespace_storage_alert_icon(alert_level) }
where(:alert_level, :result) do
:info | 'information-o'
:warning | 'warning'
:error | 'error'
:alert | 'error'
end
with_them do
it { is_expected.to eq(result) }
end
end
end end
...@@ -8,6 +8,9 @@ RSpec.describe Namespace::RootStorageSize, type: :model do ...@@ -8,6 +8,9 @@ RSpec.describe Namespace::RootStorageSize, type: :model do
let(:limit) { 100 } let(:limit) { 100 }
let(:model) { described_class.new(namespace) } let(:model) { described_class.new(namespace) }
let(:create_statistics) { create(:namespace_root_storage_statistics, namespace: namespace, storage_size: current_size)} let(:create_statistics) { create(:namespace_root_storage_statistics, namespace: namespace, storage_size: current_size)}
let_it_be(:gold_plan, reload: true) { create(:gold_plan) }
let_it_be(:plan_limits, reload: true) { create(:plan_limits, plan: gold_plan, storage_size_limit: 100) }
let!(:subscription) { create(:gitlab_subscription, namespace: namespace, hosted_plan: gold_plan) }
before do before do
create_statistics create_statistics
...@@ -41,7 +44,9 @@ RSpec.describe Namespace::RootStorageSize, type: :model do ...@@ -41,7 +44,9 @@ RSpec.describe Namespace::RootStorageSize, type: :model do
it { is_expected.to eq(0.5) } it { is_expected.to eq(0.5) }
context 'when limit is 0' do context 'when limit is 0' do
let(:limit) { 0 } before do
plan_limits.update!(storage_size_limit: 0)
end
it { is_expected.to eq(0) } it { is_expected.to eq(0) }
end end
...@@ -62,6 +67,31 @@ RSpec.describe Namespace::RootStorageSize, type: :model do ...@@ -62,6 +67,31 @@ RSpec.describe Namespace::RootStorageSize, type: :model do
describe '#limit' do describe '#limit' do
subject { model.limit } subject { model.limit }
it { is_expected.to eq(limit.megabytes) } context 'when there is additional purchased storage and a plan' do
before do
plan_limits.update!(storage_size_limit: 15_000)
namespace.update!(additional_purchased_storage_size: 10_000)
end
it { is_expected.to eq(25_000.megabytes) }
end
context 'when there is no additionl purchased storage' do
before do
plan_limits.update!(storage_size_limit: 15_000)
namespace.update!(additional_purchased_storage_size: 0)
end
it { is_expected.to eq(15_000.megabytes) }
end
context 'when there is no additional purchased storage or plan limit set' do
before do
plan_limits.update!(storage_size_limit: 0)
namespace.update!(additional_purchased_storage_size: 0)
end
it { is_expected.to eq(0) }
end
end end
end end
...@@ -31,73 +31,110 @@ RSpec.describe PostReceiveService, :geo do ...@@ -31,73 +31,110 @@ RSpec.describe PostReceiveService, :geo do
service.execute.messages.as_json service.execute.messages.as_json
end end
before do describe 'Geo' do
stub_current_geo_node(primary_node) before do
stub_current_geo_node(primary_node)
allow(Gitlab::Geo::GitPushHttp).to receive(:new).with(identifier, gl_repository).and_return(git_push_http) allow(Gitlab::Geo::GitPushHttp).to receive(:new).with(identifier, gl_repository).and_return(git_push_http)
allow(git_push_http).to receive(:fetch_referrer_node).and_return(node) allow(git_push_http).to receive(:fetch_referrer_node).and_return(node)
end end
context 'when the push was redirected from a Geo secondary to the primary' do context 'when the push was redirected from a Geo secondary to the primary' do
let(:node) { secondary_node } let(:node) { secondary_node }
context 'when the secondary has a GeoNodeStatus' do context 'when the secondary has a GeoNodeStatus' do
let!(:status) { create(:geo_node_status, geo_node: secondary_node, db_replication_lag_seconds: db_replication_lag_seconds) } let!(:status) { create(:geo_node_status, geo_node: secondary_node, db_replication_lag_seconds: db_replication_lag_seconds) }
context 'when the GeoNodeStatus db_replication_lag_seconds is greater than 0' do context 'when the GeoNodeStatus db_replication_lag_seconds is greater than 0' do
let(:db_replication_lag_seconds) { 17 } let(:db_replication_lag_seconds) { 17 }
it 'includes current Geo secondary lag in the output' do it 'includes current Geo secondary lag in the output' do
expect(subject).to include({ expect(subject).to include({
'type' => 'basic', 'type' => 'basic',
'message' => "Current replication lag: 17 seconds" 'message' => "Current replication lag: 17 seconds"
}) })
end
end end
end
context 'when the GeoNodeStatus db_replication_lag_seconds is 0' do context 'when the GeoNodeStatus db_replication_lag_seconds is 0' do
let(:db_replication_lag_seconds) { 0 } let(:db_replication_lag_seconds) { 0 }
it 'does not include current Geo secondary lag in the output' do it 'does not include current Geo secondary lag in the output' do
expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything }) expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything })
end
end end
end
context 'when the GeoNodeStatus db_replication_lag_seconds is nil' do context 'when the GeoNodeStatus db_replication_lag_seconds is nil' do
let(:db_replication_lag_seconds) { nil } let(:db_replication_lag_seconds) { nil }
it 'does not include current Geo secondary lag in the output' do
expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything })
end
end
end
context 'when the secondary does not have a GeoNodeStatus' do
it 'does not include current Geo secondary lag in the output' do it 'does not include current Geo secondary lag in the output' do
expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything }) expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything })
end end
end end
it 'includes a message advising a redirection occurred' do
redirect_message = <<~STR
This request to a Geo secondary node will be forwarded to the
Geo primary node:
http://primary.example.com/#{project.full_path}.git
STR
expect(subject).to include({
'type' => 'basic',
'message' => redirect_message
})
end
end end
context 'when the secondary does not have a GeoNodeStatus' do context 'when the push was not redirected from a Geo secondary to the primary' do
let(:node) { nil }
it 'does not include current Geo secondary lag in the output' do it 'does not include current Geo secondary lag in the output' do
expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything }) expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything })
end end
end end
end
it 'includes a message advising a redirection occurred' do describe 'storage size limit alerts' do
redirect_message = <<~STR let(:check_storage_size_response) { ServiceResponse.success }
This request to a Geo secondary node will be forwarded to the
Geo primary node:
http://primary.example.com/#{project.full_path}.git before do
STR expect_next_instance_of(Namespaces::CheckStorageSizeService, project.namespace, user) do |check_storage_size_service|
expect(check_storage_size_service).to receive(:execute).and_return(check_storage_size_response)
end
end
expect(subject).to include({ context 'when there is no payload' do
'type' => 'basic', it 'adds no alert' do
'message' => redirect_message expect(subject.size).to eq(0)
}) end
end end
end
context 'when the push was not redirected from a Geo secondary to the primary' do context 'when there is payload' do
let(:node) { nil } let(:check_storage_size_response) do
ServiceResponse.success(
payload: {
alert_level: :info,
usage_message: "Usage",
explanation_message: "Explanation"
}
)
end
it 'does not include current Geo secondary lag in the output' do it 'adds an alert' do
expect(subject).not_to include({ 'message' => a_string_matching('replication lag'), 'type' => anything }) response = subject
expect(response.size).to eq(1)
expect(response).to include({ 'type' => 'alert', 'message' => "##### INFO #####\nUsage\nExplanation" })
end
end end
end end
end end
...@@ -21,7 +21,7 @@ RSpec.describe Namespaces::CheckStorageSizeService, '#execute' do ...@@ -21,7 +21,7 @@ RSpec.describe Namespaces::CheckStorageSizeService, '#execute' do
above_size_limit?: current_size > limit above_size_limit?: current_size > limit
) )
expect(Namespace::RootStorageSize).to receive(:new).and_return(root_storage_size) expect(EE::Namespace::RootStorageSize).to receive(:new).and_return(root_storage_size)
end end
context 'feature flag' do context 'feature flag' do
......
...@@ -52,8 +52,6 @@ RSpec.describe GroupsController do ...@@ -52,8 +52,6 @@ RSpec.describe GroupsController do
expect(assigns(:events).map(&:id)).to contain_exactly(event.id) expect(assigns(:events).map(&:id)).to contain_exactly(event.id)
end end
end end
it_behaves_like 'namespace storage limit alert'
end end
describe 'GET #show' do describe 'GET #show' do
......
...@@ -385,15 +385,6 @@ RSpec.describe ProjectsController do ...@@ -385,15 +385,6 @@ RSpec.describe ProjectsController do
.not_to exceed_query_limit(2).for_query(expected_query) .not_to exceed_query_limit(2).for_query(expected_query)
end end
end end
context 'namespace storage limit' do
let_it_be(:project) { create(:project, :public, :repository ) }
let(:namespace) { project.namespace }
subject { get :show, params: { namespace_id: namespace, id: project } }
it_behaves_like 'namespace storage limit alert'
end
end end
describe 'GET edit' do describe 'GET edit' do
......
...@@ -8,10 +8,10 @@ RSpec.describe GitlabSchema.types['Namespace'] do ...@@ -8,10 +8,10 @@ RSpec.describe GitlabSchema.types['Namespace'] do
it 'has the expected fields' do it 'has the expected fields' do
expected_fields = %w[ expected_fields = %w[
id name path full_name full_path description description_html visibility id name path full_name full_path description description_html visibility
lfs_enabled request_access_enabled storage_size_limit projects root_storage_statistics lfs_enabled request_access_enabled projects root_storage_statistics
] ]
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to include_graphql_fields(*expected_fields)
end end
specify { expect(described_class).to require_graphql_authorizations(:read_namespace) } specify { expect(described_class).to require_graphql_authorizations(:read_namespace) }
......
...@@ -174,96 +174,4 @@ RSpec.describe NamespacesHelper do ...@@ -174,96 +174,4 @@ RSpec.describe NamespacesHelper do
end end
end end
end end
describe '#namespace_storage_alert' do
subject { helper.namespace_storage_alert(namespace) }
let(:namespace) { build(:namespace) }
let(:payload) do
{
alert_level: :info,
usage_message: "Usage",
explanation_message: "Explanation",
root_namespace: namespace
}
end
before do
allow(helper).to receive(:current_user).and_return(admin)
allow_next_instance_of(Namespaces::CheckStorageSizeService, namespace, admin) do |check_storage_size_service|
expect(check_storage_size_service).to receive(:execute).and_return(ServiceResponse.success(payload: payload))
end
end
context 'when payload is not empty and no cookie is set' do
it { is_expected.to eq(payload) }
end
context 'when there is no current_user' do
before do
allow(helper).to receive(:current_user).and_return(nil)
end
it { is_expected.to eq({}) }
end
context 'when payload is empty' do
let(:payload) { {} }
it { is_expected.to eq({}) }
end
context 'when cookie is set' do
before do
helper.request.cookies["hide_storage_limit_alert_#{namespace.id}_info"] = 'true'
end
it { is_expected.to eq({}) }
end
context 'when payload is empty and cookie is set' do
let(:payload) { {} }
before do
helper.request.cookies["hide_storage_limit_alert_#{namespace.id}_info"] = 'true'
end
it { is_expected.to eq({}) }
end
end
describe '#namespace_storage_alert_style' do
using RSpec::Parameterized::TableSyntax
subject { helper.namespace_storage_alert_style(alert_level) }
where(:alert_level, :result) do
:info | 'info'
:warning | 'warning'
:error | 'danger'
:alert | 'danger'
end
with_them do
it { is_expected.to eq(result) }
end
end
describe '#namespace_storage_alert_icon' do
using RSpec::Parameterized::TableSyntax
subject { helper.namespace_storage_alert_icon(alert_level) }
where(:alert_level, :result) do
:info | 'information-o'
:warning | 'warning'
:error | 'error'
:alert | 'error'
end
with_them do
it { is_expected.to eq(result) }
end
end
end end
...@@ -166,41 +166,6 @@ RSpec.describe PostReceiveService do ...@@ -166,41 +166,6 @@ RSpec.describe PostReceiveService do
expect(subject).to include(build_alert_message(message)) expect(subject).to include(build_alert_message(message))
end end
end end
context 'storage size limit alerts' do
let(:check_storage_size_response) { ServiceResponse.success }
before do
expect_next_instance_of(Namespaces::CheckStorageSizeService, project.namespace, user) do |check_storage_size_service|
expect(check_storage_size_service).to receive(:execute).and_return(check_storage_size_response)
end
end
context 'when there is no payload' do
it 'adds no alert' do
expect(subject.size).to eq(1)
end
end
context 'when there is payload' do
let(:check_storage_size_response) do
ServiceResponse.success(
payload: {
alert_level: :info,
usage_message: "Usage",
explanation_message: "Explanation"
}
)
end
it 'adds an alert' do
response = subject
expect(response.size).to eq(2)
expect(response).to include(build_alert_message("##### INFO #####\nUsage\nExplanation"))
end
end
end
end end
context 'with PersonalSnippet' do context 'with PersonalSnippet' do
......
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