diff options
Diffstat (limited to 'spec/lib/gitlab/metrics/dashboard')
9 files changed, 270 insertions, 38 deletions
diff --git a/spec/lib/gitlab/metrics/dashboard/defaults_spec.rb b/spec/lib/gitlab/metrics/dashboard/defaults_spec.rb index 420b246b3f5..dd61f8ebc4d 100644 --- a/spec/lib/gitlab/metrics/dashboard/defaults_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/defaults_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::Defaults do +RSpec.describe Gitlab::Metrics::Dashboard::Defaults do it { is_expected.to be_const_defined(:DEFAULT_PANEL_TYPE) } it { is_expected.to be_const_defined(:DEFAULT_PANEL_WEIGHT) } end diff --git a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb index 2703339d89c..60e1e29d4c5 100644 --- a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_caching do +RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_caching do include MetricsDashboardHelpers let_it_be(:project) { create(:project) } @@ -118,7 +118,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi end describe '.find_raw' do - let(:dashboard) { YAML.load_file(Rails.root.join('config', 'prometheus', 'common_metrics.yml')) } + let(:dashboard) { load_dashboard_yaml(File.read(Rails.root.join('config', 'prometheus', 'common_metrics.yml'))) } let(:params) { {} } subject { described_class.find_raw(project, **params) } @@ -132,7 +132,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi end context 'when an existing project dashboard is specified' do - let(:dashboard) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')) } + let(:dashboard) { load_sample_dashboard } let(:params) { { dashboard_path: '.gitlab/dashboards/test.yml' } } let(:project) { project_with_dashboard(params[:dashboard_path]) } @@ -142,7 +142,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi describe '.find_all_paths' do let(:all_dashboard_paths) { described_class.find_all_paths(project) } - let(:system_dashboard) { { path: system_dashboard_path, display_name: 'Default dashboard', default: true, system_dashboard: true } } + let(:system_dashboard) { { path: system_dashboard_path, display_name: 'Default dashboard', default: true, system_dashboard: true, out_of_the_box_dashboard: true } } it 'includes only the system dashboard by default' do expect(all_dashboard_paths).to eq([system_dashboard]) @@ -153,7 +153,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi let(:project) { project_with_dashboard(dashboard_path) } it 'includes system and project dashboards' do - project_dashboard = { path: dashboard_path, display_name: 'test.yml', default: false, system_dashboard: false } + project_dashboard = { path: dashboard_path, display_name: 'test.yml', default: false, system_dashboard: false, out_of_the_box_dashboard: false } expect(all_dashboard_paths).to contain_exactly(system_dashboard, project_dashboard) end @@ -165,7 +165,8 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi path: self_monitoring_dashboard_path, display_name: 'Default dashboard', default: true, - system_dashboard: false + system_dashboard: false, + out_of_the_box_dashboard: true } end let(:dashboard_path) { '.gitlab/dashboards/test.yml' } @@ -180,7 +181,8 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi path: dashboard_path, display_name: 'test.yml', default: false, - system_dashboard: false + system_dashboard: false, + out_of_the_box_dashboard: false } expect(all_dashboard_paths).to contain_exactly(self_monitoring_dashboard, project_dashboard) diff --git a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb index 7250cefb9ff..7f7070dfafb 100644 --- a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb @@ -2,10 +2,12 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::Processor do +RSpec.describe Gitlab::Metrics::Dashboard::Processor do + include MetricsDashboardHelpers + let(:project) { build(:project) } let(:environment) { create(:environment, project: project) } - let(:dashboard_yml) { YAML.load_file('spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml') } + let(:dashboard_yml) { load_sample_dashboard } describe 'process' do let(:sequence) do @@ -13,7 +15,7 @@ describe Gitlab::Metrics::Dashboard::Processor do Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter, Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter, Gitlab::Metrics::Dashboard::Stages::CustomMetricsDetailsInserter, - Gitlab::Metrics::Dashboard::Stages::EndpointInserter, + Gitlab::Metrics::Dashboard::Stages::MetricEndpointInserter, Gitlab::Metrics::Dashboard::Stages::Sorter, Gitlab::Metrics::Dashboard::Stages::AlertsInserter, Gitlab::Metrics::Dashboard::Stages::PanelIdsInserter, @@ -98,7 +100,7 @@ describe Gitlab::Metrics::Dashboard::Processor do let(:sequence) do [ Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter, - Gitlab::Metrics::Dashboard::Stages::EndpointInserter, + Gitlab::Metrics::Dashboard::Stages::MetricEndpointInserter, Gitlab::Metrics::Dashboard::Stages::Sorter ] end @@ -202,27 +204,6 @@ describe Gitlab::Metrics::Dashboard::Processor do it_behaves_like 'errors with message', 'Each "metric" must define one of :query or :query_range' end - - describe 'validating links' do - context 'when the links contain a blocked url' do - let(:dashboard_yml_links) do - [{ 'url' => 'http://1.1.1.1.1' }, { 'url' => 'https://gitlab.com' }] - end - - let(:expected) do - [{ url: '' }, { url: 'https://gitlab.com' }] - end - - before do - stub_env('RSPEC_ALLOW_INVALID_URLS', 'false') - dashboard_yml['links'] = dashboard_yml_links - end - - it 'replaces the blocked url with an empty string' do - expect(dashboard[:links]).to eq(expected) - end - end - end end private diff --git a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb index 245c98cdd00..f3c8209e0b6 100644 --- a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::ServiceSelector do +RSpec.describe Gitlab::Metrics::Dashboard::ServiceSelector do include MetricsDashboardHelpers describe '#call' do @@ -109,6 +109,46 @@ describe Gitlab::Metrics::Dashboard::ServiceSelector do it { is_expected.to be Metrics::Dashboard::TransientEmbedService } end + + context 'when cluster is provided' do + let(:arguments) { { cluster: "some cluster" } } + + it { is_expected.to be Metrics::Dashboard::ClusterDashboardService } + end + + context 'when cluster is provided and embedded is not true' do + let(:arguments) { { cluster: "some cluster", embedded: 'false' } } + + it { is_expected.to be Metrics::Dashboard::ClusterDashboardService } + end + + context 'when cluster dashboard_path is provided' do + let(:arguments) { { dashboard_path: ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH } } + + it { is_expected.to be Metrics::Dashboard::ClusterDashboardService } + end + + context 'when cluster is provided and embed params' do + let(:arguments) do + { + cluster: "some cluster", + embedded: 'true', + cluster_type: 'project', + format: :json, + group: 'Food metrics', + title: 'Pizza Consumption', + y_label: 'Slice Count' + } + end + + it { is_expected.to be Metrics::Dashboard::ClusterMetricsEmbedService } + end + + context 'when metrics embed is for an alert' do + let(:arguments) { { embedded: true, prometheus_alert_id: 5 } } + + it { is_expected.to be Metrics::Dashboard::GitlabAlertEmbedService } + end end end end diff --git a/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb index 5d4bd4512e3..8a236f72a60 100644 --- a/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::Stages::GrafanaFormatter do +RSpec.describe Gitlab::Metrics::Dashboard::Stages::GrafanaFormatter do include GrafanaApiHelpers let_it_be(:namespace) { create(:namespace, name: 'foo') } diff --git a/spec/lib/gitlab/metrics/dashboard/stages/panel_ids_inserter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/panel_ids_inserter_spec.rb index 6124f471e39..7a3a9021f86 100644 --- a/spec/lib/gitlab/metrics/dashboard/stages/panel_ids_inserter_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/stages/panel_ids_inserter_spec.rb @@ -2,7 +2,9 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::Stages::PanelIdsInserter do +RSpec.describe Gitlab::Metrics::Dashboard::Stages::PanelIdsInserter do + include MetricsDashboardHelpers + let(:project) { build_stubbed(:project) } def fetch_panel_ids(dashboard_hash) @@ -12,7 +14,7 @@ describe Gitlab::Metrics::Dashboard::Stages::PanelIdsInserter do describe '#transform!' do subject(:transform!) { described_class.new(project, dashboard, nil).transform! } - let(:dashboard) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')).deep_symbolize_keys } + let(:dashboard) { load_sample_dashboard.deep_symbolize_keys } context 'when dashboard panels are present' do it 'assigns unique ids to each panel using PerformanceMonitoring::PrometheusPanel', :aggregate_failures do diff --git a/spec/lib/gitlab/metrics/dashboard/stages/url_validator_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/url_validator_spec.rb new file mode 100644 index 00000000000..83cf161c4e2 --- /dev/null +++ b/spec/lib/gitlab/metrics/dashboard/stages/url_validator_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Metrics::Dashboard::Stages::UrlValidator do + let(:project) { build_stubbed(:project) } + + describe '#transform!' do + context 'when the links contain a blocked url' do + let(:dashboard) do + { + dashboard: "Test Dashboard", + links: [ + { url: "http://1.1.1.1.1" }, + { url: "https://gitlab.com" }, + { url: "http://0.0.0.0" } + ], + panel_groups: [ + { + group: "Group A", + panels: [ + { + title: "Super Chart A1", + type: "area-chart", + y_label: "y_label", + metrics: [ + { + id: "metric_a1", + query_range: "query", + unit: "unit", + label: "Legend Label" + } + ], + links: [ + { url: "http://1.1.1.1.1" }, + { url: "https://gitlab.com" }, + { url: "http://0.0.0.0" } + ] + } + ] + } + ] + } + end + + let(:expected) do + [{ url: '' }, { url: 'https://gitlab.com' }, { url: 'http://0.0.0.0' }] + end + + let(:transform!) { described_class.new(project, dashboard, nil).transform! } + + before do + stub_env('RSPEC_ALLOW_INVALID_URLS', 'false') + stub_application_setting(allow_local_requests_from_web_hooks_and_services: true) + end + + context 'dashboard related links' do + it 'replaces the blocked url with an empty string' do + transform! + + expect(dashboard[:links]).to eq(expected) + end + end + + context 'chart links' do + it 'replaces the blocked url with an empty string' do + transform! + + result = dashboard.dig(:panel_groups, 0, :panels, 0, :links) + expect(result).to eq(expected) + end + end + + context 'when local requests are not allowed' do + before do + stub_application_setting(allow_local_requests_from_web_hooks_and_services: false) + end + + let(:expected) do + [{ url: '' }, { url: 'https://gitlab.com' }, { url: '' }] + end + + it 'replaces the blocked url with an empty string' do + transform! + + expect(dashboard[:links]).to eq(expected) + end + end + + context 'when the links are an array of strings instead of hashes' do + before do + dashboard[:links] = dashboard[:links].map(&:values) + end + + it 'prevents an invalid link definition from erroring out' do + expect { transform! }.not_to raise_error + end + end + end + end +end diff --git a/spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb new file mode 100644 index 00000000000..9303ff981fb --- /dev/null +++ b/spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Metrics::Dashboard::Stages::VariableEndpointInserter do + include MetricsDashboardHelpers + + let(:project) { build_stubbed(:project) } + let(:environment) { build_stubbed(:environment, project: project) } + + describe '#transform!' do + subject(:transform!) { described_class.new(project, dashboard, environment: environment).transform! } + + let(:dashboard) { load_sample_dashboard.deep_symbolize_keys } + + context 'when dashboard variables are present' do + it 'assigns prometheus_endpoint_path to metric_label_values variable type' do + endpoint_path = Gitlab::Routing.url_helpers.prometheus_api_project_environment_path( + project, + environment, + proxy_path: :series, + match: ['backend:haproxy_backend_availability:ratio{env="{{env}}"}'] + ) + + transform! + + expect( + dashboard.dig(:templating, :variables, :metric_label_values_variable, :options) + ).to include(prometheus_endpoint_path: endpoint_path) + end + + it 'does not modify other variable types' do + original_text_variable = dashboard[:templating][:variables][:text_variable_full_syntax].deep_dup + + transform! + + expect(dashboard[:templating][:variables][:text_variable_full_syntax]).to eq(original_text_variable) + end + + context 'when variable does not have the required series_selector' do + it 'adds prometheus_endpoint_path without match parameter' do + dashboard[:templating][:variables][:metric_label_values_variable][:options].delete(:series_selector) + endpoint_path = Gitlab::Routing.url_helpers.prometheus_api_project_environment_path( + project, + environment, + proxy_path: :series + ) + + transform! + + expect( + dashboard.dig(:templating, :variables, :metric_label_values_variable, :options) + ).to include(prometheus_endpoint_path: endpoint_path) + end + end + end + + context 'when no variables are present' do + it 'does not fail' do + dashboard.delete(:templating) + + expect { transform! }.not_to raise_error + end + end + + context 'with no environment' do + subject(:transform!) { described_class.new(project, dashboard, {}).transform! } + + it 'raises error' do + expect { transform! }.to raise_error( + Gitlab::Metrics::Dashboard::Errors::DashboardProcessingError, + 'Environment is required for Stages::VariableEndpointInserter' + ) + end + end + end +end diff --git a/spec/lib/gitlab/metrics/dashboard/url_spec.rb b/spec/lib/gitlab/metrics/dashboard/url_spec.rb index 75f9f99c8a6..56556423b05 100644 --- a/spec/lib/gitlab/metrics/dashboard/url_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/url_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Gitlab::Metrics::Dashboard::Url do +RSpec.describe Gitlab::Metrics::Dashboard::Url do include Gitlab::Routing.url_helpers describe '#metrics_regex' do @@ -46,6 +46,35 @@ describe Gitlab::Metrics::Dashboard::Url do end end + describe '#clusters_regex' do + let(:url) do + Gitlab::Routing.url_helpers.namespace_project_cluster_url( + 'foo', + 'bar', + '1', + group: 'Cluster Health', + title: 'Memory Usage', + y_label: 'Memory 20(GiB)', + anchor: 'title' + ) + end + + let(:expected_params) do + { + 'url' => url, + 'namespace' => 'foo', + 'project' => 'bar', + 'cluster_id' => '1', + 'query' => '?group=Cluster+Health&title=Memory+Usage&y_label=Memory+20%28GiB%29', + 'anchor' => '#title' + } + end + + subject { described_class.clusters_regex } + + it_behaves_like 'regex which matches url when expected' + end + describe '#grafana_regex' do let(:url) do namespace_project_grafana_api_metrics_dashboard_url( |