Class: Clusters::Platforms::Kubernetes

Inherits:
ApplicationRecord show all
Includes:
AfterCommitQueue, Gitlab::Kubernetes, NullifyIfBlank, ReactiveCaching
Defined in:
app/models/clusters/platforms/kubernetes.rb

Constant Summary collapse

RESERVED_NAMESPACES =
%w[gitlab-managed-apps].freeze
REQUIRED_K8S_MIN_VERSION =
23
IGNORED_CONNECTION_EXCEPTIONS =
[
  Gitlab::UrlBlocker::BlockedUrlError,
  Kubeclient::HttpError,
  Errno::ECONNREFUSED,
  URI::InvalidURIError,
  Errno::EHOSTUNREACH,
  OpenSSL::X509::StoreError,
  OpenSSL::SSL::SSLError
].freeze
FailedVersionCheckError =
Class.new(StandardError)

Constants included from ReactiveCaching

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

Constants included from Gitlab::Kubernetes

Gitlab::Kubernetes::EXEC_COMMAND

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Constants included from ResetOnUnionError

ResetOnUnionError::MAX_RESET_PERIOD

Instance Method Summary collapse

Methods included from AfterCommitQueue

#run_after_commit, #run_after_commit_or_now

Methods included from Gitlab::Kubernetes

#add_terminal_auth, build_header_hash, #container_exec_url, #filter_by_annotation, #filter_by_label, #filter_by_legacy_label, #filter_by_project_environment, #terminals_for_pod, #to_kubeconfig

Methods inherited from ApplicationRecord

cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

Methods included from SensitiveSerializableHash

#serializable_hash

Instance Method Details

#allow_user_defined_namespace?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'app/models/clusters/platforms/kubernetes.rb', line 82

def allow_user_defined_namespace?
  !!cluster&.allow_user_defined_namespace?
end

#calculate_reactive_cache_for(environment) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'app/models/clusters/platforms/kubernetes.rb', line 112

def calculate_reactive_cache_for(environment)
  return unless enabled?

  pods = []
  deployments = []
  ingresses = []

  begin
    pods = read_pods(environment.deployment_namespace)
    deployments = read_deployments(environment.deployment_namespace)

    ingresses = read_ingresses(environment.deployment_namespace)
  rescue *IGNORED_CONNECTION_EXCEPTIONS => e
    log_kube_connection_error(e)

    # Return hash with default values so that it is cached.
    return {
      pods: pods, deployments: deployments, ingresses: ingresses
    }
  end

  # extract only the data required for display to avoid unnecessary caching
  {
    pods: extract_relevant_pod_data(pods),
    deployments: extract_relevant_deployment_data(deployments),
    ingresses: extract_relevant_ingress_data(ingresses)
  }
end

#enabled?Boolean Also known as: active?

Returns:

  • (Boolean)


73
74
75
# File 'app/models/clusters/platforms/kubernetes.rb', line 73

def enabled?
  !!cluster&.enabled?
end

#ingresses(namespace) ⇒ Object



161
162
163
164
# File 'app/models/clusters/platforms/kubernetes.rb', line 161

def ingresses(namespace)
  ingresses = read_ingresses(namespace)
  ingresses.map { |ingress| ::Gitlab::Kubernetes::Ingress.new(ingress) }
end

#kubeclientObject



147
148
149
# File 'app/models/clusters/platforms/kubernetes.rb', line 147

def kubeclient
  @kubeclient ||= build_kube_client!
end

#kubeconfig(namespace) ⇒ Object



170
171
172
173
174
175
176
# File 'app/models/clusters/platforms/kubernetes.rb', line 170

def kubeconfig(namespace)
  to_kubeconfig(
    url: api_url,
    namespace: namespace,
    token: token,
    ca_pem: ca_pem)
end

#patch_ingress(namespace, ingress, data) ⇒ Object



166
167
168
# File 'app/models/clusters/platforms/kubernetes.rb', line 166

def patch_ingress(namespace, ingress, data)
  kubeclient.patch_ingress(ingress.name, data, namespace)
end

#predefined_variables(project:, environment_name:, kubernetes_namespace: nil) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'app/models/clusters/platforms/kubernetes.rb', line 86

def predefined_variables(project:, environment_name:, kubernetes_namespace: nil)
  Gitlab::Ci::Variables::Collection.new.tap do |variables|
    variables.append(key: 'KUBE_URL', value: api_url)

    if ca_pem.present?
      variables
        .append(key: 'KUBE_CA_PEM', value: ca_pem)
        .append(key: 'KUBE_CA_PEM_FILE', value: ca_pem, file: true)
    end

    if !cluster.managed? || cluster.management_project == project
      namespace = kubernetes_namespace || default_namespace(project, environment_name: environment_name)

      variables
        .append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
        .append(key: 'KUBE_NAMESPACE', value: namespace)
        .append(key: 'KUBECONFIG', value: kubeconfig(namespace), public: false, file: true)

    elsif persisted_namespace = find_persisted_namespace(project, environment_name: environment_name)
      variables.concat(persisted_namespace.predefined_variables)
    end

    variables.concat(cluster.predefined_variables)
  end
end

#provided_by_user?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'app/models/clusters/platforms/kubernetes.rb', line 78

def provided_by_user?
  !!cluster&.provided_by_user?
end

#rollout_status(environment, data) ⇒ Object



151
152
153
154
155
156
157
158
159
# File 'app/models/clusters/platforms/kubernetes.rb', line 151

def rollout_status(environment, data)
  project = environment.project

  deployments = filter_by_project_environment(data[:deployments], project.full_path_slug, environment.slug)
  pods = filter_by_project_environment(data[:pods], project.full_path_slug, environment.slug)
  ingresses = data[:ingresses].presence || []

  ::Gitlab::Kubernetes::RolloutStatus.from_deployments(*deployments, pods_attrs: pods, ingresses: ingresses)
end

#terminals(environment, data) ⇒ Object



141
142
143
144
145
# File 'app/models/clusters/platforms/kubernetes.rb', line 141

def terminals(environment, data)
  pods = filter_by_project_environment(data[:pods], environment.project.full_path_slug, environment.slug)
  terminals = pods.flat_map { |pod| terminals_for_pod(api_url, environment.deployment_namespace, pod) }.compact
  terminals.each { |terminal| add_terminal_auth(terminal, **terminal_auth) }
end