diff options
-rw-r--r-- | db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb | 52 | ||||
-rw-r--r-- | spec/migrations/migrate_kubernetes_service_to_new_clusters_architectures_spec.rb | 50 |
2 files changed, 69 insertions, 33 deletions
diff --git a/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb b/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb index 5dee8cb8c5f..46b40ea7a44 100644 --- a/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb +++ b/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb @@ -51,36 +51,41 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati belongs_to :project, class_name: 'Project' - # 10.1 ~ 10.2 - # When users created a cluster, KubernetesService was automatically configured - # by Platforms::Kubernetes parameters. - # Because Platforms::Kubernetes delegated some logic to KubernetesService. - # - # 10.3 - # When users create a cluster, KubernetesService is no longer synchronized. - # Because we copied delegated logic in Platforms::Kubernetes. - # - # NOTE: - # - "unmanaged" means "unmanaged by Platforms::Kubernetes(New archetecture)" - # - We only want to migrate records which are not synchronized with Platforms::Kubernetes. - scope :unmanaged_kubernetes_service, -> do + scope :kubernetes_service, -> do where("services.category = 'deployment'") .where("services.type = 'KubernetesService'") .where("services.template = FALSE") - .where("NOT EXISTS (?)", - PlatformsKubernetes - .joins('INNER JOIN projects ON projects.id = services.project_id') - .joins('INNER JOIN cluster_projects ON cluster_projects.project_id = projects.id') - .where('cluster_projects.cluster_id = cluster_platforms_kubernetes.cluster_id') - .where("services.properties LIKE CONCAT('%', cluster_platforms_kubernetes.api_url, '%')") - .select('1') ) .order('services.project_id') end end + def find_dedicated_environement_scope(project) + environment_scopes = project.clusters.map(&:environment_scope) + + return '*' if environment_scopes.exclude?('*') # KubernetesService should be added as a default cluster (environment_scope: '*') at first place + return 'migrated/*' if environment_scopes.exclude?('migrated/*') # If it's conflicted, the KubernetesService added as a migrated cluster + + unique_iid = 0 + + # If it's still conflicted, finding an unique environment scope incrementaly + while true + candidate = "migrated#{unique_iid}/*" + return candidate if environment_scopes.exclude?(candidate) + unique_iid += 1 + end + end + + # KubernetesService might be already managed by clusters + def managed_by_clusters?(kubernetes_service) + kubernetes_service.project.clusters + .joins('INNER JOIN cluster_platforms_kubernetes ON clusters.id = cluster_platforms_kubernetes.cluster_id') + .where('cluster_platforms_kubernetes.api_url = ?', kubernetes_service.api_url) + .exists? + end + def up - Service.unmanaged_kubernetes_service - .find_each(batch_size: 1) do |kubernetes_service| + Service.kubernetes_service.find_each(batch_size: 1) do |kubernetes_service| + unless managed_by_clusters?(kubernetes_service) Cluster.create( enabled: kubernetes_service.active, user_id: nil, # KubernetesService doesn't have @@ -88,7 +93,7 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati provider_type: Cluster.provider_types[:user], platform_type: Cluster.platform_types[:kubernetes], projects: [kubernetes_service.project], - environment_scope: '*', # KubernetesService is considered as a default cluster + environment_scope: find_dedicated_environement_scope(kubernetes_service.project), platform_kubernetes_attributes: { api_url: kubernetes_service.api_url, ca_cert: kubernetes_service.ca_pem, @@ -98,6 +103,7 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati encrypted_password_iv: nil, # KubernetesService doesn't have token: kubernetes_service.token # encrypted_token and encrypted_token_iv } ) + end # Disable the KubernetesService. Platforms::Kubernetes will be used from next time. kubernetes_service.active = false diff --git a/spec/migrations/migrate_kubernetes_service_to_new_clusters_architectures_spec.rb b/spec/migrations/migrate_kubernetes_service_to_new_clusters_architectures_spec.rb index bf41b2df359..5ce1c43d92a 100644 --- a/spec/migrations/migrate_kubernetes_service_to_new_clusters_architectures_spec.rb +++ b/spec/migrations/migrate_kubernetes_service_to_new_clusters_architectures_spec.rb @@ -91,7 +91,7 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do end end - context 'when synced KubernetesService exists' do + context 'when managed KubernetesService exists' do let(:project) { create(:project) } let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } let!(:platform_kubernetes) { cluster.platform_kubernetes } @@ -105,15 +105,16 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ca_pem: platform_kubernetes.ca_cert) end - it 'does not migrate the KubernetesService' do # Because the corresponding Platform::Kubernetes already exists + it 'does not migrate the KubernetesService and disables the kubernetes_service' do # Because the corresponding Platform::Kubernetes already exists expect{ migrate! }.not_to change { Clusters::Cluster.count } - expect(kubernetes_service).to be_active - expect(kubernetes_service.properties['migrated']).to be_falsy + kubernetes_service.reload + expect(kubernetes_service).not_to be_active + expect(kubernetes_service.properties['migrated']).to be_truthy end end - context 'when production cluster has already been existsed' do + context 'when production cluster has already been existed' do # i.e. There are no environment_scope conflicts let(:project) { create(:project) } let!(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: 'production/*', projects: [project]) } let!(:kubernetes_service) { create(:kubernetes_service, api_url: 'https://debug.kube.com', active: true, project: project) } @@ -123,6 +124,7 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do kubernetes_service.reload project.clusters.last.tap do |cluster| + expect(cluster.environment_scope).to eq('*') expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url) expect(cluster.platform_kubernetes.ca_pem).to eq(kubernetes_service.ca_pem) expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token) @@ -132,16 +134,44 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do end end - context 'when default cluster has already been existsed' do + context 'when default cluster has already been existed' do let(:project) { create(:project) } let!(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) } let!(:kubernetes_service) { create(:kubernetes_service, api_url: 'https://debug.kube.com', active: true, project: project) } - it 'does not migrate the KubernetesService' do # Because environment_scope is duplicated - expect{ migrate! }.not_to change { Clusters::Cluster.count } + it 'migrates the KubernetesService to Platform::Kubernetes with dedicated environment_scope' do # Because environment_scope is duplicated + expect{ migrate! }.to change { Clusters::Cluster.count }.by(1) + + kubernetes_service.reload + project.clusters.last.tap do |cluster| + expect(cluster.environment_scope).to eq('migrated/*') + expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url) + expect(cluster.platform_kubernetes.ca_pem).to eq(kubernetes_service.ca_pem) + expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token) + expect(kubernetes_service).not_to be_active + expect(kubernetes_service.properties['migrated']).to be_truthy + end + end + end - expect(kubernetes_service).to be_active - expect(kubernetes_service.properties['migrated']).to be_falsy + context 'when default cluster and migrated cluster has already been existed' do + let(:project) { create(:project) } + let!(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) } + let!(:migrated_cluster) { create(:cluster, :provided_by_gcp, environment_scope: 'migrated/*', projects: [project]) } + let!(:kubernetes_service) { create(:kubernetes_service, api_url: 'https://debug.kube.com', active: true, project: project) } + + it 'migrates the KubernetesService to Platform::Kubernetes with dedicated environment_scope' do # Because environment_scope is duplicated + expect{ migrate! }.to change { Clusters::Cluster.count }.by(1) + + kubernetes_service.reload + project.clusters.last.tap do |cluster| + expect(cluster.environment_scope).to eq('migrated0/*') + expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url) + expect(cluster.platform_kubernetes.ca_pem).to eq(kubernetes_service.ca_pem) + expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token) + expect(kubernetes_service).not_to be_active + expect(kubernetes_service.properties['migrated']).to be_truthy + end end end |