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, where_exists, with_fast_statement_timeout, without_order

Class Method Details

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


157
158
159
160
161
162
163
164
# File 'app/models/clusters/cluster.rb', line 157

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


211
212
213
214
215
216
# File 'app/models/clusters/cluster.rb', line 211

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

  ::Project.all
end

#allow_user_defined_namespace?Boolean

Returns:

  • (Boolean)

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

def allow_user_defined_namespace?
  project_type? || !managed?
end

#applicationsObject


265
266
267
268
269
# File 'app/models/clusters/cluster.rb', line 265

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

#calculate_reactive_cacheObject


255
256
257
258
259
# File 'app/models/clusters/cluster.rb', line 255

def calculate_reactive_cache
  return unless enabled?

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

#clusterableObject


343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'app/models/clusters/cluster.rb', line 343

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


225
226
227
228
229
# File 'app/models/clusters/cluster.rb', line 225

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

#connection_statusObject


243
244
245
246
247
# File 'app/models/clusters/cluster.rb', line 243

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

#delete_cached_resources!Object


339
340
341
# File 'app/models/clusters/cluster.rb', line 339

def delete_cached_resources!
  kubernetes_namespaces.delete_all(:delete_all)
end

#find_or_build_application(application_class) ⇒ Object

Raises:

  • (ArgumentError)

271
272
273
274
275
276
277
# File 'app/models/clusters/cluster.rb', line 271

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


298
299
300
301
302
# File 'app/models/clusters/cluster.rb', line 298

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

#first_projectObject Also known as: project


291
292
293
294
295
# File 'app/models/clusters/cluster.rb', line 291

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

#instanceObject


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

def instance
  Instance.new if instance_type?
end

#kube_ingress_domainObject


327
328
329
# File 'app/models/clusters/cluster.rb', line 327

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

#kubeclientObject


309
310
311
# File 'app/models/clusters/cluster.rb', line 309

def kubeclient
  platform_kubernetes.kubeclient if kubernetes?
end

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


313
314
315
316
317
318
319
320
321
# File 'app/models/clusters/cluster.rb', line 313

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


237
238
239
240
241
# File 'app/models/clusters/cluster.rb', line 237

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

#node_connection_errorObject


231
232
233
234
235
# File 'app/models/clusters/cluster.rb', line 231

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

#nodesObject


249
250
251
252
253
# File 'app/models/clusters/cluster.rb', line 249

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

#persisted_applicationsObject


261
262
263
# File 'app/models/clusters/cluster.rb', line 261

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

#platformObject


287
288
289
# File 'app/models/clusters/cluster.rb', line 287

def platform
  return platform_kubernetes if kubernetes?
end

#predefined_variablesObject


331
332
333
334
335
336
337
# File 'app/models/clusters/cluster.rb', line 331

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


364
365
366
# File 'app/models/clusters/cluster.rb', line 364

def prometheus_adapter
  application_prometheus
end

#providerObject


279
280
281
282
283
284
285
# File 'app/models/clusters/cluster.rb', line 279

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

#serverless_domainObject


358
359
360
361
362
# File 'app/models/clusters/cluster.rb', line 358

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

#status_nameObject


218
219
220
221
222
223
# File 'app/models/clusters/cluster.rb', line 218

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