Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 14:59:07 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 14:59:07 +0300
commit8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch)
tree544930fb309b30317ae9797a9683768705d664c4 /lib/gitlab/kubernetes
parent4b1de649d0168371549608993deac953eb692019 (diff)
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'lib/gitlab/kubernetes')
-rw-r--r--lib/gitlab/kubernetes/deployment.rb117
-rw-r--r--lib/gitlab/kubernetes/helm/v2/client_command.rb11
-rw-r--r--lib/gitlab/kubernetes/helm/v2/reset_command.rb26
-rw-r--r--lib/gitlab/kubernetes/ingress.rb46
-rw-r--r--lib/gitlab/kubernetes/rollout_instances.rb75
-rw-r--r--lib/gitlab/kubernetes/rollout_status.rb72
6 files changed, 313 insertions, 34 deletions
diff --git a/lib/gitlab/kubernetes/deployment.rb b/lib/gitlab/kubernetes/deployment.rb
new file mode 100644
index 00000000000..55ed9a7517e
--- /dev/null
+++ b/lib/gitlab/kubernetes/deployment.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class Deployment
+ include Gitlab::Utils::StrongMemoize
+
+ STABLE_TRACK_VALUE = 'stable'.freeze
+
+ def initialize(attributes = {}, pods: [])
+ @attributes = attributes
+ @pods = pods
+ end
+
+ def name
+ metadata['name'] || 'unknown'
+ end
+
+ def labels
+ metadata.fetch('labels', {})
+ end
+
+ def annotations
+ metadata.fetch('annotations', {})
+ end
+
+ def track
+ labels.fetch('track', STABLE_TRACK_VALUE)
+ end
+
+ def stable?
+ track == 'stable'
+ end
+
+ def order
+ stable? ? 1 : 0
+ end
+
+ def outdated?
+ observed_generation < generation
+ end
+
+ def wanted_instances
+ spec.fetch('replicas', 0)
+ end
+
+ def created_instances
+ filtered_pods_by_track.map do |pod|
+ pod_metadata = pod.fetch('metadata', {})
+ pod_name = pod_metadata['name'] || pod_metadata['generateName']
+ pod_status = pod.dig('status', 'phase')
+
+ deployment_instance(pod_name: pod_name, pod_status: pod_status)
+ end
+ end
+
+ # These are replicas that did not get created yet,
+ # So they still do not have any associated pod,
+ # these are marked as pending instances.
+ def not_created_instances
+ pending_instances_count = wanted_instances - filtered_pods_by_track.count
+
+ return [] if pending_instances_count <= 0
+
+ Array.new(pending_instances_count, deployment_instance(pod_name: 'Not provided', pod_status: 'Pending'))
+ end
+
+ def filtered_pods_by_track
+ strong_memoize(:filtered_pods_by_track) do
+ @pods.select { |pod| has_same_track?(pod) }
+ end
+ end
+
+ def instances
+ created_instances + not_created_instances
+ end
+
+ private
+
+ def deployment_instance(pod_name:, pod_status:)
+ {
+ status: pod_status&.downcase,
+ pod_name: pod_name,
+ tooltip: "#{pod_name} (#{pod_status})",
+ track: track,
+ stable: stable?
+ }
+ end
+
+ def has_same_track?(pod)
+ pod_track = pod.dig('metadata', 'labels', 'track') || STABLE_TRACK_VALUE
+
+ pod_track == track
+ end
+
+ def metadata
+ @attributes.fetch('metadata', {})
+ end
+
+ def spec
+ @attributes.fetch('spec', {})
+ end
+
+ def status
+ @attributes.fetch('status', {})
+ end
+
+ def generation
+ metadata.fetch('generation', 0)
+ end
+
+ def observed_generation
+ status.fetch('observedGeneration', 0)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/v2/client_command.rb b/lib/gitlab/kubernetes/helm/v2/client_command.rb
index 88693a28d6c..8b15af9aeea 100644
--- a/lib/gitlab/kubernetes/helm/v2/client_command.rb
+++ b/lib/gitlab/kubernetes/helm/v2/client_command.rb
@@ -22,17 +22,6 @@ module Gitlab
def repository_update_command
'helm repo update'
end
-
- def optional_tls_flags
- return [] unless files.key?(:'ca.pem')
-
- [
- '--tls',
- '--tls-ca-cert', "#{files_dir}/ca.pem",
- '--tls-cert', "#{files_dir}/cert.pem",
- '--tls-key', "#{files_dir}/key.pem"
- ]
- end
end
end
end
diff --git a/lib/gitlab/kubernetes/helm/v2/reset_command.rb b/lib/gitlab/kubernetes/helm/v2/reset_command.rb
index 172a0884c49..00626501a9a 100644
--- a/lib/gitlab/kubernetes/helm/v2/reset_command.rb
+++ b/lib/gitlab/kubernetes/helm/v2/reset_command.rb
@@ -9,9 +9,8 @@ module Gitlab
def generate_script
super + [
- reset_helm_command,
- delete_tiller_replicaset,
- delete_tiller_clusterrolebinding
+ init_command,
+ reset_helm_command
].join("\n")
end
@@ -21,27 +20,8 @@ module Gitlab
private
- # This method can be delete once we upgrade Helm to > 12.13.0
- # https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27096#note_159695900
- #
- # Tracking this method to be removed here:
- # https://gitlab.com/gitlab-org/gitlab-foss/issues/52791#note_199374155
- def delete_tiller_replicaset
- delete_args = %w[replicaset -n gitlab-managed-apps -l name=tiller]
-
- Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
- end
-
- def delete_tiller_clusterrolebinding
- delete_args = %w[clusterrolebinding tiller-admin]
-
- Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
- end
-
def reset_helm_command
- command = %w[helm reset] + optional_tls_flags
-
- command.shelljoin
+ 'helm reset --force'
end
end
end
diff --git a/lib/gitlab/kubernetes/ingress.rb b/lib/gitlab/kubernetes/ingress.rb
new file mode 100644
index 00000000000..c5643dd670a
--- /dev/null
+++ b/lib/gitlab/kubernetes/ingress.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class Ingress
+ include Gitlab::Utils::StrongMemoize
+
+ # Canary Ingress Annotations https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary
+ ANNOTATION_KEY_CANARY = 'nginx.ingress.kubernetes.io/canary'
+ ANNOTATION_KEY_CANARY_WEIGHT = 'nginx.ingress.kubernetes.io/canary-weight'
+
+ def initialize(attributes = {})
+ @attributes = attributes
+ end
+
+ def canary?
+ strong_memoize(:is_canary) do
+ annotations.any? do |key, value|
+ key == ANNOTATION_KEY_CANARY && value == 'true'
+ end
+ end
+ end
+
+ def canary_weight
+ return unless canary?
+ return unless annotations.key?(ANNOTATION_KEY_CANARY_WEIGHT)
+
+ annotations[ANNOTATION_KEY_CANARY_WEIGHT].to_i
+ end
+
+ def name
+ metadata['name']
+ end
+
+ private
+
+ def metadata
+ @attributes.fetch('metadata', {})
+ end
+
+ def annotations
+ metadata.fetch('annotations', {})
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/rollout_instances.rb b/lib/gitlab/kubernetes/rollout_instances.rb
new file mode 100644
index 00000000000..c5dba71f505
--- /dev/null
+++ b/lib/gitlab/kubernetes/rollout_instances.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class RolloutInstances
+ include ::Gitlab::Utils::StrongMemoize
+
+ def initialize(deployments, pods)
+ @deployments = deployments
+ @pods = pods
+ end
+
+ def pod_instances
+ pods = matching_pods + extra_pending_pods
+
+ pods.sort_by(&:order).map do |pod|
+ to_hash(pod)
+ end
+ end
+
+ private
+
+ attr_reader :deployments, :pods
+
+ def matching_pods
+ strong_memoize(:matching_pods) do
+ deployment_tracks = deployments.map(&:track)
+ pods.select { |p| deployment_tracks.include?(p.track) }
+ end
+ end
+
+ def extra_pending_pods
+ wanted_instances = sum_hashes(deployments.map { |d| { d.track => d.wanted_instances } })
+ present_instances = sum_hashes(matching_pods.map { |p| { p.track => 1 } })
+ pending_instances = subtract_hashes(wanted_instances, present_instances)
+
+ pending_instances.flat_map do |track, num|
+ Array.new(num, pending_pod_for(track))
+ end
+ end
+
+ def sum_hashes(hashes)
+ hashes.reduce({}) do |memo, hash|
+ memo.merge(hash) { |_key, memo_val, hash_val| memo_val + hash_val }
+ end
+ end
+
+ def subtract_hashes(hash_a, hash_b)
+ hash_a.merge(hash_b) { |_key, val_a, val_b| [0, val_a - val_b].max }
+ end
+
+ def pending_pod_for(track)
+ ::Gitlab::Kubernetes::Pod.new({
+ 'status' => { 'phase' => 'Pending' },
+ 'metadata' => {
+ 'name' => 'Not provided',
+ 'labels' => {
+ 'track' => track
+ }
+ }
+ })
+ end
+
+ def to_hash(pod)
+ {
+ status: pod.status&.downcase,
+ pod_name: pod.name,
+ tooltip: "#{pod.name} (#{pod.status})",
+ track: pod.track,
+ stable: pod.stable?
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/rollout_status.rb b/lib/gitlab/kubernetes/rollout_status.rb
new file mode 100644
index 00000000000..e275303e650
--- /dev/null
+++ b/lib/gitlab/kubernetes/rollout_status.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ # Calculates the rollout status for a set of kubernetes deployments.
+ #
+ # A GitLab environment may be composed of several Kubernetes deployments and
+ # other resources. The rollout status sums the Kubernetes deployments
+ # together.
+ class RolloutStatus
+ attr_reader :deployments, :instances, :completion, :status, :canary_ingress
+
+ def complete?
+ completion == 100
+ end
+
+ def loading?
+ @status == :loading
+ end
+
+ def not_found?
+ @status == :not_found
+ end
+
+ def found?
+ @status == :found
+ end
+
+ def canary_ingress_exists?
+ canary_ingress.present?
+ end
+
+ def self.from_deployments(*deployments_attrs, pods_attrs: [], ingresses: [])
+ return new([], status: :not_found) if deployments_attrs.empty?
+
+ deployments = deployments_attrs.map do |attrs|
+ ::Gitlab::Kubernetes::Deployment.new(attrs, pods: pods_attrs)
+ end
+ deployments.sort_by!(&:order)
+
+ pods = pods_attrs.map do |attrs|
+ ::Gitlab::Kubernetes::Pod.new(attrs)
+ end
+
+ ingresses = ingresses.map { |ingress| ::Gitlab::Kubernetes::Ingress.new(ingress) }
+
+ new(deployments, pods: pods, ingresses: ingresses)
+ end
+
+ def self.loading
+ new([], status: :loading)
+ end
+
+ def initialize(deployments, pods: [], ingresses: [], status: :found)
+ @status = status
+ @deployments = deployments
+ @instances = RolloutInstances.new(deployments, pods).pod_instances
+ @canary_ingress = ingresses.find(&:canary?)
+
+ @completion =
+ if @instances.empty?
+ 100
+ else
+ # We downcase the pod status in Gitlab::Kubernetes::Deployment#deployment_instance
+ finished = @instances.count { |instance| instance[:status] == ::Gitlab::Kubernetes::Pod::RUNNING.downcase }
+
+ (finished / @instances.count.to_f * 100).to_i
+ end
+ end
+ end
+ end
+end