summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/clusters/cluster.rb2
-rw-r--r--changelogs/unreleased/migrate_k8s_service_integration.yml5
-rw-r--r--db/post_migrate/20190517153211_migrate_k8s_service_integration.rb104
-rw-r--r--spec/migrations/migrate_k8s_service_integration_spec.rb161
-rw-r--r--spec/models/clusters/cluster_spec.rb34
5 files changed, 300 insertions, 6 deletions
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 0206ce81c5f..8c044c86c47 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -226,7 +226,7 @@ module Clusters
end
def allow_user_defined_namespace?
- project_type?
+ project_type? || !managed?
end
def kube_ingress_domain
diff --git a/changelogs/unreleased/migrate_k8s_service_integration.yml b/changelogs/unreleased/migrate_k8s_service_integration.yml
new file mode 100644
index 00000000000..57f03e6bdab
--- /dev/null
+++ b/changelogs/unreleased/migrate_k8s_service_integration.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Kubernetes service integration templates to clusters
+merge_request: 28534
+author:
+type: added
diff --git a/db/post_migrate/20190517153211_migrate_k8s_service_integration.rb b/db/post_migrate/20190517153211_migrate_k8s_service_integration.rb
new file mode 100644
index 00000000000..4bd04edb239
--- /dev/null
+++ b/db/post_migrate/20190517153211_migrate_k8s_service_integration.rb
@@ -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
diff --git a/spec/migrations/migrate_k8s_service_integration_spec.rb b/spec/migrations/migrate_k8s_service_integration_spec.rb
new file mode 100644
index 00000000000..4dd0c09632a
--- /dev/null
+++ b/spec/migrations/migrate_k8s_service_integration_spec.rb
@@ -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
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index c302b7a15f4..52661178d76 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -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 }
+ end
- it { is_expected.to be_falsey }
+ 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 }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance, managed: false) }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_truthy }
+ end
end
end