Commit 5255296f authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'extract-ci-minutes-quota' into 'master'

Extract Ci::Minutes::Quota class

See merge request gitlab-org/gitlab!29230
parents aa9ee169 8d0594a8
......@@ -3,28 +3,18 @@
module EE
module NamespacesHelper
def namespace_extra_shared_runner_limits_quota(namespace)
limit = namespace.extra_shared_runners_minutes_limit.to_i
used = namespace.extra_shared_runners_minutes.to_i
status = namespace.extra_shared_runners_minutes_used? ? 'over_quota' : 'under_quota'
report = ::Ci::Minutes::Quota.new(namespace).purchased_minutes_report
content_tag(:span, class: "shared_runners_limit_#{status}") do
"#{used} / #{limit}"
content_tag(:span, class: "shared_runners_limit_#{report.status}") do
"#{report.used} / #{report.limit}"
end
end
def namespace_shared_runner_limits_quota(namespace)
used = namespace.shared_runners_minutes(include_extra: false).to_i
if namespace.shared_runners_minutes_limit_enabled?
limit = namespace.actual_shared_runners_minutes_limit(include_extra: false)
status = namespace.shared_runners_minutes_used? ? 'over_quota' : 'under_quota'
else
limit = 'Unlimited'
status = 'disabled'
end
report = ::Ci::Minutes::Quota.new(namespace).monthly_minutes_report
content_tag(:span, class: "shared_runners_limit_#{status}") do
"#{used} / #{limit}"
content_tag(:span, class: "shared_runners_limit_#{report.status}") do
"#{report.used} / #{report.limit}"
end
end
......
# frozen_string_literal: true
# This class provides current status of Shared Runners minutes usage for a namespace
# taking in consideration the monthly minutes allowance that Gitlab.com provides and
# any possible purchased minutes.
module Ci
module Minutes
class Quota
Report = Struct.new(:used, :limit, :status)
def initialize(namespace)
@namespace = namespace
end
# Status of the monthly allowance being used.
def monthly_minutes_report
if namespace.shared_runners_minutes_limit_enabled? # TODO: try to refactor this
status = monthly_minutes_used_up? ? :over_quota : :under_quota
Report.new(monthly_minutes_used, monthly_minutes, status)
else
Report.new(monthly_minutes_used, 'Unlimited', :disabled)
end
end
# Status of any purchased minutes used.
def purchased_minutes_report
status = purchased_minutes_used_up? ? :over_quota : :under_quota
Report.new(purchased_minutes_used, purchased_minutes, status)
end
private
# TODO: maps to NamespacesHelper#namespace_shared_runner_limits_percent_used
# TODO: consider including this into monthly_minutes_report
def monthly_percent_used
return 0 unless namespace.shared_runners_minutes_limit_enabled?
100 * monthly_minutes_used.to_i / monthly_minutes
end
# TODO: maps to NamespacesHelper#namespace_extra_shared_runner_limits_percent_used
# TODO: consider including this into purchased_minutes_report
def purchased_percent_used
return 0 if purchased_minutes.zero?
100 * purchased_minutes_used.to_i / purchased_minutes
end
# TODO: maps to Namespace#shared_runners_minutes_used?
def monthly_minutes_used_up?
namespace.shared_runners_minutes_limit_enabled? &&
monthly_minutes_used >= monthly_minutes
end
# TODO: maps to Namespace#extra_shared_runners_minutes_used?
def purchased_minutes_used_up?
namespace.shared_runners_minutes_limit_enabled? &&
any_minutes_purchased? &&
purchased_minutes_used >= purchased_minutes
end
# TODO: maps to NamespaceStatistics#shared_runners_minutes(include_extra: false)
def monthly_minutes_used
minutes_used - purchased_minutes_used
end
def monthly_minutes_available?
minutes_used <= monthly_minutes
end
# TODO: maps to NamespaceStatistics#extra_shared_runners_minutes
def purchased_minutes_used
return 0 if no_minutes_purchased? || monthly_minutes_available?
minutes_used - monthly_minutes
end
def no_minutes_purchased?
purchased_minutes.zero?
end
def any_minutes_purchased?
purchased_minutes.positive?
end
# TODO: maps to NamespaceStatistics#shared_runners_minutes(include_extra: true)
def minutes_used
@minutes_used ||= namespace.shared_runners_seconds.to_i / 60
end
# TODO: maps to Namespace#actual_shared_runners_minuts_limit(include_extra: false)
def monthly_minutes
@monthly_minutes ||= (namespace.shared_runners_minutes_limit || ::Gitlab::CurrentSettings.shared_runners_minutes).to_i
end
def purchased_minutes
@purchased_minutes ||= namespace.extra_shared_runners_minutes_limit.to_i
end
attr_reader :namespace
end
end
end
......@@ -33,7 +33,7 @@ describe EE::NamespacesHelper do
end
it 'returns the proper value for the used section' do
allow(user_group).to receive(:shared_runners_minutes).and_return(100)
allow(user_group).to receive(:shared_runners_seconds).and_return(100 * 60)
expect(helper.namespace_shared_runner_limits_quota(user_group)).to match(%r{100 / Unlimited})
end
......@@ -42,7 +42,7 @@ describe EE::NamespacesHelper do
context "when it's limited" do
before do
allow(user_group).to receive(:shared_runners_minutes_limit_enabled?).and_return(true)
allow(user_group).to receive(:shared_runners_minutes).and_return(100)
allow(user_group).to receive(:shared_runners_seconds).and_return(100 * 60)
user_group.update!(shared_runners_minutes_limit: 500)
end
......@@ -56,7 +56,7 @@ describe EE::NamespacesHelper do
describe '#namespace_extra_shared_runner_limits_quota' do
context 'when extra minutes are assigned' do
it 'returns the proper values for used and limit sections' do
allow(user_group).to receive(:extra_shared_runners_minutes).and_return(50)
allow(user_group).to receive(:shared_runners_seconds).and_return(50 * 60)
user_group.update!(extra_shared_runners_minutes_limit: 100)
expect(helper.namespace_extra_shared_runner_limits_quota(user_group)).to match(%r{50 / 100})
......
# frozen_string_literal: true
require 'spec_helper'
describe Ci::Minutes::Quota do
let_it_be(:namespace) do
create(:namespace, namespace_statistics: create(:namespace_statistics))
end
let(:quota) { described_class.new(namespace) }
describe '#monthly_minutes_report' do
context 'when unlimited' do
before do
allow(namespace).to receive(:shared_runners_minutes_limit_enabled?).and_return(false)
end
context 'when minutes are not used' do
it 'returns unlimited report with no usage' do
report = quota.monthly_minutes_report
expect(report.limit).to eq 'Unlimited'
expect(report.used).to eq 0
expect(report.status).to eq :disabled
end
end
context 'when minutes are used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 20.minutes
end
it 'returns unlimited report with usage' do
report = quota.monthly_minutes_report
expect(report.limit).to eq 'Unlimited'
expect(report.used).to eq 20
expect(report.status).to eq :disabled
end
end
end
context 'when limited' do
before do
allow(namespace).to receive(:shared_runners_minutes_limit_enabled?).and_return(true)
namespace.shared_runners_minutes_limit = 100
end
context 'when minutes are not all used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 30.minutes
end
it 'returns report with under quota' do
report = quota.monthly_minutes_report
expect(report.limit).to eq 100
expect(report.used).to eq 30
expect(report.status).to eq :under_quota
end
end
context 'when minutes are all used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 101.minutes
end
it 'returns report with over quota' do
report = quota.monthly_minutes_report
expect(report.limit).to eq 100
expect(report.used).to eq 101
expect(report.status).to eq :over_quota
end
end
end
end
describe '#purchased_minutes_report' do
context 'when limit enabled' do
before do
allow(namespace).to receive(:shared_runners_minutes_limit_enabled?).and_return(true)
namespace.shared_runners_minutes_limit = 200
end
context 'when extra minutes have been purchased' do
before do
namespace.extra_shared_runners_minutes_limit = 100
end
context 'when all monthly minutes are used and some puarchased minutes are used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 250.minutes
end
it 'returns report with under quota' do
report = quota.purchased_minutes_report
expect(report.limit).to eq 100
expect(report.used).to eq 50
expect(report.status).to eq :under_quota
end
end
context 'when all monthly and all puarchased minutes have been used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 301.minutes
end
it 'returns report with over quota' do
report = quota.purchased_minutes_report
expect(report.limit).to eq 100
expect(report.used).to eq 101
expect(report.status).to eq :over_quota
end
end
context 'when not all monthly minutes have been used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 190.minutes
end
it 'returns report with no usage' do
report = quota.purchased_minutes_report
expect(report.limit).to eq 100
expect(report.used).to eq 0
expect(report.status).to eq :under_quota
end
end
end
context 'when no extra minutes have been purchased' do
before do
namespace.extra_shared_runners_minutes_limit = nil
end
context 'when all monthly minutes have been used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 201.minutes
end
it 'returns report without usage' do
report = quota.purchased_minutes_report
expect(report.limit).to eq 0
expect(report.used).to eq 0
expect(report.status).to eq :under_quota
end
end
context 'when not all monthly minutes have been used' do
before do
namespace.namespace_statistics.shared_runners_seconds = 190.minutes
end
it 'returns report with no usage' do
report = quota.purchased_minutes_report
expect(report.limit).to eq 0
expect(report.used).to eq 0
expect(report.status).to eq :under_quota
end
end
end
end
end
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