2018-08-03 07:15:25 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-10-13 17:21:23 +00:00
|
|
|
module Clusters
|
2019-03-28 13:17:42 +00:00
|
|
|
class Cluster < ApplicationRecord
|
2020-07-08 12:09:33 +00:00
|
|
|
prepend HasEnvironmentScope
|
2017-10-13 17:21:23 +00:00
|
|
|
include Presentable
|
2018-11-03 10:13:05 +00:00
|
|
|
include Gitlab::Utils::StrongMemoize
|
2018-11-25 08:26:28 +00:00
|
|
|
include FromUnion
|
2019-05-27 08:23:17 +00:00
|
|
|
include ReactiveCaching
|
2019-10-29 12:06:40 +00:00
|
|
|
include AfterCommitQueue
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2017-10-23 08:36:35 +00:00
|
|
|
self.table_name = 'clusters'
|
|
|
|
|
2017-11-02 14:10:46 +00:00
|
|
|
APPLICATIONS = {
|
2020-02-25 15:08:50 +00:00
|
|
|
Clusters::Applications::Helm.application_name => Clusters::Applications::Helm,
|
|
|
|
Clusters::Applications::Ingress.application_name => Clusters::Applications::Ingress,
|
|
|
|
Clusters::Applications::CertManager.application_name => Clusters::Applications::CertManager,
|
|
|
|
Clusters::Applications::Crossplane.application_name => Clusters::Applications::Crossplane,
|
|
|
|
Clusters::Applications::Prometheus.application_name => Clusters::Applications::Prometheus,
|
|
|
|
Clusters::Applications::Runner.application_name => Clusters::Applications::Runner,
|
|
|
|
Clusters::Applications::Jupyter.application_name => Clusters::Applications::Jupyter,
|
|
|
|
Clusters::Applications::Knative.application_name => Clusters::Applications::Knative,
|
2020-04-16 00:09:22 +00:00
|
|
|
Clusters::Applications::ElasticStack.application_name => Clusters::Applications::ElasticStack,
|
2020-07-09 06:09:37 +00:00
|
|
|
Clusters::Applications::Cilium.application_name => Clusters::Applications::Cilium
|
2019-10-26 00:06:20 +00:00
|
|
|
}.freeze
|
2019-08-31 19:57:00 +00:00
|
|
|
DEFAULT_ENVIRONMENT = '*'
|
|
|
|
KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN'
|
2019-11-19 03:06:07 +00:00
|
|
|
APPLICATIONS_ASSOCIATIONS = APPLICATIONS.values.map(&:association_name).freeze
|
2017-11-02 14:10:46 +00:00
|
|
|
|
2020-04-24 21:09:48 +00:00
|
|
|
self.reactive_cache_work_type = :external_dependency
|
|
|
|
|
2017-10-13 17:21:23 +00:00
|
|
|
belongs_to :user
|
2019-10-14 12:06:14 +00:00
|
|
|
belongs_to :management_project, class_name: '::Project', optional: true
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2017-10-23 08:36:35 +00:00
|
|
|
has_many :cluster_projects, class_name: 'Clusters::Project'
|
2018-04-18 13:41:42 +00:00
|
|
|
has_many :projects, through: :cluster_projects, class_name: '::Project'
|
2018-11-02 15:46:15 +00:00
|
|
|
has_one :cluster_project, -> { order(id: :desc) }, class_name: 'Clusters::Project'
|
2020-02-10 12:08:59 +00:00
|
|
|
has_many :deployment_clusters
|
2020-05-04 03:09:50 +00:00
|
|
|
has_many :deployments, inverse_of: :cluster
|
2020-06-16 03:08:24 +00:00
|
|
|
has_many :successful_deployments, -> { success }, class_name: 'Deployment'
|
|
|
|
has_many :environments, -> { distinct }, through: :deployments
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2018-10-14 20:42:29 +00:00
|
|
|
has_many :cluster_groups, class_name: 'Clusters::Group'
|
|
|
|
has_many :groups, through: :cluster_groups, class_name: '::Group'
|
2019-12-10 07:53:40 +00:00
|
|
|
has_many :groups_projects, through: :groups, source: :projects, class_name: '::Project'
|
2018-10-14 20:42:29 +00:00
|
|
|
|
2017-11-01 11:57:05 +00:00
|
|
|
# we force autosave to happen when we save `Cluster` model
|
|
|
|
has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp', autosave: true
|
2019-10-16 21:07:22 +00:00
|
|
|
has_one :provider_aws, class_name: 'Clusters::Providers::Aws', autosave: true
|
2017-11-01 11:57:05 +00:00
|
|
|
|
2018-11-06 08:55:10 +00:00
|
|
|
has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', inverse_of: :cluster, autosave: true
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2021-04-15 12:09:05 +00:00
|
|
|
has_one :integration_prometheus, class_name: 'Clusters::Integrations::Prometheus', inverse_of: :cluster
|
2021-05-14 03:10:11 +00:00
|
|
|
has_one :integration_elastic_stack, class_name: 'Clusters::Integrations::ElasticStack', inverse_of: :cluster
|
2021-04-15 12:09:05 +00:00
|
|
|
|
2019-09-17 12:06:48 +00:00
|
|
|
def self.has_one_cluster_application(name) # rubocop:disable Naming/PredicateName
|
|
|
|
application = APPLICATIONS[name.to_s]
|
2019-09-20 12:05:52 +00:00
|
|
|
has_one application.association_name, class_name: application.to_s, inverse_of: :cluster # rubocop:disable Rails/ReflectionClassName
|
2019-09-17 12:06:48 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
has_one_cluster_application :helm
|
|
|
|
has_one_cluster_application :ingress
|
|
|
|
has_one_cluster_application :cert_manager
|
2019-11-18 03:06:28 +00:00
|
|
|
has_one_cluster_application :crossplane
|
2019-09-17 12:06:48 +00:00
|
|
|
has_one_cluster_application :prometheus
|
|
|
|
has_one_cluster_application :runner
|
|
|
|
has_one_cluster_application :jupyter
|
|
|
|
has_one_cluster_application :knative
|
2019-10-22 15:06:06 +00:00
|
|
|
has_one_cluster_application :elastic_stack
|
2020-07-09 06:09:37 +00:00
|
|
|
has_one_cluster_application :cilium
|
2017-11-02 14:10:46 +00:00
|
|
|
|
2018-10-16 20:03:59 +00:00
|
|
|
has_many :kubernetes_namespaces
|
2020-04-07 18:09:19 +00:00
|
|
|
has_many :metrics_dashboard_annotations, class_name: 'Metrics::Dashboard::Annotation', inverse_of: :cluster
|
2018-10-16 20:03:59 +00:00
|
|
|
|
2017-10-31 08:47:48 +00:00
|
|
|
accepts_nested_attributes_for :provider_gcp, update_only: true
|
2019-11-13 06:06:38 +00:00
|
|
|
accepts_nested_attributes_for :provider_aws, update_only: true
|
2017-10-30 12:55:18 +00:00
|
|
|
accepts_nested_attributes_for :platform_kubernetes, update_only: true
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2017-10-23 08:36:35 +00:00
|
|
|
validates :name, cluster_name: true
|
2018-10-14 20:42:29 +00:00
|
|
|
validates :cluster_type, presence: true
|
2019-02-14 21:10:35 +00:00
|
|
|
validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
|
2019-08-07 04:40:29 +00:00
|
|
|
validates :namespace_per_environment, inclusion: { in: [true, false] }
|
2020-11-05 09:09:00 +00:00
|
|
|
validates :helm_major_version, inclusion: { in: [2, 3] }
|
|
|
|
|
|
|
|
default_value_for :helm_major_version, 3
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2019-01-14 17:59:35 +00:00
|
|
|
validate :restrict_modification, on: :update
|
2018-10-14 20:42:29 +00:00
|
|
|
validate :no_groups, unless: :group_type?
|
|
|
|
validate :no_projects, unless: :project_type?
|
2019-10-14 12:06:14 +00:00
|
|
|
validate :unique_management_project_environment_scope
|
2020-07-08 12:09:33 +00:00
|
|
|
validate :unique_environment_scope
|
2018-10-14 20:42:29 +00:00
|
|
|
|
2019-05-27 08:23:17 +00:00
|
|
|
after_save :clear_reactive_cache!
|
|
|
|
|
2017-11-03 08:22:11 +00:00
|
|
|
delegate :status, to: :provider, allow_nil: true
|
2017-10-13 17:21:23 +00:00
|
|
|
delegate :status_reason, to: :provider, allow_nil: true
|
2017-10-23 08:36:35 +00:00
|
|
|
delegate :on_creation?, to: :provider, allow_nil: true
|
2019-11-13 06:06:38 +00:00
|
|
|
delegate :knative_pre_installed?, to: :provider, allow_nil: true
|
2017-10-13 17:21:23 +00:00
|
|
|
|
2017-11-06 14:48:44 +00:00
|
|
|
delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true
|
2018-09-06 10:03:38 +00:00
|
|
|
delegate :rbac?, to: :platform_kubernetes, prefix: true, allow_nil: true
|
2018-10-15 09:03:15 +00:00
|
|
|
delegate :available?, to: :application_helm, prefix: true, allow_nil: true
|
|
|
|
delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
|
2018-12-21 03:38:50 +00:00
|
|
|
delegate :available?, to: :application_knative, prefix: true, allow_nil: true
|
2021-05-14 03:10:11 +00:00
|
|
|
delegate :available?, to: :integration_elastic_stack, prefix: true, allow_nil: true
|
2021-06-03 12:10:18 +00:00
|
|
|
delegate :available?, to: :integration_prometheus, prefix: true, allow_nil: true
|
2019-01-23 16:28:19 +00:00
|
|
|
delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true
|
2019-03-07 21:51:43 +00:00
|
|
|
delegate :external_hostname, to: :application_ingress, prefix: true, allow_nil: true
|
2017-11-06 14:48:44 +00:00
|
|
|
|
2019-01-31 14:58:58 +00:00
|
|
|
alias_attribute :base_domain, :domain
|
2019-03-29 18:23:18 +00:00
|
|
|
alias_attribute :provided_by_user?, :user?
|
2019-01-31 14:58:58 +00:00
|
|
|
|
2018-10-14 20:42:29 +00:00
|
|
|
enum cluster_type: {
|
|
|
|
instance_type: 1,
|
|
|
|
group_type: 2,
|
|
|
|
project_type: 3
|
|
|
|
}
|
|
|
|
|
2017-10-29 18:48:45 +00:00
|
|
|
enum platform_type: {
|
|
|
|
kubernetes: 1
|
|
|
|
}
|
|
|
|
|
|
|
|
enum provider_type: {
|
|
|
|
user: 0,
|
2019-10-16 21:07:22 +00:00
|
|
|
gcp: 1,
|
|
|
|
aws: 2
|
2017-10-29 18:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
scope :enabled, -> { where(enabled: true) }
|
|
|
|
scope :disabled, -> { where(enabled: false) }
|
2019-10-16 21:07:22 +00:00
|
|
|
|
|
|
|
scope :user_provided, -> { where(provider_type: :user) }
|
|
|
|
scope :gcp_provided, -> { where(provider_type: :gcp) }
|
|
|
|
scope :aws_provided, -> { where(provider_type: :aws) }
|
|
|
|
|
2019-09-24 06:06:02 +00:00
|
|
|
scope :gcp_installed, -> { gcp_provided.joins(:provider_gcp).merge(Clusters::Providers::Gcp.with_status(:created)) }
|
2019-10-16 21:07:22 +00:00
|
|
|
scope :aws_installed, -> { aws_provided.joins(:provider_aws).merge(Clusters::Providers::Aws.with_status(:created)) }
|
|
|
|
|
2020-06-16 03:08:24 +00:00
|
|
|
scope :with_available_elasticstack, -> { joins(:application_elastic_stack).merge(::Clusters::Applications::ElasticStack.available) }
|
2020-07-14 09:09:02 +00:00
|
|
|
scope :with_available_cilium, -> { joins(:application_cilium).merge(::Clusters::Applications::Cilium.available) }
|
2020-06-16 03:08:24 +00:00
|
|
|
scope :distinct_with_deployed_environments, -> { joins(:environments).merge(::Deployment.success).distinct }
|
|
|
|
|
2019-05-03 01:05:53 +00:00
|
|
|
scope :managed, -> { where(managed: true) }
|
2019-11-19 03:06:07 +00:00
|
|
|
scope :with_persisted_applications, -> { eager_load(*APPLICATIONS_ASSOCIATIONS) }
|
2018-03-21 14:59:40 +00:00
|
|
|
scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) }
|
2020-04-09 18:09:34 +00:00
|
|
|
scope :with_management_project, -> { where.not(management_project: nil) }
|
2017-10-29 18:48:45 +00:00
|
|
|
|
2019-10-24 12:06:03 +00:00
|
|
|
scope :for_project_namespace, -> (namespace_id) { joins(:projects).where(projects: { namespace_id: namespace_id }) }
|
2021-09-09 18:11:44 +00:00
|
|
|
scope :with_name, -> (name) { where(name: name) }
|
2021-04-15 12:09:05 +00:00
|
|
|
|
2021-10-19 06:09:36 +00:00
|
|
|
scope :with_integration_prometheus, -> { includes(:integration_prometheus).joins(:integration_prometheus) }
|
2020-12-07 18:10:36 +00:00
|
|
|
scope :with_project_http_integrations, -> (project_ids) do
|
|
|
|
conditions = { projects: :alert_management_http_integrations }
|
2020-05-28 03:08:08 +00:00
|
|
|
includes(conditions).joins(conditions).where(projects: { id: project_ids })
|
|
|
|
end
|
2019-10-24 12:06:03 +00:00
|
|
|
|
2018-12-02 21:22:33 +00:00
|
|
|
def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
|
2019-04-18 02:45:31 +00:00
|
|
|
return [] if clusterable.is_a?(Instance)
|
|
|
|
|
2018-12-03 11:38:20 +00:00
|
|
|
hierarchy_groups = clusterable.ancestors_upto(hierarchy_order: hierarchy_order).eager_load(:clusters)
|
|
|
|
hierarchy_groups = hierarchy_groups.merge(current_scope) if current_scope
|
2018-10-29 02:28:36 +00:00
|
|
|
|
2019-04-18 02:45:31 +00:00
|
|
|
hierarchy_groups.flat_map(&:clusters) + Instance.new.clusters
|
2018-10-29 02:28:36 +00:00
|
|
|
end
|
|
|
|
|
2019-10-29 12:06:40 +00:00
|
|
|
state_machine :cleanup_status, initial: :cleanup_not_started do
|
|
|
|
state :cleanup_not_started, value: 1
|
|
|
|
state :cleanup_removing_project_namespaces, value: 3
|
|
|
|
state :cleanup_removing_service_account, value: 4
|
|
|
|
state :cleanup_errored, value: 5
|
|
|
|
|
|
|
|
event :start_cleanup do |cluster|
|
2021-06-15 21:10:04 +00:00
|
|
|
transition [:cleanup_not_started, :cleanup_errored] => :cleanup_removing_project_namespaces
|
2019-10-29 12:06:40 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
event :continue_cleanup do
|
|
|
|
transition(
|
|
|
|
cleanup_removing_project_namespaces: :cleanup_removing_service_account)
|
|
|
|
end
|
|
|
|
|
|
|
|
event :make_cleanup_errored do
|
|
|
|
transition any => :cleanup_errored
|
|
|
|
end
|
|
|
|
|
|
|
|
before_transition any => [:cleanup_errored] do |cluster, transition|
|
|
|
|
status_reason = transition.args.first
|
|
|
|
cluster.cleanup_status_reason = status_reason if status_reason
|
|
|
|
end
|
|
|
|
|
2021-06-15 21:10:04 +00:00
|
|
|
after_transition [:cleanup_not_started, :cleanup_errored] => :cleanup_removing_project_namespaces do |cluster|
|
2019-10-29 12:06:40 +00:00
|
|
|
cluster.run_after_commit do
|
|
|
|
Clusters::Cleanup::ProjectNamespaceWorker.perform_async(cluster.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
after_transition cleanup_removing_project_namespaces: :cleanup_removing_service_account do |cluster|
|
|
|
|
cluster.run_after_commit do
|
|
|
|
Clusters::Cleanup::ServiceAccountWorker.perform_async(cluster.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-10 07:53:40 +00:00
|
|
|
def all_projects
|
|
|
|
return projects if project_type?
|
|
|
|
return groups_projects if group_type?
|
|
|
|
|
|
|
|
::Project.all
|
|
|
|
end
|
|
|
|
|
2017-11-02 14:10:46 +00:00
|
|
|
def status_name
|
2019-10-29 12:06:40 +00:00
|
|
|
return cleanup_status_name if cleanup_errored?
|
|
|
|
return :cleanup_ongoing unless cleanup_not_started?
|
|
|
|
|
2019-05-27 08:23:17 +00:00
|
|
|
provider&.status_name || connection_status.presence || :created
|
|
|
|
end
|
|
|
|
|
2020-08-05 21:09:40 +00:00
|
|
|
def connection_error
|
|
|
|
with_reactive_cache do |data|
|
|
|
|
data[:connection_error]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def node_connection_error
|
|
|
|
with_reactive_cache do |data|
|
|
|
|
data[:node_connection_error]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def metrics_connection_error
|
|
|
|
with_reactive_cache do |data|
|
|
|
|
data[:metrics_connection_error]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-05-27 08:23:17 +00:00
|
|
|
def connection_status
|
|
|
|
with_reactive_cache do |data|
|
|
|
|
data[:connection_status]
|
2017-11-02 14:10:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-14 21:07:52 +00:00
|
|
|
def nodes
|
|
|
|
with_reactive_cache do |data|
|
|
|
|
data[:nodes]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-05-27 08:23:17 +00:00
|
|
|
def calculate_reactive_cache
|
|
|
|
return unless enabled?
|
|
|
|
|
2020-08-05 21:09:40 +00:00
|
|
|
connection_data.merge(Gitlab::Kubernetes::Node.new(self).all)
|
2017-12-01 15:49:56 +00:00
|
|
|
end
|
|
|
|
|
2019-11-19 03:06:07 +00:00
|
|
|
def persisted_applications
|
|
|
|
APPLICATIONS_ASSOCIATIONS.map(&method(:public_send)).compact
|
|
|
|
end
|
|
|
|
|
2017-11-02 16:57:50 +00:00
|
|
|
def applications
|
2020-05-18 12:08:08 +00:00
|
|
|
APPLICATIONS.each_value.map do |application_class|
|
|
|
|
find_or_build_application(application_class)
|
2019-09-17 12:06:48 +00:00
|
|
|
end
|
2017-11-02 16:57:50 +00:00
|
|
|
end
|
|
|
|
|
2020-05-18 12:08:08 +00:00
|
|
|
def find_or_build_application(application_class)
|
|
|
|
raise ArgumentError, "#{application_class} is not in APPLICATIONS" unless APPLICATIONS.value?(application_class)
|
|
|
|
|
|
|
|
association_name = application_class.association_name
|
|
|
|
|
|
|
|
public_send(association_name) || public_send("build_#{association_name}") # rubocop:disable GitlabSecurity/PublicSend
|
|
|
|
end
|
|
|
|
|
2021-04-15 12:09:05 +00:00
|
|
|
def find_or_build_integration_prometheus
|
|
|
|
integration_prometheus || build_integration_prometheus
|
|
|
|
end
|
|
|
|
|
2021-05-14 03:10:11 +00:00
|
|
|
def find_or_build_integration_elastic_stack
|
|
|
|
integration_elastic_stack || build_integration_elastic_stack
|
|
|
|
end
|
|
|
|
|
2017-10-13 17:21:23 +00:00
|
|
|
def provider
|
2019-10-16 21:07:22 +00:00
|
|
|
if gcp?
|
|
|
|
provider_gcp
|
|
|
|
elsif aws?
|
|
|
|
provider_aws
|
|
|
|
end
|
2017-10-13 17:21:23 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def platform
|
2017-10-23 08:36:35 +00:00
|
|
|
return platform_kubernetes if kubernetes?
|
|
|
|
end
|
|
|
|
|
2017-10-13 17:21:23 +00:00
|
|
|
def first_project
|
2018-11-03 10:13:05 +00:00
|
|
|
strong_memoize(:first_project) do
|
|
|
|
projects.first
|
|
|
|
end
|
2017-10-13 17:21:23 +00:00
|
|
|
end
|
2017-10-29 18:48:45 +00:00
|
|
|
alias_method :project, :first_project
|
2017-10-23 08:36:35 +00:00
|
|
|
|
2018-11-03 10:13:05 +00:00
|
|
|
def first_group
|
|
|
|
strong_memoize(:first_group) do
|
|
|
|
groups.first
|
|
|
|
end
|
|
|
|
end
|
|
|
|
alias_method :group, :first_group
|
|
|
|
|
2019-04-10 02:13:43 +00:00
|
|
|
def instance
|
|
|
|
Instance.new if instance_type?
|
|
|
|
end
|
|
|
|
|
2017-11-02 14:10:46 +00:00
|
|
|
def kubeclient
|
2021-11-12 03:12:11 +00:00
|
|
|
platform_kubernetes&.kubeclient if kubernetes?
|
2017-11-02 14:10:46 +00:00
|
|
|
end
|
|
|
|
|
2021-05-14 03:10:11 +00:00
|
|
|
def elastic_stack_adapter
|
2021-06-03 12:10:18 +00:00
|
|
|
integration_elastic_stack
|
2021-05-14 03:10:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def elasticsearch_client
|
|
|
|
elastic_stack_adapter&.elasticsearch_client
|
|
|
|
end
|
|
|
|
|
|
|
|
def elastic_stack_available?
|
2021-06-03 12:10:18 +00:00
|
|
|
!!integration_elastic_stack_available?
|
2021-05-14 03:10:11 +00:00
|
|
|
end
|
|
|
|
|
2020-03-06 06:08:30 +00:00
|
|
|
def kubernetes_namespace_for(environment, deployable: environment.last_deployable)
|
|
|
|
if deployable && environment.project_id != deployable.project_id
|
|
|
|
raise ArgumentError, 'environment.project_id must match deployable.project_id'
|
|
|
|
end
|
|
|
|
|
2019-12-12 12:07:33 +00:00
|
|
|
managed_namespace(environment) ||
|
2020-03-06 06:08:30 +00:00
|
|
|
ci_configured_namespace(deployable) ||
|
2019-12-12 12:07:33 +00:00
|
|
|
default_namespace(environment)
|
2018-11-02 15:46:15 +00:00
|
|
|
end
|
|
|
|
|
2018-11-06 23:30:36 +00:00
|
|
|
def allow_user_defined_namespace?
|
2019-05-24 08:39:59 +00:00
|
|
|
project_type? || !managed?
|
2018-11-06 23:30:36 +00:00
|
|
|
end
|
|
|
|
|
2019-02-05 19:11:33 +00:00
|
|
|
def kube_ingress_domain
|
2019-05-20 03:55:11 +00:00
|
|
|
@kube_ingress_domain ||= domain.presence || instance_domain
|
2019-01-23 16:28:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def predefined_variables
|
|
|
|
Gitlab::Ci::Variables::Collection.new.tap do |variables|
|
2019-02-05 19:11:33 +00:00
|
|
|
break variables unless kube_ingress_domain
|
2019-01-23 16:28:19 +00:00
|
|
|
|
2019-02-05 19:11:33 +00:00
|
|
|
variables.append(key: KUBE_INGRESS_BASE_DOMAIN, value: kube_ingress_domain)
|
2019-01-23 16:28:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-11-26 09:08:36 +00:00
|
|
|
def delete_cached_resources!
|
|
|
|
kubernetes_namespaces.delete_all(:delete_all)
|
|
|
|
end
|
|
|
|
|
2019-12-04 21:07:31 +00:00
|
|
|
def clusterable
|
|
|
|
return unless cluster_type
|
|
|
|
|
|
|
|
case cluster_type
|
|
|
|
when 'project_type'
|
|
|
|
project
|
|
|
|
when 'group_type'
|
|
|
|
group
|
|
|
|
when 'instance_type'
|
|
|
|
instance
|
|
|
|
else
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-02-11 18:08:58 +00:00
|
|
|
def serverless_domain
|
|
|
|
strong_memoize(:serverless_domain) do
|
|
|
|
self.application_knative&.serverless_domain_cluster
|
|
|
|
end
|
|
|
|
end
|
2020-06-11 06:08:22 +00:00
|
|
|
|
2020-07-13 15:09:08 +00:00
|
|
|
def prometheus_adapter
|
2021-06-03 12:10:18 +00:00
|
|
|
integration_prometheus
|
2020-07-13 15:09:08 +00:00
|
|
|
end
|
|
|
|
|
2017-10-23 08:36:35 +00:00
|
|
|
private
|
|
|
|
|
2019-10-14 12:06:14 +00:00
|
|
|
def unique_management_project_environment_scope
|
|
|
|
return unless management_project
|
|
|
|
|
|
|
|
duplicate_management_clusters = management_project.management_clusters
|
|
|
|
.where(environment_scope: environment_scope)
|
|
|
|
.where.not(id: id)
|
|
|
|
|
|
|
|
if duplicate_management_clusters.any?
|
2020-03-03 09:07:54 +00:00
|
|
|
errors.add(:environment_scope, 'cannot add duplicated environment scope')
|
2019-10-14 12:06:14 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-08 12:09:33 +00:00
|
|
|
def unique_environment_scope
|
|
|
|
if clusterable.present? && clusterable.clusters.where(environment_scope: environment_scope).where.not(id: id).exists?
|
|
|
|
errors.add(:environment_scope, 'cannot add duplicated environment scope')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-12 12:07:33 +00:00
|
|
|
def managed_namespace(environment)
|
|
|
|
Clusters::KubernetesNamespaceFinder.new(
|
|
|
|
self,
|
|
|
|
project: environment.project,
|
|
|
|
environment_name: environment.name
|
|
|
|
).execute&.namespace
|
|
|
|
end
|
|
|
|
|
2020-03-06 06:08:30 +00:00
|
|
|
def ci_configured_namespace(deployable)
|
|
|
|
# YAML configuration of namespaces not supported for managed clusters
|
|
|
|
return if managed?
|
|
|
|
|
|
|
|
deployable&.expanded_kubernetes_namespace
|
2019-12-12 12:07:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def default_namespace(environment)
|
|
|
|
Gitlab::Kubernetes::DefaultNamespace.new(
|
|
|
|
self,
|
|
|
|
project: environment.project
|
|
|
|
).from_environment_slug(environment.slug)
|
|
|
|
end
|
|
|
|
|
2019-01-23 16:28:19 +00:00
|
|
|
def instance_domain
|
2019-02-05 19:11:33 +00:00
|
|
|
@instance_domain ||= Gitlab::CurrentSettings.auto_devops_domain
|
|
|
|
end
|
|
|
|
|
2020-08-05 21:09:40 +00:00
|
|
|
def connection_data
|
2020-05-14 21:07:52 +00:00
|
|
|
result = ::Gitlab::Kubernetes::KubeClient.graceful_request(id) { kubeclient.core_client.discover }
|
2020-08-05 21:09:40 +00:00
|
|
|
|
|
|
|
{ connection_status: result[:status], connection_error: result[:connection_error] }.compact
|
2020-05-14 21:07:52 +00:00
|
|
|
end
|
|
|
|
|
2019-05-27 08:23:17 +00:00
|
|
|
# To keep backward compatibility with AUTO_DEVOPS_DOMAIN
|
|
|
|
# environment variable, we need to ensure KUBE_INGRESS_BASE_DOMAIN
|
|
|
|
# is set if AUTO_DEVOPS_DOMAIN is set on any of the following options:
|
|
|
|
# ProjectAutoDevops#Domain, project variables or group variables,
|
|
|
|
# as the AUTO_DEVOPS_DOMAIN is needed for CI_ENVIRONMENT_URL
|
|
|
|
#
|
|
|
|
# This method should is scheduled to be removed on
|
2019-09-18 14:02:45 +00:00
|
|
|
# https://gitlab.com/gitlab-org/gitlab-foss/issues/56959
|
2019-05-27 08:23:17 +00:00
|
|
|
def legacy_auto_devops_domain
|
|
|
|
if project_type?
|
|
|
|
project&.auto_devops&.domain.presence ||
|
|
|
|
project.variables.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence ||
|
|
|
|
project.group&.variables&.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence
|
|
|
|
elsif group_type?
|
|
|
|
group.variables.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-23 08:36:35 +00:00
|
|
|
def restrict_modification
|
|
|
|
if provider&.on_creation?
|
2020-03-03 09:07:54 +00:00
|
|
|
errors.add(:base, _('Cannot modify provider during creation'))
|
2017-10-23 08:36:35 +00:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
true
|
|
|
|
end
|
2018-10-14 20:42:29 +00:00
|
|
|
|
|
|
|
def no_groups
|
|
|
|
if groups.any?
|
|
|
|
errors.add(:cluster, 'cannot have groups assigned')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def no_projects
|
|
|
|
if projects.any?
|
|
|
|
errors.add(:cluster, 'cannot have projects assigned')
|
|
|
|
end
|
|
|
|
end
|
2017-10-13 17:21:23 +00:00
|
|
|
end
|
|
|
|
end
|
2019-09-13 13:26:31 +00:00
|
|
|
|
2021-05-11 21:10:21 +00:00
|
|
|
Clusters::Cluster.prepend_mod_with('Clusters::Cluster')
|