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-03-24 12:09:25 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-24 12:09:25 +0300
commit6f7881ee9dcec34141a8f34fc814b56b366d2b48 (patch)
tree25f72a06874b32b1049b79a9d7f4f1b7bca43b9b /app/services/clusters
parent8c8bf44fa64f98114f7439f751c92d59a44b3218 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/clusters')
-rw-r--r--app/services/clusters/applications/check_upgrade_progress_service.rb71
-rw-r--r--app/services/clusters/applications/prometheus_config_service.rb155
-rw-r--r--app/services/clusters/applications/prometheus_update_service.rb35
-rw-r--r--app/services/clusters/applications/schedule_update_service.rb38
4 files changed, 299 insertions, 0 deletions
diff --git a/app/services/clusters/applications/check_upgrade_progress_service.rb b/app/services/clusters/applications/check_upgrade_progress_service.rb
new file mode 100644
index 00000000000..8502ea69f27
--- /dev/null
+++ b/app/services/clusters/applications/check_upgrade_progress_service.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class CheckUpgradeProgressService < BaseHelmService
+ def execute
+ return unless app.updating?
+
+ case phase
+ when ::Gitlab::Kubernetes::Pod::SUCCEEDED
+ on_success
+ when ::Gitlab::Kubernetes::Pod::FAILED
+ on_failed
+ else
+ check_timeout
+ end
+ rescue ::Kubeclient::HttpError => e
+ app.make_update_errored!("Kubernetes error: #{e.message}") unless app.update_errored?
+ end
+
+ private
+
+ def on_success
+ app.make_installed!
+ ensure
+ remove_pod
+ end
+
+ def on_failed
+ app.make_update_errored!(errors || 'Update silently failed')
+ ensure
+ remove_pod
+ end
+
+ def check_timeout
+ if timed_out?
+ begin
+ app.make_update_errored!('Update timed out')
+ ensure
+ remove_pod
+ end
+ else
+ ::ClusterWaitForAppUpdateWorker.perform_in(
+ ::ClusterWaitForAppUpdateWorker::INTERVAL, app.name, app.id)
+ end
+ end
+
+ def timed_out?
+ Time.now.utc - app.updated_at.to_time.utc > ::ClusterWaitForAppUpdateWorker::TIMEOUT
+ end
+
+ def remove_pod
+ helm_api.delete_pod!(pod_name)
+ rescue
+ # no-op
+ end
+
+ def phase
+ helm_api.status(pod_name)
+ end
+
+ def errors
+ helm_api.log(pod_name)
+ end
+
+ def pod_name
+ @pod_name ||= patch_command.pod_name
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/prometheus_config_service.rb b/app/services/clusters/applications/prometheus_config_service.rb
new file mode 100644
index 00000000000..34d44ab881e
--- /dev/null
+++ b/app/services/clusters/applications/prometheus_config_service.rb
@@ -0,0 +1,155 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class PrometheusConfigService
+ def initialize(project, cluster, app)
+ @project = project
+ @cluster = cluster
+ @app = app
+ end
+
+ def execute(config = {})
+ if has_alerts?
+ generate_alert_manager(config)
+ else
+ reset_alert_manager(config)
+ end
+ end
+
+ private
+
+ attr_reader :project, :cluster, :app
+
+ def reset_alert_manager(config)
+ config = set_alert_manager_enabled(config, false)
+ config.delete('alertmanagerFiles')
+ config['serverFiles'] ||= {}
+ config['serverFiles']['alerts'] = {}
+
+ config
+ end
+
+ def generate_alert_manager(config)
+ config = set_alert_manager_enabled(config, true)
+ config = set_alert_manager_files(config)
+
+ set_alert_manager_groups(config)
+ end
+
+ def set_alert_manager_enabled(config, enabled)
+ config['alertmanager'] ||= {}
+ config['alertmanager']['enabled'] = enabled
+
+ config
+ end
+
+ def set_alert_manager_files(config)
+ config['alertmanagerFiles'] = {
+ 'alertmanager.yml' => {
+ 'receivers' => alert_manager_receivers_params,
+ 'route' => alert_manager_route_params
+ }
+ }
+
+ config
+ end
+
+ def set_alert_manager_groups(config)
+ config['serverFiles'] ||= {}
+ config['serverFiles']['alerts'] ||= {}
+ config['serverFiles']['alerts']['groups'] ||= []
+
+ environments_with_alerts.each do |env_name, alerts|
+ index = config['serverFiles']['alerts']['groups'].find_index do |group|
+ group['name'] == env_name
+ end
+
+ if index
+ config['serverFiles']['alerts']['groups'][index]['rules'] = alerts
+ else
+ config['serverFiles']['alerts']['groups'] << {
+ 'name' => env_name,
+ 'rules' => alerts
+ }
+ end
+ end
+
+ config
+ end
+
+ def alert_manager_receivers_params
+ [
+ {
+ 'name' => 'gitlab',
+ 'webhook_configs' => [
+ {
+ 'url' => notify_url,
+ 'send_resolved' => true,
+ 'http_config' => {
+ 'bearer_token' => alert_manager_token
+ }
+ }
+ ]
+ }
+ ]
+ end
+
+ def alert_manager_token
+ app.generate_alert_manager_token!
+
+ app.alert_manager_token
+ end
+
+ def alert_manager_route_params
+ {
+ 'receiver' => 'gitlab',
+ 'group_wait' => '30s',
+ 'group_interval' => '5m',
+ 'repeat_interval' => '4h'
+ }
+ end
+
+ def notify_url
+ ::Gitlab::Routing.url_helpers
+ .notify_project_prometheus_alerts_url(project, format: :json)
+ end
+
+ def has_alerts?
+ environments_with_alerts.values.flatten(1).any?
+ end
+
+ def environments_with_alerts
+ @environments_with_alerts ||=
+ environments.each_with_object({}) do |environment, hash|
+ name = rule_name(environment)
+ hash[name] = alerts(environment)
+ end
+ end
+
+ def rule_name(environment)
+ "#{environment.name}.rules"
+ end
+
+ def alerts(environment)
+ variables = Gitlab::Prometheus::QueryVariables.call(environment)
+ alerts = Projects::Prometheus::AlertsFinder
+ .new(environment: environment)
+ .execute
+
+ alerts.map do |alert|
+ substitute_query_variables(alert.to_param, variables)
+ end
+ end
+
+ def substitute_query_variables(hash, variables)
+ hash['expr'] %= variables
+ hash
+ end
+
+ def environments
+ project.environments_for_scope(cluster.environment_scope)
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/prometheus_update_service.rb b/app/services/clusters/applications/prometheus_update_service.rb
new file mode 100644
index 00000000000..437f6ab1202
--- /dev/null
+++ b/app/services/clusters/applications/prometheus_update_service.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class PrometheusUpdateService < BaseHelmService
+ attr_accessor :project
+
+ def initialize(app, project)
+ super(app)
+ @project = project
+ end
+
+ def execute
+ app.make_updating!
+
+ helm_api.update(patch_command(values))
+
+ ::ClusterWaitForAppUpdateWorker.perform_in(::ClusterWaitForAppUpdateWorker::INTERVAL, app.name, app.id)
+ rescue ::Kubeclient::HttpError => ke
+ app.make_update_errored!("Kubernetes error: #{ke.message}")
+ rescue StandardError => e
+ app.make_update_errored!(e.message)
+ end
+
+ private
+
+ def values
+ PrometheusConfigService
+ .new(project, cluster, app)
+ .execute
+ .to_yaml
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/schedule_update_service.rb b/app/services/clusters/applications/schedule_update_service.rb
new file mode 100644
index 00000000000..b7639c771a8
--- /dev/null
+++ b/app/services/clusters/applications/schedule_update_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class ScheduleUpdateService
+ BACKOFF_DELAY = 2.minutes
+
+ attr_accessor :application, :project
+
+ def initialize(application, project)
+ @application = application
+ @project = project
+ end
+
+ def execute
+ return unless application
+
+ if recently_scheduled?
+ worker_class.perform_in(BACKOFF_DELAY, application.name, application.id, project.id, Time.now)
+ else
+ worker_class.perform_async(application.name, application.id, project.id, Time.now)
+ end
+ end
+
+ private
+
+ def worker_class
+ ::ClusterUpdateAppWorker
+ end
+
+ def recently_scheduled?
+ return false unless application.last_update_started_at
+
+ application.last_update_started_at.utc >= Time.now.utc - BACKOFF_DELAY
+ end
+ end
+ end
+end