diff options
author | Shinya Maeda <shinya@gitlab.com> | 2017-11-23 17:28:08 +0300 |
---|---|---|
committer | Shinya Maeda <shinya@gitlab.com> | 2017-11-23 19:56:35 +0300 |
commit | 7caa62e050049f774b3e282376b00cd438994e58 (patch) | |
tree | cf6d71d18ebcc21d4caa5668d09624dbf5ab204a | |
parent | 038f5a412d0085f2d9610c77cea37cec75572b27 (diff) |
Follow up cluster_id recovery for Platform::Kubernetes
-rw-r--r-- | db/migrate/20171123104051_fix_cluster_platforms_kubernetes_association_mismatch.rb | 55 | ||||
-rw-r--r-- | spec/migrations/fix_cluster_platforms_kubernetes_association_mismatch_spec.rb | 98 |
2 files changed, 153 insertions, 0 deletions
diff --git a/db/migrate/20171123104051_fix_cluster_platforms_kubernetes_association_mismatch.rb b/db/migrate/20171123104051_fix_cluster_platforms_kubernetes_association_mismatch.rb new file mode 100644 index 00000000000..01bafaa4539 --- /dev/null +++ b/db/migrate/20171123104051_fix_cluster_platforms_kubernetes_association_mismatch.rb @@ -0,0 +1,55 @@ +class FixClusterPlatformsKubernetesAssociationMismatch < ActiveRecord::Migration + DOWNTIME = false + + class GcpCluster < ActiveRecord::Base + self.table_name = 'gcp_clusters' + + belongs_to :project, class_name: 'Project' + end + + class Cluster < ActiveRecord::Base + self.table_name = 'clusters' + + has_one :provider_gcp, class_name: 'ProvidersGcp' + has_one :platform_kubernetes, class_name: 'PlatformsKubernetes' + end + + class ProvidersGcp < ActiveRecord::Base + self.table_name = 'cluster_providers_gcp' + end + + class PlatformsKubernetes < ActiveRecord::Base + include EachBatch + + self.table_name = 'cluster_platforms_kubernetes' + end + + def up + PlatformsKubernetes.all.find_each(batch_size: 1) do |platforms_kubernetes| + # This is the culprit. See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15566 + gcp_cluster = GcpCluster.find_by_id(platforms_kubernetes.cluster_id) + + provider_gcp = ProvidersGcp.join(:clusters) + .where(gcp_project_id: gcp_cluster.gcp_project_id, + zone: gcp_cluster.gcp_cluster_zone, + num_nodes: gcp_cluster.gcp_cluster_size, + machine_type: gcp_cluster.gcp_machine_type, + endpoint: gcp_cluster.endpoint, + "clusters.name": gcp_cluster.gcp_cluster_name) + + next unless provider_gcp.count == 1 + + correct_cluster_id = provider_gcp.first.cluster_id + + unless correct_cluster_id == platforms_kubernetes.cluster_id + say 'Association mismatch detected' + + platforms_kubernetes.update(cluster_id: correct_cluster_id) + end + end + end + + def down + # noop + end +end diff --git a/spec/migrations/fix_cluster_platforms_kubernetes_association_mismatch_spec.rb b/spec/migrations/fix_cluster_platforms_kubernetes_association_mismatch_spec.rb new file mode 100644 index 00000000000..15a9a8e2591 --- /dev/null +++ b/spec/migrations/fix_cluster_platforms_kubernetes_association_mismatch_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20171123104051_fix_cluster_platforms_kubernetes_association_mismatch.rb') + +## +# See more details at https://gitlab.com/gitlab-org/gitlab-ce/issues/40478 +# +describe FixClusterPlatformsKubernetesAssociationMismatch, :migration do + let(:project) { create(:project) } + let(:user) { create(:user) } + + shared_examples 'expected behavior' do + it 'has correct association' do + migrate! + + Cluster.all.each do |cluster| + expect(cluster.platform_kubernetes.api_url).to eq(api_url(cluster.provider_gcp.endpoint)) + end + end + end + + context 'when user did not create a cluster before post migration has done' do + before do + prepare + end + + it_behaves_like 'expected behavior' + end + + context 'when user created a cluster before post migration has done' do + before do + prepare + culprit + end + + it_behaves_like 'expected behavior' + end + + def prepare + create_test_data + migrate_gcp_clusters_to_new_clusters_architectures! + end + + def migrate_gcp_clusters_to_new_clusters_architectures! + ActiveRecord::Migrator.up(migrations_paths) do |migration| + migration.name == 'MigrateGcpClustersToNewClustersArchitectures' + end + end + + def create_test_data + (1..5).each do |i| + project = create(:project) + user = create(:user) + service = create(:kubernetes_service, project: project) + + # Params + project_id = create(:project).id + user_id = create(:user).id + service_id = service.id + status = 3 # created + gcp_cluster_size = 1 + created_at = "'2017-10-17 20:24:02'" + updated_at = "'2017-10-17 20:28:44'" + enabled = true + status_reason = "'NULL'" + project_namespace = "'sample-app-#{i}'" + endpoint = "'111.111.111.#{i}'" + ca_cert = "'ca_cert-#{i}'" + encrypted_kubernetes_token = "'NULL'" + encrypted_kubernetes_token_iv = "'NULL'" + username = "'username-#{i}'" + encrypted_password = "'encrypted_password-#{i}'" + encrypted_password_iv = "'encrypted_password_iv-#{i}'" + gcp_project_id = "'gcp_project_id-#{i}'" + gcp_cluster_zone = "'gcp_cluster_zone-#{i}'" + gcp_cluster_name = "'gcp_cluster_name-#{i}'" + gcp_machine_type = "'gcp_machine_type-#{i}'" + gcp_operation_id = "'gcp_operation_id-#{i}'" + encrypted_gcp_token = "'encrypted_gcp_token-#{i}'" + encrypted_gcp_token_iv = "'encrypted_gcp_token_iv-#{i}'" + + ActiveRecord::Base.connection.execute <<-SQL + INSERT INTO gcp_clusters (project_id, user_id, service_id, status, gcp_cluster_size, created_at, updated_at, enabled, status_reason, project_namespace, endpoint, ca_cert, encrypted_kubernetes_token, encrypted_kubernetes_token_iv, username, encrypted_password, encrypted_password_iv, gcp_project_id, gcp_cluster_zone, gcp_cluster_name, gcp_machine_type, gcp_operation_id, encrypted_gcp_token, encrypted_gcp_token_iv) + VALUES (#{project_id}, #{user_id}, #{service_id}, #{status}, #{gcp_cluster_size}, #{created_at}, #{updated_at}, #{enabled}, #{status_reason}, #{project_namespace}, #{endpoint}, #{ca_cert}, #{encrypted_kubernetes_token}, #{encrypted_kubernetes_token_iv}, #{username}, #{encrypted_password}, #{encrypted_password_iv}, #{gcp_project_id}, #{gcp_cluster_zone}, #{gcp_cluster_name}, #{gcp_machine_type}, #{gcp_operation_id}, #{encrypted_gcp_token}, #{encrypted_gcp_token_iv}); + SQL + end + end + + def culprit + (1..5).each do |i| + cluster = Cluster.find_by_id(i) + cluster.platform_kubernetes.update!(cluster_id: (i % 5) + 1) + end + end + + def api_url(endpoint) + endpoint ? 'https://' + endpoint : nil + end +end |