2019-02-15 15:39:39 +05:30
|
|
|
class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migration[4.2]
|
2018-03-17 18:26:18 +05:30
|
|
|
include Gitlab::Database::MigrationHelpers
|
|
|
|
|
|
|
|
DOWNTIME = false
|
|
|
|
DEFAULT_KUBERNETES_SERVICE_CLUSTER_NAME = 'KubernetesService'.freeze
|
|
|
|
|
|
|
|
disable_ddl_transaction!
|
|
|
|
|
|
|
|
class Project < ActiveRecord::Base
|
|
|
|
self.table_name = 'projects'
|
|
|
|
|
|
|
|
has_many :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::ClustersProject'
|
|
|
|
has_many :clusters, through: :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Cluster'
|
|
|
|
has_many :services, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Service'
|
|
|
|
has_one :kubernetes_service, -> { where(category: 'deployment', type: 'KubernetesService') }, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Service', inverse_of: :project, foreign_key: :project_id
|
|
|
|
end
|
|
|
|
|
|
|
|
class Cluster < ActiveRecord::Base
|
|
|
|
self.table_name = 'clusters'
|
|
|
|
|
|
|
|
has_many :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::ClustersProject'
|
|
|
|
has_many :projects, through: :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Project'
|
|
|
|
has_one :platform_kubernetes, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::PlatformsKubernetes'
|
|
|
|
|
|
|
|
accepts_nested_attributes_for :platform_kubernetes
|
|
|
|
|
|
|
|
enum platform_type: {
|
|
|
|
kubernetes: 1
|
|
|
|
}
|
|
|
|
|
|
|
|
enum provider_type: {
|
|
|
|
user: 0,
|
|
|
|
gcp: 1
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
class ClustersProject < ActiveRecord::Base
|
|
|
|
self.table_name = 'cluster_projects'
|
|
|
|
|
|
|
|
belongs_to :cluster, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Cluster'
|
|
|
|
belongs_to :project, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Project'
|
|
|
|
end
|
|
|
|
|
|
|
|
class PlatformsKubernetes < ActiveRecord::Base
|
|
|
|
self.table_name = 'cluster_platforms_kubernetes'
|
|
|
|
|
|
|
|
belongs_to :cluster, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Cluster'
|
|
|
|
|
|
|
|
attr_encrypted :token,
|
|
|
|
mode: :per_attribute_iv,
|
2018-11-08 19:23:39 +05:30
|
|
|
key: Settings.attr_encrypted_db_key_base_truncated,
|
2018-03-17 18:26:18 +05:30
|
|
|
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: 'MigrateKubernetesServiceToNewClustersArchitectures::Project', foreign_key: :project_id
|
|
|
|
|
|
|
|
scope :unmanaged_kubernetes_service, -> do
|
|
|
|
joins('LEFT JOIN projects ON projects.id = services.project_id')
|
|
|
|
.joins('LEFT JOIN cluster_projects ON cluster_projects.project_id = projects.id')
|
|
|
|
.joins('LEFT JOIN cluster_platforms_kubernetes ON cluster_platforms_kubernetes.cluster_id = cluster_projects.cluster_id')
|
|
|
|
.where(category: 'deployment', type: 'KubernetesService', template: false)
|
|
|
|
.where("services.properties LIKE '%api_url%'")
|
|
|
|
.where("(services.properties NOT LIKE CONCAT('%', cluster_platforms_kubernetes.api_url, '%')) OR cluster_platforms_kubernetes.api_url IS NULL")
|
|
|
|
.group(:id)
|
|
|
|
.order(id: :asc)
|
|
|
|
end
|
|
|
|
|
|
|
|
scope :kubernetes_service_without_template, -> do
|
|
|
|
where(category: 'deployment', type: 'KubernetesService', template: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
def api_url
|
|
|
|
parsed_properties['api_url']
|
|
|
|
end
|
|
|
|
|
|
|
|
def ca_pem
|
|
|
|
parsed_properties['ca_pem']
|
|
|
|
end
|
|
|
|
|
|
|
|
def namespace
|
|
|
|
parsed_properties['namespace']
|
|
|
|
end
|
|
|
|
|
|
|
|
def token
|
|
|
|
parsed_properties['token']
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def parsed_properties
|
|
|
|
@parsed_properties ||= JSON.parse(self.properties)
|
|
|
|
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
|
|
|
|
loop do
|
|
|
|
candidate = "migrated#{unique_iid}/*"
|
|
|
|
return candidate if environment_scopes.exclude?(candidate)
|
|
|
|
|
|
|
|
unique_iid += 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def up
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
MigrateKubernetesServiceToNewClustersArchitectures::Service
|
|
|
|
.unmanaged_kubernetes_service.find_each(batch_size: 1) do |kubernetes_service|
|
|
|
|
MigrateKubernetesServiceToNewClustersArchitectures::Cluster.create(
|
|
|
|
enabled: kubernetes_service.active,
|
|
|
|
user_id: nil, # KubernetesService doesn't have
|
|
|
|
name: DEFAULT_KUBERNETES_SERVICE_CLUSTER_NAME,
|
|
|
|
provider_type: MigrateKubernetesServiceToNewClustersArchitectures::Cluster.provider_types[:user],
|
|
|
|
platform_type: MigrateKubernetesServiceToNewClustersArchitectures::Cluster.platform_types[:kubernetes],
|
|
|
|
projects: [kubernetes_service.project],
|
|
|
|
environment_scope: find_dedicated_environement_scope(kubernetes_service.project),
|
|
|
|
platform_kubernetes_attributes: {
|
|
|
|
api_url: kubernetes_service.api_url,
|
|
|
|
ca_cert: kubernetes_service.ca_pem,
|
|
|
|
namespace: kubernetes_service.namespace,
|
|
|
|
username: nil, # KubernetesService doesn't have
|
|
|
|
encrypted_password: nil, # KubernetesService doesn't have
|
|
|
|
encrypted_password_iv: nil, # KubernetesService doesn't have
|
|
|
|
token: kubernetes_service.token # encrypted_token and encrypted_token_iv
|
|
|
|
} )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
MigrateKubernetesServiceToNewClustersArchitectures::Service
|
|
|
|
.kubernetes_service_without_template.each_batch(of: 100) do |kubernetes_service|
|
|
|
|
kubernetes_service.update_all(active: false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def down
|
|
|
|
# noop
|
|
|
|
end
|
|
|
|
end
|