Commit 5608a604 authored by Tiger Watson's avatar Tiger Watson

Merge branch...

Merge branch '255519-migrate-existing-generic-alert-endpoints-to-http-integrations-format-2' into 'master'

Migrate existing Generic Alert Endpoints to HTTP integrations format

See merge request gitlab-org/gitlab!46188
parents c0dc8d31 5b6a7b1c
......@@ -14,6 +14,8 @@ class AlertsService < Service
before_validation :prevent_token_assignment
before_validation :ensure_token, if: :activated?
after_save :update_http_integration
def url
return if instance? || template?
......@@ -77,6 +79,14 @@ class AlertsService < Service
def url_helpers
Gitlab::Routing.url_helpers
end
def update_http_integration
return unless project_id && type == 'AlertsService'
AlertManagement::SyncAlertServiceDataService # rubocop: disable CodeReuse/ServiceClass
.new(self)
.execute
end
end
AlertsService.prepend_if_ee('EE::AlertsService')
# frozen_string_literal: true
module AlertManagement
class SyncAlertServiceDataService
# @param alert_service [AlertsService]
def initialize(alert_service)
@alert_service = alert_service
end
def execute
http_integration = find_http_integration
result = if http_integration
update_integration_data(http_integration)
else
create_integration
end
result ? ServiceResponse.success : ServiceResponse.error(message: 'Update failed')
end
private
attr_reader :alert_service
def find_http_integration
AlertManagement::HttpIntegrationsFinder.new(
alert_service.project,
endpoint_identifier: ::AlertManagement::HttpIntegration::LEGACY_IDENTIFIER
)
.execute
.first
end
def create_integration
new_integration = AlertManagement::HttpIntegration.create(
project_id: alert_service.project_id,
name: 'HTTP endpoint',
endpoint_identifier: AlertManagement::HttpIntegration::LEGACY_IDENTIFIER,
active: alert_service.active,
encrypted_token: alert_service.data.encrypted_token,
encrypted_token_iv: alert_service.data.encrypted_token_iv
)
new_integration.persisted?
end
def update_integration_data(http_integration)
http_integration.update(
active: alert_service.active,
encrypted_token: alert_service.data.encrypted_token,
encrypted_token_iv: alert_service.data.encrypted_token_iv
)
end
end
end
---
title: Migrate Alert Service to HTTP Integrations model
merge_request: 46188
author:
type: added
# frozen_string_literal: true
class MigrateServicesToHttpIntegrations < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
ALERT_SERVICE_TYPE = 'AlertsService'
SERVICE_NAMES_IDENTIFIER = {
name: 'HTTP endpoint',
identifier: 'legacy'
}
class HttpIntegration < ActiveRecord::Base
self.table_name = 'alert_management_http_integrations'
end
# For each Alerts service,
# Create the matching HttpIntegration
def up
HttpIntegration.reset_column_information
sql = <<~SQL
SELECT * FROM services
JOIN alerts_service_data
ON (services.id = alerts_service_data.service_id)
WHERE type = '#{ALERT_SERVICE_TYPE}'
AND active = TRUE
SQL
current_time = Time.current
values = select_all(sql).map do |alerts_service|
{
project_id: alerts_service['project_id'],
name: SERVICE_NAMES_IDENTIFIER[:name],
endpoint_identifier: SERVICE_NAMES_IDENTIFIER[:identifier],
encrypted_token: alerts_service['encrypted_token'],
encrypted_token_iv: alerts_service['encrypted_token_iv'],
active: alerts_service['active'],
updated_at: current_time,
created_at: current_time
}
end
HttpIntegration.insert_all(values) if values.present?
end
def down
# no-op
end
end
34e357b739235d627e543e1bc7202e0cf26f5b1ca8021bb25357e29e883f785b
\ No newline at end of file
# frozen_string_literal: true
FactoryBot.define do
factory :alerts_service_data do
service { association(:alerts_service) }
token { SecureRandom.hex }
end
end
......@@ -56,6 +56,10 @@ FactoryBot.define do
trait :inactive do
active { false }
end
before(:create) do |service|
service.data = build(:alerts_service_data, service: service)
end
end
factory :drone_ci_service do
......
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20201027002551_migrate_services_to_http_integrations.rb')
RSpec.describe MigrateServicesToHttpIntegrations do
let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
let!(:alert_service) { table(:services).create!(type: 'AlertsService', project_id: project.id, active: true) }
let!(:alert_service_data) { table(:alerts_service_data).create!(service_id: alert_service.id, encrypted_token: 'test', encrypted_token_iv: 'test')}
let(:http_integrations) { table(:alert_management_http_integrations) }
describe '#up' do
it 'creates the http integrations from the alert services', :aggregate_failures do
expect { migrate! }.to change { http_integrations.count }.by(1)
http_integration = http_integrations.last
expect(http_integration.project_id).to eq(alert_service.project_id)
expect(http_integration.encrypted_token).to eq(alert_service_data.encrypted_token)
expect(http_integration.encrypted_token_iv).to eq(alert_service_data.encrypted_token_iv)
expect(http_integration.active).to eq(alert_service.active)
expect(http_integration.name).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:name])
expect(http_integration.endpoint_identifier).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:identifier])
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AlertManagement::SyncAlertServiceDataService do
let_it_be(:alerts_service) do
AlertsService.skip_callback(:save, :after, :update_http_integration)
service = create(:alerts_service, :active)
AlertsService.set_callback(:save, :after, :update_http_integration)
service
end
describe '#execute' do
subject(:execute) { described_class.new(alerts_service).execute }
context 'without http integration' do
it 'creates the integration' do
expect { execute }
.to change { AlertManagement::HttpIntegration.count }.by(1)
end
it 'returns a success' do
expect(subject.success?).to eq(true)
end
end
context 'existing legacy http integration' do
let_it_be(:integration) { create(:alert_management_http_integration, :legacy, project: alerts_service.project) }
it 'updates the integration' do
expect { execute }
.to change { integration.reload.encrypted_token }.to(alerts_service.data.encrypted_token)
.and change { integration.encrypted_token_iv }.to(alerts_service.data.encrypted_token_iv)
end
it 'returns a success' do
expect(subject.success?).to eq(true)
end
end
context 'existing other http integration' do
let_it_be(:integration) { create(:alert_management_http_integration, project: alerts_service.project) }
it 'creates the integration' do
expect { execute }
.to change { AlertManagement::HttpIntegration.count }.by(1)
end
it 'returns a success' do
expect(subject.success?).to eq(true)
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