Commit 4554b194 authored by Brett Walker's avatar Brett Walker Committed by Alper Akgun

Background migration for jira deployment type

to be backfilled
parent 545f50f8
---
title: Background migration for setting Jira tracker data deployment type
merge_request: 37002
author:
type: changed
# frozen_string_literal: true
class BackfillJiraTrackerDeploymentType < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
MIGRATION = 'BackfillJiraTrackerDeploymentType'
BATCH_SIZE = 100
BATCH_INTERVAL = 20.seconds
class JiraTrackerData < ActiveRecord::Base
self.table_name = 'jira_tracker_data'
include ::EachBatch
end
# 78_627 JiraTrackerData records, 76_313 with deployment_type == 0
def up
JiraTrackerData.where(deployment_type: 0).each_batch(of: BATCH_SIZE) do |relation, index|
jobs = relation.pluck(:id).map { |id| [MIGRATION, [id]] }
delay = index * BATCH_INTERVAL
bulk_migrate_in(delay, jobs)
end
end
def down
# no-op
# intentionally blank
end
end
6cba0aecae495458b3b161999417cb9d790e60b4edfb10bb26b9684d466e3fd2
\ No newline at end of file
# frozen_string_literal: true
# Based on https://community.developer.atlassian.com/t/get-rest-api-3-filter-search/29459/2,
# it's enough at the moment to simply notice if the url is from `atlassian.net`
module Gitlab
module BackgroundMigration
# Backfill the deployment_type in jira_tracker_data table
class BackfillJiraTrackerDeploymentType
# Migration only version of jira_tracker_data table
class JiraTrackerDataTemp < ApplicationRecord
self.table_name = 'jira_tracker_data'
def self.encryption_options
{
key: Settings.attr_encrypted_db_key_base_32,
encode: true,
mode: :per_attribute_iv,
algorithm: 'aes-256-gcm'
}
end
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options
enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
end
# Migration only version of services table
class JiraServiceTemp < ApplicationRecord
self.table_name = 'services'
self.inheritance_column = :_type_disabled
end
def perform(tracker_id)
@jira_tracker_data = JiraTrackerDataTemp.find_by(id: tracker_id, deployment_type: 0)
return unless jira_tracker_data
return unless client_url
update_deployment_type
end
private
attr_reader :jira_tracker_data
def client_url
jira_tracker_data.api_url.presence || jira_tracker_data.url.presence
end
def server_type
client_url.downcase.include?('.atlassian.net') ? :cloud : :server
end
def update_deployment_type
case server_type
when :server
jira_tracker_data.deployment_server!
when :cloud
jira_tracker_data.deployment_cloud!
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillJiraTrackerDeploymentType, :migration, schema: 20200910155617 do
let_it_be(:jira_service_temp) { described_class::JiraServiceTemp }
let_it_be(:jira_tracker_data_temp) { described_class::JiraTrackerDataTemp }
let_it_be(:api_host) { 'https://api.atlassian.net' }
let(:jira_service) { jira_service_temp.create!(type: 'JiraService', active: true, category: 'issue_tracker') }
subject { described_class.new }
describe '#perform' do
context 'when tracker is not valid' do
it 'returns if deployment already set' do
jira_tracker_data = jira_tracker_data_temp.create!(service_id: jira_service.id,
url: api_host, deployment_type: 1)
expect(subject).not_to receive(:update_deployment_type)
subject.perform(jira_tracker_data.id)
end
it 'returns if no url is set' do
jira_tracker_data = jira_tracker_data_temp.create!(service_id: jira_service.id,
deployment_type: 0)
expect(subject).not_to receive(:update_deployment_type)
subject.perform(jira_tracker_data.id)
end
end
context 'when tracker is valid' do
let(:jira_tracker_data) do
jira_tracker_data_temp.create!(service_id: jira_service.id,
url: api_host, deployment_type: 0)
end
it 'sets the deployment_type to cloud' do
subject.perform(jira_tracker_data.id)
expect(jira_tracker_data.reload.deployment_cloud?).to be_truthy
end
describe 'with a mixed case url' do
let_it_be(:api_host) { 'https://api.AtlassiaN.nEt' }
it 'sets the deployment_type to cloud' do
subject.perform(jira_tracker_data.id)
expect(jira_tracker_data.reload.deployment_cloud?).to be_truthy
end
end
describe 'with a Jira Server' do
let_it_be(:api_host) { 'https://my.server.net' }
it 'sets the deployment_type to server' do
subject.perform(jira_tracker_data.id)
expect(jira_tracker_data.reload.deployment_server?).to be_truthy
end
end
describe 'with api_url specified' do
let(:jira_tracker_data) do
jira_tracker_data_temp.create!(service_id: jira_service.id,
api_url: api_host, deployment_type: 0)
end
it 'sets the deployment_type to cloud' do
subject.perform(jira_tracker_data.id)
expect(jira_tracker_data.reload.deployment_cloud?).to be_truthy
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200910155617_backfill_jira_tracker_deployment_type.rb')
RSpec.describe BackfillJiraTrackerDeploymentType, :sidekiq, schema: 20200910155617 do
let(:services) { table(:services) }
let(:jira_tracker_data) { table(:jira_tracker_data) }
let(:migration) { described_class.new }
let(:batch_interval) { described_class::BATCH_INTERVAL }
describe '#up' do
before do
stub_const("#{described_class}::BATCH_SIZE", 2)
active_service = services.create!(type: 'JiraService', active: true)
inactive_service = services.create!(type: 'JiraService', active: false)
jira_tracker_data.create!(id: 1, service_id: active_service.id, deployment_type: 0)
jira_tracker_data.create!(id: 2, service_id: active_service.id, deployment_type: 1)
jira_tracker_data.create!(id: 3, service_id: inactive_service.id, deployment_type: 2)
jira_tracker_data.create!(id: 4, service_id: inactive_service.id, deployment_type: 0)
jira_tracker_data.create!(id: 5, service_id: active_service.id, deployment_type: 0)
end
it 'schedules BackfillJiraTrackerDeploymentType background jobs' do
Sidekiq::Testing.fake! do
freeze_time do
migration.up
expect(BackgroundMigrationWorker.jobs.size).to eq(3)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval, 1)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval, 4)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval * 2, 5)
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