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:
Diffstat (limited to 'app/models/integrations/prometheus.rb')
-rw-r--r--app/models/integrations/prometheus.rb203
1 files changed, 203 insertions, 0 deletions
diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb
new file mode 100644
index 00000000000..54cb823d606
--- /dev/null
+++ b/app/models/integrations/prometheus.rb
@@ -0,0 +1,203 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Prometheus < BaseMonitoring
+ include PrometheusAdapter
+
+ # Access to prometheus is directly through the API
+ prop_accessor :api_url
+ prop_accessor :google_iap_service_account_json
+ prop_accessor :google_iap_audience_client_id
+ boolean_accessor :manual_configuration
+
+ # We need to allow the self-monitoring project to connect to the internal
+ # Prometheus instance.
+ # Since the internal Prometheus instance is usually a localhost URL, we need
+ # to allow localhost URLs when the following conditions are true:
+ # 1. project is the self-monitoring project.
+ # 2. api_url is the internal Prometheus URL.
+ with_options presence: true do
+ validates :api_url, public_url: true, if: ->(object) { object.manual_configuration? && !object.allow_local_api_url? }
+ validates :api_url, url: true, if: ->(object) { object.manual_configuration? && object.allow_local_api_url? }
+ end
+
+ before_save :synchronize_service_state
+
+ after_save :clear_reactive_cache!
+
+ after_commit :track_events
+
+ after_create_commit :create_default_alerts
+
+ scope :preload_project, -> { preload(:project) }
+ scope :with_clusters_with_cilium, -> { joins(project: [:clusters]).merge(Clusters::Cluster.with_available_cilium) }
+
+ def initialize_properties
+ if properties.nil?
+ self.properties = {}
+ end
+ end
+
+ def show_active_box?
+ false
+ end
+
+ def title
+ 'Prometheus'
+ end
+
+ def description
+ s_('PrometheusService|Monitor application health with Prometheus metrics and dashboards')
+ end
+
+ def self.to_param
+ 'prometheus'
+ end
+
+ def fields
+ [
+ {
+ type: 'checkbox',
+ name: 'manual_configuration',
+ title: s_('PrometheusService|Active'),
+ help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'api_url',
+ title: 'API URL',
+ placeholder: s_('PrometheusService|https://prometheus.example.com/'),
+ help: s_('PrometheusService|The Prometheus API base URL.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'google_iap_audience_client_id',
+ title: 'Google IAP Audience Client ID',
+ placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'),
+ help: s_('PrometheusService|PrometheusService|The ID of the IAP-secured resource.'),
+ autocomplete: 'off',
+ required: false
+ },
+ {
+ type: 'textarea',
+ name: 'google_iap_service_account_json',
+ title: 'Google IAP Service Account JSON',
+ placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'),
+ help: s_('PrometheusService|The contents of the credentials.json file of your service account.'),
+ required: false
+ }
+ ]
+ end
+
+ # Check we can connect to the Prometheus API
+ def test(*args)
+ prometheus_client.ping
+ { success: true, result: 'Checked API endpoint' }
+ rescue Gitlab::PrometheusClient::Error => err
+ { success: false, result: err }
+ end
+
+ def prometheus_client
+ return unless should_return_client?
+
+ options = prometheus_client_default_options.merge(
+ allow_local_requests: allow_local_api_url?
+ )
+
+ if behind_iap?
+ # Adds the Authorization header
+ options[:headers] = iap_client.apply({})
+ end
+
+ Gitlab::PrometheusClient.new(api_url, options)
+ end
+
+ def prometheus_available?
+ return false if template?
+ return false unless project
+
+ project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster|
+ cluster.integration_prometheus_available?
+ end
+ end
+
+ def allow_local_api_url?
+ allow_local_requests_from_web_hooks_and_services? ||
+ (self_monitoring_project? && internal_prometheus_url?)
+ end
+
+ def configured?
+ should_return_client?
+ end
+
+ private
+
+ delegate :allow_local_requests_from_web_hooks_and_services?, to: :current_settings, private: true
+
+ def self_monitoring_project?
+ project && project.id == current_settings.self_monitoring_project_id
+ end
+
+ def internal_prometheus_url?
+ api_url.present? && api_url == ::Gitlab::Prometheus::Internal.uri
+ end
+
+ def should_return_client?
+ api_url.present? && manual_configuration? && active? && valid?
+ end
+
+ def current_settings
+ Gitlab::CurrentSettings.current_application_settings
+ end
+
+ def synchronize_service_state
+ self.active = prometheus_available? || manual_configuration?
+
+ true
+ end
+
+ def track_events
+ if enabled_manual_prometheus?
+ Gitlab::Tracking.event('cluster:services:prometheus', 'enabled_manual_prometheus')
+ elsif disabled_manual_prometheus?
+ Gitlab::Tracking.event('cluster:services:prometheus', 'disabled_manual_prometheus')
+ end
+
+ true
+ end
+
+ def enabled_manual_prometheus?
+ manual_configuration_changed? && manual_configuration?
+ end
+
+ def disabled_manual_prometheus?
+ manual_configuration_changed? && !manual_configuration?
+ end
+
+ def create_default_alerts
+ return unless project_id
+
+ ::Prometheus::CreateDefaultAlertsWorker.perform_async(project_id)
+ end
+
+ def behind_iap?
+ manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present?
+ end
+
+ def clean_google_iap_service_account
+ return unless google_iap_service_account_json
+
+ google_iap_service_account_json
+ .then { |json| Gitlab::Json.parse(json) }
+ .except('token_credential_uri')
+ end
+
+ def iap_client
+ @iap_client ||= Google::Auth::Credentials
+ .new(clean_google_iap_service_account, target_audience: google_iap_audience_client_id)
+ .client
+ end
+ end
+end