Commit c120336d authored by Rubén Dávila's avatar Rubén Dávila

Add new endpoint to do a manual sync of seat link

`should_sync_seats?` was moved because we want to use that method
outside of the worker.
parent 5f64a44d
...@@ -62,6 +62,18 @@ class Admin::LicensesController < Admin::ApplicationController ...@@ -62,6 +62,18 @@ class Admin::LicensesController < Admin::ApplicationController
redirect_to admin_license_path, status: :found redirect_to admin_license_path, status: :found
end end
def sync_seat_link
sync_result = Gitlab::SeatLinkData.new.sync
if sync_result
flash[:notice] = _('Your license was successfully synced.')
else
flash[:error] = _('There was an error when trying to sync your license. Please verify that your instance is using an active license key.')
end
redirect_to admin_license_path
end
private private
def build_license def build_license
......
...@@ -19,9 +19,20 @@ module Gitlab ...@@ -19,9 +19,20 @@ module Gitlab
@active_users = active_users || default_active_count @active_users = active_users || default_active_count
end end
# Returns true if historical data exists between license start and the given date. def sync
def historical_data_exists? return unless should_sync_seats?
historical_data.present?
SyncSeatLinkWorker.perform_async
end
# Only sync paid licenses from start date until 14 days after expiration
# when seat link feature is enabled.
def should_sync_seats?
Gitlab::CurrentSettings.seat_link_enabled? &&
!license&.trial? &&
license&.expires_at && # Skip sync if license has no expiration
historical_data.present? && # Skip sync if there is no historical data
timestamp.between?(license.starts_at.beginning_of_day, license.expires_at.end_of_day + 14.days)
end end
private private
...@@ -36,19 +47,23 @@ module Gitlab ...@@ -36,19 +47,23 @@ module Gitlab
} }
end end
def license
::License.current
end
def default_key def default_key
::License.current.data license&.data
end end
def default_max_count def default_max_count
::License.current.historical_max(to: timestamp) license&.historical_max(to: timestamp)
end end
def historical_data def historical_data
strong_memoize(:historical_data) do strong_memoize(:historical_data) do
to_timestamp = timestamp || Time.current to_timestamp = timestamp || Time.current
::License.current.historical_data(to: to_timestamp).order(:recorded_at).last license&.historical_data(to: to_timestamp)&.order(:recorded_at)&.last
end end
end end
......
...@@ -13,7 +13,7 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker ...@@ -13,7 +13,7 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 12, dead: false sidekiq_options retry: 12, dead: false
def perform def perform
return unless should_sync_seats? return unless seat_link_data.should_sync_seats?
SyncSeatLinkRequestWorker.perform_async( SyncSeatLinkRequestWorker.perform_async(
seat_link_data.timestamp.iso8601, seat_link_data.timestamp.iso8601,
...@@ -28,15 +28,4 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker ...@@ -28,15 +28,4 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker
def seat_link_data def seat_link_data
@seat_link_data ||= Gitlab::SeatLinkData.new @seat_link_data ||= Gitlab::SeatLinkData.new
end end
# Only sync paid licenses from start date until 14 days after expiration
# when seat link feature is enabled.
def should_sync_seats?
Gitlab::CurrentSettings.seat_link_enabled? &&
License.current &&
!License.current.trial? &&
License.current.expires_at && # Skip sync if license has no expiration
seat_link_data.historical_data_exists? && # Skip sync if there is no historical data
seat_link_data.timestamp.between?(License.current.starts_at.beginning_of_day, License.current.expires_at.end_of_day + 14.days)
end
end end
...@@ -28,6 +28,7 @@ namespace :admin do ...@@ -28,6 +28,7 @@ namespace :admin do
resource :license, only: [:show, :new, :create, :destroy] do resource :license, only: [:show, :new, :create, :destroy] do
get :download, on: :member get :download, on: :member
post :sync_seat_link, on: :collection
resource :usage_export, controller: 'licenses/usage_exports', only: [:show] resource :usage_export, controller: 'licenses/usage_exports', only: [:show]
end end
......
...@@ -83,4 +83,35 @@ RSpec.describe Admin::LicensesController do ...@@ -83,4 +83,35 @@ RSpec.describe Admin::LicensesController do
end end
end end
end end
describe 'POST sync_seat_link' do
let_it_be(:historical_data) { create(:historical_data, recorded_at: Time.current) }
before do
allow(License).to receive(:current).and_return(create(:license))
allow(Settings.gitlab).to receive(:seat_link_enabled).and_return(seat_link_enabled)
end
context 'with seat link enabled' do
let(:seat_link_enabled) { true }
it 'redirects with a successful message' do
post :sync_seat_link
expect(response).to redirect_to(admin_license_path)
expect(flash[:notice]).to eq('Your license was successfully synced.')
end
end
context 'with seat link disabled' do
let(:seat_link_enabled) { false }
it 'redirects with an error message' do
post :sync_seat_link
expect(response).to redirect_to(admin_license_path)
expect(flash[:error]).to match('There was an error when trying to sync your license.')
end
end
end
end end
...@@ -91,24 +91,69 @@ RSpec.describe Gitlab::SeatLinkData do ...@@ -91,24 +91,69 @@ RSpec.describe Gitlab::SeatLinkData do
end end
end end
describe '#historical_data_exists?' do describe '#sync' do
let_it_be(:license) { create_current_license(starts_at: Date.current - 7.days) } before do
allow(subject).to receive(:should_sync_seats?).and_return(sync_seats)
end
context 'when ready to sync seats' do
let(:sync_seats) { true }
it 'performs the sync' do
expect(SyncSeatLinkWorker).to receive(:perform_async)
subject.sync
end
end
it 'returns false if no historical data exists' do context 'when not ready to sync seats' do
expect(described_class.new.historical_data_exists?).to be(false) let(:sync_seats) { false }
it 'does not perform the sync' do
expect(SyncSeatLinkWorker).not_to receive(:perform_async)
subject.sync
end
end end
end
describe '#should_sync_seats?' do
let_it_be(:historical_data) { create(:historical_data, recorded_at: timestamp) }
subject { super().should_sync_seats? }
it 'returns false if no historical data exists within [license start date, seat_link_data.date]' do context 'when all the pre conditions are valid' do
create(:historical_data, recorded_at: Time.current - 8.days) it { is_expected.to eq(true) }
create(:historical_data, recorded_at: Time.current) end
context 'when seat link is disabled' do
before do
allow(Settings.gitlab).to receive(:seat_link_enabled).and_return(false)
end
it { is_expected.to be_falsey }
end
context 'when license key is missing' do
before do
allow(License).to receive(:current).and_return(nil)
end
it { is_expected.to be_falsey }
end
context 'when license is trial' do
before do
allow(License).to receive(:current).and_return(create(:license, trial: true))
end
expect(described_class.new(timestamp: Time.current - 1.day).historical_data_exists?).to be(false) it { is_expected.to be_falsey }
end end
it 'returns true if historical data exists within [license start date, seat_link_data.date]' do context 'when timestamp is out of the range' do
create(:historical_data, recorded_at: Time.current - 2.days) let(:timestamp) { Time.iso8601('2015-03-22T06:09:18Z') }
expect(described_class.new(timestamp: Time.current - 1.day).historical_data_exists?).to be(true) it { is_expected.to be_falsey }
end end
end end
end end
...@@ -30876,6 +30876,9 @@ msgstr "" ...@@ -30876,6 +30876,9 @@ msgstr ""
msgid "There was an error when subscribing to this label." msgid "There was an error when subscribing to this label."
msgstr "" msgstr ""
msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
msgstr ""
msgid "There was an error when unsubscribing from this label." msgid "There was an error when unsubscribing from this label."
msgstr "" msgstr ""
...@@ -35397,6 +35400,9 @@ msgstr "" ...@@ -35397,6 +35400,9 @@ msgstr ""
msgid "Your license is valid from" msgid "Your license is valid from"
msgstr "" msgstr ""
msgid "Your license was successfully synced."
msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file." msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr "" msgstr ""
......
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