Class: Clusters::Cluster

Inherits:
ApplicationRecord show all
Includes:
AfterCommitQueue, FromUnion, Gitlab::Utils::StrongMemoize, Presentable, ReactiveCaching
Defined in:
app/models/clusters/cluster.rb

Constant Summary collapse

APPLICATIONS =
{
  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,
  Clusters::Applications::ElasticStack.application_name => Clusters::Applications::ElasticStack,
  Clusters::Applications::Fluentd.application_name => Clusters::Applications::Fluentd,
  Clusters::Applications::Cilium.application_name => Clusters::Applications::Cilium
}.freeze
DEFAULT_ENVIRONMENT =
'*'
KUBE_INGRESS_BASE_DOMAIN =
'KUBE_INGRESS_BASE_DOMAIN'
APPLICATIONS_ASSOCIATIONS =
APPLICATIONS.values.map(&:association_name).freeze

Constants included from ReactiveCaching

ReactiveCaching::ExceededReactiveCacheLimit, ReactiveCaching::InvalidateReactiveCache, ReactiveCaching::WORK_TYPE

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AfterCommitQueue

#run_after_commit, #run_after_commit_or_now

Methods included from Gitlab::Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Methods included from Presentable

#present

Methods inherited from ApplicationRecord

at_most, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, underscore, without_order

Class Method Details

.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc) ⇒ Object


154
155
156
157
158
159
160
161
# File 'app/models/clusters/cluster.rb', line 154

def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
  return [] if clusterable.is_a?(Instance)

  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) + Instance.new.clusters
end

.has_one_cluster_application(name) ⇒ Object

rubocop:disable Naming/PredicateName


54
55
56
57
# File 'app/models/clusters/cluster.rb', line 54

def self.has_one_cluster_application(name) # rubocop:disable Naming/PredicateName
  application = APPLICATIONS[name.to_s]
  has_one application.association_name, class_name: application.to_s, inverse_of: :cluster # rubocop:disable Rails/ReflectionClassName
end

Instance Method Details

#all_projectsObject


208
209
210
211
212
213
# File 'app/models/clusters/cluster.rb', line 208

def all_projects
  return projects if project_type?
  return groups_projects if group_type?

  ::Project.all
end

#allow_user_defined_namespace?Boolean

Returns:

  • (Boolean)

320
321
322
# File 'app/models/clusters/cluster.rb', line 320

def allow_user_defined_namespace?
  project_type? || !managed?
end

#applicationsObject


262
263
264
265
266
# File 'app/models/clusters/cluster.rb', line 262

def applications
  APPLICATIONS.each_value.map do |application_class|
    find_or_build_application(application_class)
  end
end

#calculate_reactive_cacheObject


252
253
254
255
256
# File 'app/models/clusters/cluster.rb', line 252

def calculate_reactive_cache
  return unless enabled?

  connection_data.merge(Gitlab::Kubernetes::Node.new(self).all)
end

#clusterableObject


340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'app/models/clusters/cluster.rb', line 340

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

#connection_errorObject


222
223
224
225
226
# File 'app/models/clusters/cluster.rb', line 222

def connection_error
  with_reactive_cache do |data|
    data[:connection_error]
  end
end

#connection_statusObject


240
241
242
243
244
# File 'app/models/clusters/cluster.rb', line 240

def connection_status
  with_reactive_cache do |data|
    data[:connection_status]
  end
end

#delete_cached_resources!Object


336
337
338
# File 'app/models/clusters/cluster.rb', line 336

def delete_cached_resources!
  kubernetes_namespaces.delete_all(:delete_all)
end

#find_or_build_application(application_class) ⇒ Object

Raises:

  • (ArgumentError)

268
269
270
271
272
273
274
# File 'app/models/clusters/cluster.rb', line 268

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

#first_groupObject Also known as: group


295
296
297
298
299
# File 'app/models/clusters/cluster.rb', line 295

def first_group
  strong_memoize(:first_group) do
    groups.first
  end
end

#first_projectObject Also known as: project


288
289
290
291
292
# File 'app/models/clusters/cluster.rb', line 288

def first_project
  strong_memoize(:first_project) do
    projects.first
  end
end

#instanceObject


302
303
304
# File 'app/models/clusters/cluster.rb', line 302

def instance
  Instance.new if instance_type?
end

#kube_ingress_domainObject


324
325
326
# File 'app/models/clusters/cluster.rb', line 324

def kube_ingress_domain
  @kube_ingress_domain ||= domain.presence || instance_domain
end

#kubeclientObject


306
307
308
# File 'app/models/clusters/cluster.rb', line 306

def kubeclient
  platform_kubernetes.kubeclient if kubernetes?
end

#kubernetes_namespace_for(environment, deployable: environment.last_deployable) ⇒ Object


310
311
312
313
314
315
316
317
318
# File 'app/models/clusters/cluster.rb', line 310

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

  managed_namespace(environment) ||
    ci_configured_namespace(deployable) ||
    default_namespace(environment)
end

#metrics_connection_errorObject


234
235
236
237
238
# File 'app/models/clusters/cluster.rb', line 234

def metrics_connection_error
  with_reactive_cache do |data|
    data[:metrics_connection_error]
  end
end

#node_connection_errorObject


228
229
230
231
232
# File 'app/models/clusters/cluster.rb', line 228

def node_connection_error
  with_reactive_cache do |data|
    data[:node_connection_error]
  end
end

#nodesObject


246
247
248
249
250
# File 'app/models/clusters/cluster.rb', line 246

def nodes
  with_reactive_cache do |data|
    data[:nodes]
  end
end

#persisted_applicationsObject


258
259
260
# File 'app/models/clusters/cluster.rb', line 258

def persisted_applications
  APPLICATIONS_ASSOCIATIONS.map(&method(:public_send)).compact
end

#platformObject


284
285
286
# File 'app/models/clusters/cluster.rb', line 284

def platform
  return platform_kubernetes if kubernetes?
end

#predefined_variablesObject


328
329
330
331
332
333
334
# File 'app/models/clusters/cluster.rb', line 328

def predefined_variables
  Gitlab::Ci::Variables::Collection.new.tap do |variables|
    break variables unless kube_ingress_domain

    variables.append(key: KUBE_INGRESS_BASE_DOMAIN, value: kube_ingress_domain)
  end
end

#prometheus_adapterObject


361
362
363
# File 'app/models/clusters/cluster.rb', line 361

def prometheus_adapter
  application_prometheus
end

#providerObject


276
277
278
279
280
281
282
# File 'app/models/clusters/cluster.rb', line 276

def provider
  if gcp?
    provider_gcp
  elsif aws?
    provider_aws
  end
end

#serverless_domainObject


355
356
357
358
359
# File 'app/models/clusters/cluster.rb', line 355

def serverless_domain
  strong_memoize(:serverless_domain) do
    self.application_knative&.serverless_domain_cluster
  end
end

#status_nameObject


215
216
217
218
219
220
# File 'app/models/clusters/cluster.rb', line 215

def status_name
  return cleanup_status_name if cleanup_errored?
  return :cleanup_ongoing unless cleanup_not_started?

  provider&.status_name || connection_status.presence || :created
end