summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-12-05 15:46:41 +0000
committerKamil Trzciński <ayufan@ayufan.eu>2018-12-05 15:46:41 +0000
commit13b1508c3ed9887d9fcffdad66cbcf90b14eabd9 (patch)
treefb5c76469015186badbbb1af0c6375c4e4de2df4 /app
parent2ea6900882edb151bfb2ee4ef9733a9fc7b521f6 (diff)
parente3188eb13e3145e9bd4b123c304e43b18eeb1154 (diff)
downloadgitlab-ce-13b1508c3ed9887d9fcffdad66cbcf90b14eabd9.tar.gz
Merge branch '34758-deployment-cluster' into 'master'
Use group clusters when deploying (DeploymentPlatform) See merge request gitlab-org/gitlab-ce!22308
Diffstat (limited to 'app')
-rw-r--r--app/controllers/groups/clusters_controller.rb8
-rw-r--r--app/helpers/groups_helper.rb2
-rw-r--r--app/models/clusters/cluster.rb40
-rw-r--r--app/models/concerns/deployment_platform.rb13
-rw-r--r--app/models/group.rb4
-rw-r--r--app/models/namespace.rb6
-rw-r--r--app/models/project.rb19
-rw-r--r--app/services/clusters/refresh_service.rb40
-rw-r--r--app/services/projects/create_service.rb6
-rw-r--r--app/services/projects/transfer_service.rb5
-rw-r--r--app/workers/all_queues.yml1
-rw-r--r--app/workers/cluster_platform_configure_worker.rb12
-rw-r--r--app/workers/cluster_project_configure_worker.rb12
13 files changed, 144 insertions, 24 deletions
diff --git a/app/controllers/groups/clusters_controller.rb b/app/controllers/groups/clusters_controller.rb
index 50c44b7a58b..b846fb21266 100644
--- a/app/controllers/groups/clusters_controller.rb
+++ b/app/controllers/groups/clusters_controller.rb
@@ -3,8 +3,8 @@
class Groups::ClustersController < Clusters::ClustersController
include ControllerWithCrossProjectAccessCheck
- prepend_before_action :check_group_clusters_feature_flag!
prepend_before_action :group
+ prepend_before_action :check_group_clusters_feature_flag!
requires_cross_project_access
layout 'group'
@@ -20,6 +20,10 @@ class Groups::ClustersController < Clusters::ClustersController
end
def check_group_clusters_feature_flag!
- render_404 unless Feature.enabled?(:group_clusters)
+ render_404 unless group_clusters_enabled?
+ end
+
+ def group_clusters_enabled?
+ group.group_clusters_enabled?
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index e9b9b9b7721..866fc555856 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -140,7 +140,7 @@ module GroupsHelper
can?(current_user, "read_group_#{resource}".to_sym, @group)
end
- if can?(current_user, :read_cluster, @group) && Feature.enabled?(:group_clusters)
+ if can?(current_user, :read_cluster, @group) && @group.group_clusters_enabled?
links << :kubernetes
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 13906c903b9..c9bd1728dbd 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -4,6 +4,7 @@ module Clusters
class Cluster < ActiveRecord::Base
include Presentable
include Gitlab::Utils::StrongMemoize
+ include FromUnion
self.table_name = 'clusters'
@@ -86,6 +87,19 @@ 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
+
+ def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
+ hierarchy_groups = clusterable.ancestors_upto(hierarchy_order: hierarchy_order).eager_load(:clusters)
+ hierarchy_groups = hierarchy_groups.merge(current_scope) if current_scope
+
+ hierarchy_groups.flat_map(&:clusters)
+ end
+
def status_name
if provider
provider.status_name
@@ -122,6 +136,16 @@ module Clusters
!user?
end
+ def all_projects
+ if project_type?
+ projects
+ elsif group_type?
+ first_group.all_projects
+ else
+ Project.none
+ end
+ end
+
def first_project
strong_memoize(:first_project) do
projects.first
@@ -140,11 +164,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/concerns/deployment_platform.rb b/app/models/concerns/deployment_platform.rb
index e57a3383544..0107af5f8ec 100644
--- a/app/models/concerns/deployment_platform.rb
+++ b/app/models/concerns/deployment_platform.rb
@@ -13,6 +13,7 @@ module DeploymentPlatform
def find_deployment_platform(environment)
find_cluster_platform_kubernetes(environment: environment) ||
+ find_group_cluster_platform_kubernetes_with_feature_guard(environment: environment) ||
find_kubernetes_service_integration ||
build_cluster_and_deployment_platform
end
@@ -23,6 +24,18 @@ module DeploymentPlatform
.last&.platform_kubernetes
end
+ def find_group_cluster_platform_kubernetes_with_feature_guard(environment: nil)
+ return unless group_clusters_enabled?
+
+ find_group_cluster_platform_kubernetes(environment: environment)
+ end
+
+ # EE would override this and utilize environment argument
+ def find_group_cluster_platform_kubernetes(environment: nil)
+ Clusters::Cluster.enabled.default_environment.ancestor_clusters_for_clusterable(self)
+ .first&.platform_kubernetes
+ end
+
def find_kubernetes_service_integration
services.deployment.reorder(nil).find_by(active: true)
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 02ddc8762af..233747cc2c2 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -400,6 +400,10 @@ class Group < Namespace
ensure_runners_token!
end
+ def group_clusters_enabled?
+ Feature.enabled?(:group_clusters, root_ancestor, default_enabled: true)
+ end
+
private
def update_two_factor_requirement
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 11b03846f0b..8865c164b11 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -192,9 +192,9 @@ class Namespace < ActiveRecord::Base
# returns all ancestors upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
- def ancestors_upto(top = nil)
+ def ancestors_upto(top = nil, hierarchy_order: nil)
Gitlab::GroupHierarchy.new(self.class.where(id: id))
- .ancestors(upto: top)
+ .ancestors(upto: top, hierarchy_order: hierarchy_order)
end
def self_and_ancestors
@@ -243,7 +243,7 @@ class Namespace < ActiveRecord::Base
end
def root_ancestor
- ancestors.reorder(nil).find_by(parent_id: nil)
+ self_and_ancestors.reorder(nil).find_by(parent_id: nil)
end
def subgroup?
diff --git a/app/models/project.rb b/app/models/project.rb
index 0ab3ea53675..587bada469e 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -238,6 +238,7 @@ class Project < ActiveRecord::Base
has_one :cluster_project, class_name: 'Clusters::Project'
has_many :clusters, through: :cluster_project, class_name: 'Clusters::Cluster'
has_many :cluster_ingresses, through: :clusters, source: :application_ingress, class_name: 'Clusters::Applications::Ingress'
+ has_many :kubernetes_namespaces, class_name: 'Clusters::KubernetesNamespace'
has_many :prometheus_metrics
@@ -300,6 +301,8 @@ class Project < ActiveRecord::Base
delegate :add_guest, :add_reporter, :add_developer, :add_maintainer, :add_role, to: :team
delegate :add_master, to: :team # @deprecated
delegate :group_runners_enabled, :group_runners_enabled=, :group_runners_enabled?, to: :ci_cd_settings
+ delegate :group_clusters_enabled?, to: :group, allow_nil: true
+ delegate :root_ancestor, to: :namespace, allow_nil: true
# Validations
validates :creator, presence: true, on: :create
@@ -392,6 +395,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,
@@ -556,9 +565,9 @@ class Project < ActiveRecord::Base
# returns all ancestor-groups upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
- def ancestors_upto(top = nil)
+ def ancestors_upto(top = nil, hierarchy_order: nil)
Gitlab::GroupHierarchy.new(Group.where(id: namespace_id))
- .base_and_ancestors(upto: top)
+ .base_and_ancestors(upto: top, hierarchy_order: hierarchy_order)
end
def lfs_enabled?
@@ -1071,6 +1080,12 @@ class Project < ActiveRecord::Base
path
end
+ def all_clusters
+ group_clusters = Clusters::Cluster.joins(:groups).where(cluster_groups: { group_id: ancestors_upto } )
+
+ Clusters::Cluster.from_union([clusters, group_clusters])
+ end
+
def items_for(entity)
case entity
when 'issue' then
diff --git a/app/services/clusters/refresh_service.rb b/app/services/clusters/refresh_service.rb
new file mode 100644
index 00000000000..7c82b98a33f
--- /dev/null
+++ b/app/services/clusters/refresh_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Clusters
+ class RefreshService
+ def self.create_or_update_namespaces_for_cluster(cluster)
+ projects_with_missing_kubernetes_namespaces_for_cluster(cluster).each do |project|
+ create_or_update_namespace(cluster, project)
+ end
+ end
+
+ def self.create_or_update_namespaces_for_project(project)
+ clusters_with_missing_kubernetes_namespaces_for_project(project).each do |cluster|
+ create_or_update_namespace(cluster, project)
+ end
+ end
+
+ def self.projects_with_missing_kubernetes_namespaces_for_cluster(cluster)
+ cluster.all_projects.missing_kubernetes_namespace(cluster.kubernetes_namespaces)
+ end
+
+ private_class_method :projects_with_missing_kubernetes_namespaces_for_cluster
+
+ def self.clusters_with_missing_kubernetes_namespaces_for_project(project)
+ project.all_clusters.missing_kubernetes_namespace(project.kubernetes_namespaces)
+ end
+
+ private_class_method :clusters_with_missing_kubernetes_namespaces_for_project
+
+ def self.create_or_update_namespace(cluster, 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
+
+ private_class_method :create_or_update_namespace
+ 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..aa7570caa79 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.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..497e57c0d0b
--- /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.create_or_update_namespaces_for_project(project)
+ end
+end