Merge branch 'migrate_k8s_service_integration' into 'master'
Migrate Kubernetes service integration templates to clusters See merge request gitlab-org/gitlab-ce!28534
This commit is contained in:
commit
04307096bc
5 changed files with 300 additions and 6 deletions
|
@ -226,7 +226,7 @@ module Clusters
|
|||
end
|
||||
|
||||
def allow_user_defined_namespace?
|
||||
project_type?
|
||||
project_type? || !managed?
|
||||
end
|
||||
|
||||
def kube_ingress_domain
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Migrate Kubernetes service integration templates to clusters
|
||||
merge_request: 28534
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,104 @@
|
|||
# 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
|
||||
has_instance_cluster = Cluster.instance_type.where(enabled: true).exists?
|
||||
|
||||
MigrateK8sServiceIntegration::Service.kubernetes_service_templates.find_each do |service|
|
||||
next unless service.api_url && service.token
|
||||
|
||||
MigrateK8sServiceIntegration::Cluster.create!(
|
||||
enabled: !has_instance_cluster && 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
|
161
spec/migrations/migrate_k8s_service_integration_spec.rb
Normal file
161
spec/migrations/migrate_k8s_service_integration_spec.rb
Normal file
|
@ -0,0 +1,161 @@
|
|||
# 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
|
||||
|
||||
context 'when an instance cluster already exists' 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!(:existing_cluster) do
|
||||
MigrateK8sServiceIntegration::Cluster.create!(
|
||||
name: 'test-cluster',
|
||||
cluster_type: :instance_type,
|
||||
managed: true,
|
||||
provider_type: :user,
|
||||
platform_type: :kubernetes
|
||||
)
|
||||
end
|
||||
let(:new_cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
|
||||
let(:platform) { new_cluster.platform_kubernetes }
|
||||
|
||||
it 'migrates the KubernetesService template to disabled Platform::Kubernetes' do
|
||||
expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
|
||||
|
||||
expect(new_cluster).not_to be_enabled
|
||||
expect(new_cluster).to be_user
|
||||
expect(new_cluster).not_to be_managed
|
||||
expect(new_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
|
|
@ -514,19 +514,43 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
|
|||
subject { cluster.allow_user_defined_namespace? }
|
||||
|
||||
context 'project type cluster' do
|
||||
it { is_expected.to be_truthy }
|
||||
context 'gitlab managed' do
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'not managed' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, managed: false) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
context 'group type cluster' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
|
||||
context 'gitlab managed' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
context 'not managed' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :group, managed: false) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
context 'instance type cluster' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
|
||||
context 'gitlab managed' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
context 'not managed' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :instance, managed: false) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue