Migrate Kubernetes service integration templates to clusters
The migration uses active record model stubs so that field encryption can be more easily used.
This commit is contained in:
parent
82ccc8bc12
commit
f26884a0a8
3 changed files with 231 additions and 0 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Migrate Kubernetes service integration templates to clusters
|
||||||
|
merge_request: 28534
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -0,0 +1,102 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class MigrateK8sServiceIntegration < ActiveRecord::Migration[5.1]
|
||||||
|
include Gitlab::Database::MigrationHelpers
|
||||||
|
|
||||||
|
DOWNTIME = false
|
||||||
|
|
||||||
|
class Cluster < ActiveRecord::Base
|
||||||
|
self.table_name = 'clusters'
|
||||||
|
|
||||||
|
has_one :platform_kubernetes, class_name: 'MigrateK8sServiceIntegration::PlatformsKubernetes'
|
||||||
|
|
||||||
|
accepts_nested_attributes_for :platform_kubernetes
|
||||||
|
|
||||||
|
enum cluster_type: {
|
||||||
|
instance_type: 1,
|
||||||
|
group_type: 2,
|
||||||
|
project_type: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
enum platform_type: {
|
||||||
|
kubernetes: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
enum provider_type: {
|
||||||
|
user: 0,
|
||||||
|
gcp: 1
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
class PlatformsKubernetes < ActiveRecord::Base
|
||||||
|
self.table_name = 'cluster_platforms_kubernetes'
|
||||||
|
|
||||||
|
belongs_to :cluster, class_name: 'MigrateK8sServiceIntegration::Cluster'
|
||||||
|
|
||||||
|
attr_encrypted :token,
|
||||||
|
mode: :per_attribute_iv,
|
||||||
|
key: Settings.attr_encrypted_db_key_base_truncated,
|
||||||
|
algorithm: 'aes-256-cbc'
|
||||||
|
end
|
||||||
|
|
||||||
|
class Service < ActiveRecord::Base
|
||||||
|
include EachBatch
|
||||||
|
|
||||||
|
self.table_name = 'services'
|
||||||
|
self.inheritance_column = :_type_disabled # Disable STI, otherwise KubernetesModel will be looked up
|
||||||
|
|
||||||
|
belongs_to :project, class_name: 'MigrateK8sServiceIntegration::Project', foreign_key: :project_id
|
||||||
|
|
||||||
|
scope :kubernetes_service_templates, -> do
|
||||||
|
where(category: 'deployment', type: 'KubernetesService', template: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def api_url
|
||||||
|
parsed_properties['api_url'].presence
|
||||||
|
end
|
||||||
|
|
||||||
|
def ca_pem
|
||||||
|
parsed_properties['ca_pem']
|
||||||
|
end
|
||||||
|
|
||||||
|
def namespace
|
||||||
|
parsed_properties['namespace'].presence
|
||||||
|
end
|
||||||
|
|
||||||
|
def token
|
||||||
|
parsed_properties['token'].presence
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def parsed_properties
|
||||||
|
@parsed_properties ||= JSON.parse(self.properties)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def up
|
||||||
|
MigrateK8sServiceIntegration::Service.kubernetes_service_templates.find_each do |service|
|
||||||
|
next unless service.api_url && service.token
|
||||||
|
|
||||||
|
MigrateK8sServiceIntegration::Cluster.create!(
|
||||||
|
enabled: service.active,
|
||||||
|
managed: false,
|
||||||
|
name: 'KubernetesService',
|
||||||
|
cluster_type: 'instance_type',
|
||||||
|
provider_type: 'user',
|
||||||
|
platform_type: 'kubernetes',
|
||||||
|
platform_kubernetes_attributes: {
|
||||||
|
api_url: service.api_url,
|
||||||
|
ca_cert: service.ca_pem,
|
||||||
|
namespace: service.namespace,
|
||||||
|
token: service.token
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# It is not possible to tell which instance-level clusters were created by
|
||||||
|
# this migration. The original data is intentionally left intact.
|
||||||
|
end
|
||||||
|
end
|
124
spec/migrations/migrate_k8s_service_integration_spec.rb
Normal file
124
spec/migrations/migrate_k8s_service_integration_spec.rb
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require Rails.root.join('db', 'post_migrate', '20190517153211_migrate_k8s_service_integration.rb')
|
||||||
|
|
||||||
|
describe MigrateK8sServiceIntegration, :migration do
|
||||||
|
context 'template service' do
|
||||||
|
context 'with namespace' do
|
||||||
|
let!(:service) do
|
||||||
|
MigrateK8sServiceIntegration::Service.create!(
|
||||||
|
active: true,
|
||||||
|
template: true,
|
||||||
|
category: 'deployment',
|
||||||
|
type: 'KubernetesService',
|
||||||
|
properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
|
||||||
|
let(:platform) { cluster.platform_kubernetes }
|
||||||
|
|
||||||
|
it 'migrates the KubernetesService template to Platform::Kubernetes' do
|
||||||
|
expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
|
||||||
|
|
||||||
|
expect(cluster).to be_enabled
|
||||||
|
expect(cluster).to be_user
|
||||||
|
expect(cluster).not_to be_managed
|
||||||
|
expect(cluster.environment_scope).to eq('*')
|
||||||
|
expect(platform.api_url).to eq('https://sample.kubernetes.com')
|
||||||
|
expect(platform.ca_cert).to eq('ca_pem-sample')
|
||||||
|
expect(platform.namespace).to eq('prod')
|
||||||
|
expect(platform.token).to eq('token-sample')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without namespace' do
|
||||||
|
let!(:service) do
|
||||||
|
MigrateK8sServiceIntegration::Service.create!(
|
||||||
|
active: true,
|
||||||
|
template: true,
|
||||||
|
category: 'deployment',
|
||||||
|
type: 'KubernetesService',
|
||||||
|
properties: "{\"namespace\":\"\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
|
||||||
|
let(:platform) { cluster.platform_kubernetes }
|
||||||
|
|
||||||
|
it 'migrates the KubernetesService template to Platform::Kubernetes' do
|
||||||
|
expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
|
||||||
|
|
||||||
|
expect(cluster).to be_enabled
|
||||||
|
expect(cluster).to be_user
|
||||||
|
expect(cluster).not_to be_managed
|
||||||
|
expect(cluster.environment_scope).to eq('*')
|
||||||
|
expect(platform.api_url).to eq('https://sample.kubernetes.com')
|
||||||
|
expect(platform.ca_cert).to eq('ca_pem-sample')
|
||||||
|
expect(platform.namespace).to be_nil
|
||||||
|
expect(platform.token).to eq('token-sample')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with nullified parameters' do
|
||||||
|
let!(:service) do
|
||||||
|
MigrateK8sServiceIntegration::Service.create!(
|
||||||
|
active: true,
|
||||||
|
template: true,
|
||||||
|
category: 'deployment',
|
||||||
|
type: 'KubernetesService',
|
||||||
|
properties: "{}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not migrate the KubernetesService' do
|
||||||
|
expect { migrate! }.not_to change { MigrateK8sServiceIntegration::Cluster.count }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when disabled' do
|
||||||
|
let!(:service) do
|
||||||
|
MigrateK8sServiceIntegration::Service.create!(
|
||||||
|
active: false,
|
||||||
|
template: true,
|
||||||
|
category: 'deployment',
|
||||||
|
type: 'KubernetesService',
|
||||||
|
properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
|
||||||
|
let(:platform) { cluster.platform_kubernetes }
|
||||||
|
|
||||||
|
it 'migrates the KubernetesService template to Platform::Kubernetes' do
|
||||||
|
expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
|
||||||
|
|
||||||
|
expect(cluster).not_to be_enabled
|
||||||
|
expect(cluster).to be_user
|
||||||
|
expect(cluster).not_to be_managed
|
||||||
|
expect(cluster.environment_scope).to eq('*')
|
||||||
|
expect(platform.api_url).to eq('https://sample.kubernetes.com')
|
||||||
|
expect(platform.ca_cert).to eq('ca_pem-sample')
|
||||||
|
expect(platform.namespace).to eq('prod')
|
||||||
|
expect(platform.token).to eq('token-sample')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'non-template service' do
|
||||||
|
let!(:service) do
|
||||||
|
MigrateK8sServiceIntegration::Service.create!(
|
||||||
|
active: true,
|
||||||
|
template: false,
|
||||||
|
category: 'deployment',
|
||||||
|
type: 'KubernetesService',
|
||||||
|
properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not migrate the KubernetesService' do
|
||||||
|
expect { migrate! }.not_to change { MigrateK8sServiceIntegration::Cluster.count }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue