diff options
author | Thong Kuah <tkuah@gitlab.com> | 2018-11-15 22:17:41 +1300 |
---|---|---|
committer | Thong Kuah <tkuah@gitlab.com> | 2018-12-05 10:16:44 +1300 |
commit | d54791e0942ae774876db22675cde1b54f35109d (patch) | |
tree | 0921f14ff534d058b321d008c2ff570d043d4cfc /app | |
parent | 8419b7dd2b85fbe9216a31ce84d5ecb234a8b90a (diff) | |
download | gitlab-ce-d54791e0942ae774876db22675cde1b54f35109d.tar.gz |
Create k8s namespace for project in group clusters
AFAIK the only relevant place is Projects::CreateService, this gets
called when user creates a new project, forks a new project and does
those things via the api.
Also create k8s namespace for new group hierarchy
when transferring project between groups
Uses new Refresh service to create k8s namespaces
- Ensure we use Cluster#cluster_project
If a project has multiple clusters (EE), using Project#cluster_project
is not guaranteed to return the cluster_project for this cluster. So
switch to using Cluster#cluster_project - at this stage a cluster can
only have 1 cluster_project.
Also, remove rescue so that sidekiq can retry
Diffstat (limited to 'app')
-rw-r--r-- | app/models/clusters/cluster.rb | 22 | ||||
-rw-r--r-- | app/models/project.rb | 6 | ||||
-rw-r--r-- | app/services/clusters/refresh_service.rb | 33 | ||||
-rw-r--r-- | app/services/projects/create_service.rb | 6 | ||||
-rw-r--r-- | app/services/projects/transfer_service.rb | 5 | ||||
-rw-r--r-- | app/workers/all_queues.yml | 1 | ||||
-rw-r--r-- | app/workers/cluster_platform_configure_worker.rb | 12 | ||||
-rw-r--r-- | app/workers/cluster_project_configure_worker.rb | 12 |
8 files changed, 81 insertions, 16 deletions
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 54314f69c3d..73cae8d3b25 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -87,6 +87,12 @@ module Clusters scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) } + scope :missing_kubernetes_namespace, -> (kubernetes_namespaces) do + subquery = kubernetes_namespaces.select('1').where('clusters_kubernetes_namespaces.cluster_id = clusters.id') + + where('NOT EXISTS (?)', subquery) + end + # Returns an ordered list of group clusters order from clusters of closest # group up to furthest ancestor group def self.ordered_group_clusters_for_project(project_id) @@ -161,11 +167,17 @@ module Clusters platform_kubernetes.kubeclient if kubernetes? end - def find_or_initialize_kubernetes_namespace(cluster_project) - kubernetes_namespaces.find_or_initialize_by( - project: cluster_project.project, - cluster_project: cluster_project - ) + def find_or_initialize_kubernetes_namespace_for_project(project) + if project_type? + kubernetes_namespaces.find_or_initialize_by( + project: project, + cluster_project: cluster_project + ) + else + kubernetes_namespaces.find_or_initialize_by( + project: project + ) + end end def allow_user_defined_namespace? diff --git a/app/models/project.rb b/app/models/project.rb index 8f41629e5e5..a3580961d42 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -383,6 +383,12 @@ class Project < ActiveRecord::Base .where(project_ci_cd_settings: { group_runners_enabled: true }) end + scope :missing_kubernetes_namespace, -> (kubernetes_namespaces) do + subquery = kubernetes_namespaces.select('1').where('clusters_kubernetes_namespaces.project_id = projects.id') + + where('NOT EXISTS (?)', subquery) + end + enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 } chronic_duration_attr :build_timeout_human_readable, :build_timeout, default: 3600 diff --git a/app/services/clusters/refresh_service.rb b/app/services/clusters/refresh_service.rb new file mode 100644 index 00000000000..51859a002c0 --- /dev/null +++ b/app/services/clusters/refresh_service.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Clusters + class RefreshService + def create_or_update_namespaces_for_cluster(cluster) + cluster_namespaces = cluster.kubernetes_namespaces + + # Create all namespaces that are missing for each project + cluster.all_projects.missing_kubernetes_namespace(cluster_namespaces).each do |project| + kubernetes_namespace = cluster.find_or_initialize_kubernetes_namespace_for_project(project) + + ::Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new( + cluster: cluster, + kubernetes_namespace: kubernetes_namespace + ).execute + end + end + + def create_or_update_namespaces_for_project(project) + project_namespaces = project.kubernetes_namespaces + + # Create all namespaces that are missing for each cluster + project.all_clusters.missing_kubernetes_namespace(project_namespaces).each do |cluster| + kubernetes_namespace = cluster.find_or_initialize_kubernetes_namespace_for_project(project) + + ::Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new( + cluster: cluster, + kubernetes_namespace: kubernetes_namespace + ).execute + end + end + end +end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 9e77a3237e3..d03137b63b2 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -96,6 +96,8 @@ module Projects current_user.invalidate_personal_projects_count create_readme if @initialize_with_readme + + configure_group_clusters_for_project end # Refresh the current user's authorizations inline (so they can access the @@ -121,6 +123,10 @@ module Projects Files::CreateService.new(@project, current_user, commit_attrs).execute end + def configure_group_clusters_for_project + ClusterProjectConfigureWorker.perform_async(@project.id) + end + def skip_wiki? !@project.feature_available?(:wiki, current_user) || @skip_wiki end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 9d40ab166ff..9db3fd9cf17 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -54,6 +54,7 @@ module Projects end attempt_transfer_transaction + configure_group_clusters_for_project end # rubocop: enable CodeReuse/ActiveRecord @@ -162,5 +163,9 @@ module Projects @new_namespace.full_path ) end + + def configure_group_clusters_for_project + ClusterProjectConfigureWorker.perform_async(project.id) + end end end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index c0b410472eb..e51da79c6b5 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -29,6 +29,7 @@ - gcp_cluster:wait_for_cluster_creation - gcp_cluster:cluster_wait_for_ingress_ip_address - gcp_cluster:cluster_platform_configure +- gcp_cluster:cluster_project_configure - github_import_advance_stage - github_importer:github_import_import_diff_note diff --git a/app/workers/cluster_platform_configure_worker.rb b/app/workers/cluster_platform_configure_worker.rb index 8f3689f0166..7f14f8efa2f 100644 --- a/app/workers/cluster_platform_configure_worker.rb +++ b/app/workers/cluster_platform_configure_worker.rb @@ -6,17 +6,7 @@ class ClusterPlatformConfigureWorker def perform(cluster_id) Clusters::Cluster.find_by_id(cluster_id).try do |cluster| - next unless cluster.cluster_project - - kubernetes_namespace = cluster.find_or_initialize_kubernetes_namespace(cluster.cluster_project) - - Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new( - cluster: cluster, - kubernetes_namespace: kubernetes_namespace - ).execute + Clusters::RefreshService.new.create_or_update_namespaces_for_cluster(cluster) end - - rescue ::Kubeclient::HttpError => err - Rails.logger.error "Failed to create/update Kubernetes namespace for cluster_id: #{cluster_id} with error: #{err.message}" end end diff --git a/app/workers/cluster_project_configure_worker.rb b/app/workers/cluster_project_configure_worker.rb new file mode 100644 index 00000000000..1271b26e945 --- /dev/null +++ b/app/workers/cluster_project_configure_worker.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class ClusterProjectConfigureWorker + include ApplicationWorker + include ClusterQueue + + def perform(project_id) + project = Project.find(project_id) + + ::Clusters::RefreshService.new.create_or_update_namespaces_for_project(project) + end +end |