Commit 45f52235 authored by Matija Čupić's avatar Matija Čupić

Remove ListGcpProjectsWorker

parent 7a1ce56f
require 'securerandom'
class ListGcpProjectsWorker
include ApplicationWorker
include ClusterQueue
LEASE_TIMEOUT = 3.seconds.to_i
SESSION_KEY_TIMEOUT = 5.minutes
PROJECT_TIMEOUT = 1.hour
BILLING_CHANGED_LABELS = { state_transition: nil }.freeze
def self.get_session_token(token_key)
Gitlab::Redis::SharedState.with do |redis|
redis.get(get_redis_session_key(token_key))
end
end
def self.store_session_token(token)
generate_token_key.tap do |token_key|
Gitlab::Redis::SharedState.with do |redis|
redis.set(get_redis_session_key(token_key), token, ex: SESSION_KEY_TIMEOUT)
end
end
end
def self.read_projects(token)
Gitlab::Redis::SharedState.with do |redis|
value = redis.get(redis_shared_state_key_for(token))
value ? JSON.parse(value) : []
end
end
def perform(token_key)
return unless token_key
token = self.class.get_session_token(token_key)
return unless token
return unless try_obtain_lease_for(token)
billing_enabled_projects = ListGcpProjectsService.new.execute(token)
update_billing_change_counter(!self.class.read_projects(token).empty?, !billing_enabled_projects.empty?)
self.class.store_projects(token, billing_enabled_projects.to_json)
end
private
def self.generate_token_key
SecureRandom.uuid
end
def self.get_redis_session_key(token_key)
"gitlab:gcp:session:#{token_key}"
end
def self.redis_shared_state_key_for(token)
"gitlab:gcp:#{Digest::SHA1.hexdigest(token)}:projects"
end
def self.store_projects(token, value)
Gitlab::Redis::SharedState.with do |redis|
redis.set(redis_shared_state_key_for(token), value, ex: PROJECT_TIMEOUT)
end
end
def try_obtain_lease_for(token)
Gitlab::ExclusiveLease
.new("list_gcp_projects_worker:#{token.hash}", timeout: LEASE_TIMEOUT)
.try_obtain
end
def billing_changed_counter
@billing_changed_counter ||= Gitlab::Metrics.counter(
:gcp_billing_change_count,
"Counts the number of times a GCP project changed billing_enabled state from false to true",
BILLING_CHANGED_LABELS
)
end
def state_transition(previous_state, current_state)
if previous_state.nil? && !current_state
'no_billing'
elsif previous_state.nil? && current_state
'with_billing'
elsif !previous_state && current_state
'billing_configured'
end
end
def update_billing_change_counter(previous_state, current_state)
billing_changed_counter.increment(state_transition: state_transition(previous_state, current_state))
end
end
require 'spec_helper'
describe ListGcpProjectsWorker do
describe '.perform' do
let(:token) { 'bogustoken' }
subject { described_class.new.perform('token_key') }
before do
allow(described_class).to receive(:read_projects).and_return([double])
allow_any_instance_of(described_class).to receive(:update_billing_change_counter)
end
context 'when there is a token in redis' do
before do
allow(described_class).to receive(:get_session_token).and_return(token)
end
context 'when there is no lease' do
before do
allow_any_instance_of(described_class).to receive(:try_obtain_lease_for).and_return('randomuuid')
end
it 'calls the service' do
expect(ListGcpProjectsService).to receive_message_chain(:new, :execute).and_return([double])
subject
end
it 'stores projects in redis' do
expect(ListGcpProjectsService).to receive_message_chain(:new, :execute).and_return([double])
expect(described_class).to receive(:store_projects).with(token, anything)
subject
end
end
context 'when there is a lease' do
before do
allow_any_instance_of(described_class).to receive(:try_obtain_lease_for).and_return(false)
end
it 'does not call the service' do
expect(ListGcpProjectsService).not_to receive(:new)
subject
end
end
end
context 'when there is no token in redis' do
before do
allow(described_class).to receive(:get_session_token).and_return(nil)
end
it 'does not call the service' do
expect(ListGcpProjectsService).not_to receive(:new)
subject
end
end
end
describe 'billing change counter' do
subject { described_class.new.perform('token_key') }
before do
allow(described_class).to receive(:get_session_token).and_return('bogustoken')
allow_any_instance_of(described_class).to receive(:try_obtain_lease_for).and_return('randomuuid')
allow(described_class).to receive(:store_projects)
end
context 'when there are no projects in redis' do
before do
expect(described_class).to receive(:read_projects).and_return([])
end
context 'when the service does not return projects' do
before do
expect(ListGcpProjectsService).to receive_message_chain(:new, :execute).and_return([])
end
it 'increments the billing change counter' do
expect_any_instance_of(described_class).to receive_message_chain(:billing_changed_counter, :increment)
subject
end
end
context 'when the service returns projects' do
before do
expect(ListGcpProjectsService).to receive_message_chain(:new, :execute).and_return([double])
end
it 'increments the billing change counter' do
expect_any_instance_of(described_class).to receive_message_chain(:billing_changed_counter, :increment)
subject
end
end
end
context 'when there are projects in redis' do
before do
expect(described_class).to receive(:read_projects).and_return([double])
expect(ListGcpProjectsService).to receive_message_chain(:new, :execute).and_return([double])
end
it 'increments the billing change counter' do
expect_any_instance_of(described_class).to receive_message_chain(:billing_changed_counter, :increment)
subject
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