diff options
-rw-r--r-- | app/models/clusters/cluster.rb | 3 | ||||
-rw-r--r-- | app/models/environment.rb | 12 | ||||
-rw-r--r-- | app/models/project_services/prometheus_service.rb | 22 | ||||
-rw-r--r-- | lib/gitlab/prometheus_client.rb | 2 | ||||
-rw-r--r-- | spec/models/project_services/prometheus_service_spec.rb | 127 |
5 files changed, 147 insertions, 19 deletions
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 5ecbd4cbceb..8678f70f78c 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -49,6 +49,9 @@ module Clusters scope :enabled, -> { where(enabled: true) } scope :disabled, -> { where(enabled: false) } + scope :for_environment, -> (env) { where(environment_scope: ['*', '', env.slug]) } + scope :for_all_environments, -> { where(environment_scope: ['*', '']) } + def status_name if provider provider.status_name diff --git a/app/models/environment.rb b/app/models/environment.rb index d895550784d..bf69b4c50f0 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -163,18 +163,6 @@ class Environment < ActiveRecord::Base end end - def enabled_clusters - slug = self.slug - result = project.clusters.enabled.select do |cluster| - scope = cluster.environment_scope || '*' - File.fnmatch(scope, slug) - end - - # sort results by descending order based on environment_scope being longer - # thus more closely matching environment slug - result.sort_by { |cluster| cluster.environment_scope.length }.reverse! - end - def slug super.presence || generate_slug end diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb index 2fb94c1facb..580e2c01aaa 100644 --- a/app/models/project_services/prometheus_service.rb +++ b/app/models/project_services/prometheus_service.rb @@ -116,31 +116,41 @@ class PrometheusService < MonitoringService { success: false, result: err.message } end - def client(environment_id) + def client(environment_id = nil) if manual_configuration? Gitlab::PrometheusClient.new(RestClient::Resource.new(api_url)) else cluster = cluster_with_prometheus(environment_id) raise Gitlab::PrometheusError, "couldn't find cluster with Prometheus installed" unless cluster + rest_client = client_from_cluster(cluster) - Gitlab::PrometheusClient.new(cluster.application_prometheus.proxy_client) + raise Gitlab::PrometheusError, "couldn't create proxy Prometheus client" unless rest_client + Gitlab::PrometheusClient.new(rest_client) end end def prometheus_installed? - cluster_with_prometheus.present? + project.clusters.enabled.any? { |cluster| cluster.application_prometheus&.installed? } end private def cluster_with_prometheus(environment_id = nil) clusters = if environment_id - ::Environment.find_by(id: environment_id).try(:enabled_clusters) || [] + ::Environment.find_by(id: environment_id).try do |env| + # sort results by descending order based on environment_scope being longer + # thus more closely matching environment slug + project.clusters.enabled.for_environment(env).sort_by { |c| c.environment_scope&.length }.reverse! + end else - project.clusters.enabled.select { |c| c.environment_scope == '*' || c.environment_scope == '' } + project.clusters.enabled.for_all_environments end - clusters.detect { |cluster| cluster.application_prometheus&.installed? } + clusters&.detect { |cluster| cluster.application_prometheus&.installed? } + end + + def client_from_cluster(cluster) + cluster.application_prometheus.proxy_client end def rename_data_to_metrics(metrics) diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb index 79f66b42c21..8264501b1ae 100644 --- a/lib/gitlab/prometheus_client.rb +++ b/lib/gitlab/prometheus_client.rb @@ -6,7 +6,7 @@ module Gitlab attr_reader :rest_client, :headers def initialize(rest_client) - @rest_client = rest_client || RestClient::Resource.new(api_url) + @rest_client = rest_client end def ping diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb index bf39e8d7a39..3cbd0bb75f7 100644 --- a/spec/models/project_services/prometheus_service_spec.rb +++ b/spec/models/project_services/prometheus_service_spec.rb @@ -8,6 +8,8 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do let(:service) { project.prometheus_service } let(:environment_query) { Gitlab::Prometheus::Queries::EnvironmentQuery } + subject { project.prometheus_service } + describe "Associations" do it { is_expected.to belong_to :project } end @@ -132,4 +134,129 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do end end end + + describe '#client' do + context 'manual configuration is enabled' do + let(:api_url) { 'http://some_url' } + before do + subject.manual_configuration = true + subject.api_url = api_url + end + + it 'returns simple rest client from api_url' do + expect(subject.client).to be_instance_of(Gitlab::PrometheusClient) + expect(subject.client.rest_client.url).to eq(api_url) + end + end + + context 'manual configuration is disabled' do + let!(:cluster_for_all) { create(:cluster, environment_scope: '*', projects: [project]) } + let!(:cluster_for_dev) { create(:cluster, environment_scope: 'dev', projects: [project]) } + + let!(:prometheus_for_dev) { create(:clusters_applications_prometheus, :installed, cluster: cluster_for_dev) } + let(:proxy_client) { double('proxy_client') } + + before do + subject.manual_configuration = false + end + + context 'with cluster for all environments with prometheus installed' do + let!(:prometheus_for_all) { create(:clusters_applications_prometheus, :installed, cluster: cluster_for_all) } + + context 'without environment supplied' do + it 'returns client handling all environments' do + expect(subject).to receive(:client_from_cluster).with(cluster_for_all).and_return(proxy_client).twice + + expect(subject.client).to be_instance_of(Gitlab::PrometheusClient) + expect(subject.client.rest_client).to eq(proxy_client) + end + end + + context 'with dev environment supplied' do + let!(:environment) { create(:environment, project: project, name: 'dev') } + + it 'returns dev cluster client' do + expect(subject).to receive(:client_from_cluster).with(cluster_for_dev).and_return(proxy_client).twice + + expect(subject.client(environment.id)).to be_instance_of(Gitlab::PrometheusClient) + expect(subject.client(environment.id).rest_client).to eq(proxy_client) + end + end + + context 'with prod environment supplied' do + let!(:environment) { create(:environment, project: project, name: 'prod') } + + it 'returns dev cluster client' do + expect(subject).to receive(:client_from_cluster).with(cluster_for_all).and_return(proxy_client).twice + + expect(subject.client(environment.id)).to be_instance_of(Gitlab::PrometheusClient) + expect(subject.client(environment.id).rest_client).to eq(proxy_client) + end + end + end + + context 'with cluster for all environments without prometheus installed' do + context 'without environment supplied' do + it 'raises PrometheusError because cluster was not found' do + expect{subject.client}.to raise_error(Gitlab::PrometheusError, /couldn't find cluster with Prometheus installed/) + end + end + + context 'with dev environment supplied' do + let!(:environment) { create(:environment, project: project, name: 'dev') } + + it 'returns dev cluster client' do + expect(subject).to receive(:client_from_cluster).with(cluster_for_dev).and_return(proxy_client).twice + + expect(subject.client(environment.id)).to be_instance_of(Gitlab::PrometheusClient) + expect(subject.client(environment.id).rest_client).to eq(proxy_client) + end + end + + context 'with prod environment supplied' do + let!(:environment) { create(:environment, project: project, name: 'prod') } + + it 'raises PrometheusError because cluster was not found' do + expect{subject.client}.to raise_error(Gitlab::PrometheusError, /couldn't find cluster with Prometheus installed/) + end + end + end + end + end + + describe '#prometheus_installed?' do + subject { project.prometheus_service } + + context 'clusters with installed prometheus' do + let!(:cluster) { create(:cluster, projects: [project]) } + let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) } + + it 'returns true' do + expect(subject.prometheus_installed?).to be(true) + end + end + + context 'clusters without prometheus installed' do + let(:cluster) { create(:cluster, projects: [project]) } + let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) } + + it 'returns false' do + expect(subject.prometheus_installed?).to be(false) + end + end + + context 'clusters without prometheus' do + let(:cluster) { create(:cluster, projects: [project]) } + + it 'returns false' do + expect(subject.prometheus_installed?).to be(false) + end + end + + context 'no clusters' do + it 'returns false' do + expect(subject.prometheus_installed?).to be(false) + end + end + end end |