diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 1325a2682143fca2400f914eca455e1d11f63401..27136c7289fa8f97557f2f26c1ea2dd9f9003d40 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -117,7 +117,10 @@
-
+
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue
index ea5c24efaf9a91dc4649935332f41fed1223462a..9e67a6f2146543a379762e5962c4af3d8e9d5a38 100644
--- a/app/assets/javascripts/monitoring/components/graph.vue
+++ b/app/assets/javascripts/monitoring/components/graph.vue
@@ -52,6 +52,16 @@
type: String,
required: true,
},
+ showLegend: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ smallGraph: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
@@ -130,7 +140,7 @@
const breakpointSize = bp.getBreakpointSize();
const query = this.graphData.queries[0];
this.margin = measurements.large.margin;
- if (breakpointSize === 'xs' || breakpointSize === 'sm') {
+ if (this.smallGraph || breakpointSize === 'xs' || breakpointSize === 'sm') {
this.graphHeight = 300;
this.margin = measurements.small.margin;
this.measurements = measurements.small;
@@ -182,7 +192,9 @@
this.graphHeightOffset,
);
- if (this.timeSeries.length > 3) {
+ if (!this.showLegend) {
+ this.baseGraphHeight -= 50;
+ } else if (this.timeSeries.length > 3) {
this.baseGraphHeight = this.baseGraphHeight += (this.timeSeries.length - 3) * 20;
}
@@ -255,6 +267,7 @@
:time-series="timeSeries"
:unit-of-display="unitOfDisplay"
:current-data-index="currentDataIndex"
+ :show-legend-group="showLegend"
/>
diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue
index 079351a69af6ea20799c2afc13433f99bf45872e..f71cf614552df01047b65830a1388db8b7befe08 100644
--- a/app/assets/javascripts/monitoring/components/graph_group.vue
+++ b/app/assets/javascripts/monitoring/components/graph_group.vue
@@ -5,12 +5,20 @@
type: String,
required: true,
},
+ showPanels: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
};
-
+
{{ name }}
@@ -18,4 +26,10 @@
+
+
+
diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index c3b0ef7e9ca1ff1258c9ab1a6a84719e22c8dd29..41270e015d49390e96af8c18974e382207999419 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -1,7 +1,22 @@
import Vue from 'vue';
+import { convertPermissionToBoolean } from '~/lib/utils/common_utils';
import Dashboard from './components/dashboard.vue';
-export default () => new Vue({
- el: '#prometheus-graphs',
- render: createElement => createElement(Dashboard),
-});
+export default () => {
+ const el = document.getElementById('prometheus-graphs');
+
+ if (el && el.dataset) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render(createElement) {
+ return createElement(Dashboard, {
+ props: {
+ ...el.dataset,
+ hasMetrics: convertPermissionToBoolean(el.dataset.hasMetrics),
+ },
+ });
+ },
+ });
+ }
+};
diff --git a/app/assets/javascripts/monitoring/services/monitoring_service.js b/app/assets/javascripts/monitoring/services/monitoring_service.js
index e230a06cd8c540f988af33ad51499227d9e23f89..6fcca36d2fad2d77228f5f70c491b4d459d11182 100644
--- a/app/assets/javascripts/monitoring/services/monitoring_service.js
+++ b/app/assets/javascripts/monitoring/services/monitoring_service.js
@@ -40,6 +40,9 @@ export default class MonitoringService {
}
getDeploymentData() {
+ if (!this.deploymentEndpoint) {
+ return Promise.resolve([]);
+ }
return backOffRequest(() => axios.get(this.deploymentEndpoint))
.then(resp => resp.data)
.then((response) => {
diff --git a/app/assets/javascripts/pages/projects/environments/index.js b/app/assets/javascripts/pages/projects/environments/index/index.js
similarity index 100%
rename from app/assets/javascripts/pages/projects/environments/index.js
rename to app/assets/javascripts/pages/projects/environments/index/index.js
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 3952af434e19c1b1e671e40c1b9f4175e517aeb9..ed3da2cd3d1177f49b2fbad4fc5eb77149a5f39c 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -529,7 +529,8 @@
}
> text {
- font-size: 12px;
+ fill: $theme-gray-600;
+ font-size: 10px;
}
}
@@ -573,3 +574,17 @@
}
}
}
+
+// EE-only
+.cluster-health-graphs {
+ .prometheus-state {
+ .state-svg img {
+ max-height: 120px;
+ }
+
+ .state-description,
+ .state-button {
+ display: none;
+ }
+ }
+}
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index d58039b7d42cba0bb8fc47e95a1fa811f1f429b3..e15d4aac318bde62f98b3a0e1523d1137b796a76 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -64,6 +64,22 @@ def destroy
end
end
+ def metrics
+ return render_404 unless prometheus_adapter&.can_query?
+
+ respond_to do |format|
+ format.json do
+ metrics = prometheus_adapter.query(:cluster) || {}
+
+ if metrics.any?
+ render json: metrics
+ else
+ head :no_content
+ end
+ end
+ end
+ end
+
private
def cluster
@@ -71,6 +87,12 @@ def cluster
.present(current_user: current_user)
end
+ def prometheus_adapter
+ return unless cluster&.application_prometheus&.installed?
+
+ cluster.application_prometheus
+ end
+
def update_params
if cluster.managed?
params.require(:cluster).permit(
diff --git a/app/views/projects/clusters/show.html.haml b/app/views/projects/clusters/show.html.haml
index 2ee0eafcf1af341df963ac2ce9360881d331a798..04acb979b49dff6d5b335e04851044376f1f9375 100644
--- a/app/views/projects/clusters/show.html.haml
+++ b/app/views/projects/clusters/show.html.haml
@@ -22,6 +22,10 @@
.js-cluster-application-notice
.flash-container
+ -# EE-specific
+ - if @cluster.project.feature_available?(:cluster_health)
+ = render 'health'
+
%section.settings.no-animate.expanded#cluster-integration
= render 'banner'
= render 'integration_form'
diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml
index 9d9759ebc5fb140d27cccba33c431aedeb9cf03e..c151b5acdf7256d3c221f384e5545fbeba3761f7 100644
--- a/app/views/projects/environments/metrics.html.haml
+++ b/app/views/projects/environments/metrics.html.haml
@@ -15,7 +15,8 @@
"empty-getting-started-svg-path": image_path('illustrations/monitoring/getting_started.svg'),
"empty-loading-svg-path": image_path('illustrations/monitoring/loading.svg'),
"empty-unable-to-connect-svg-path": image_path('illustrations/monitoring/unable_to_connect.svg'),
- "additional-metrics": additional_metrics_project_environment_path(@project, @environment, format: :json),
+ "metrics-endpoint": additional_metrics_project_environment_path(@project, @environment, format: :json),
+ "deployment-endpoint": project_environment_deployments_path(@project, @environment, format: :json),
"project-path": project_path(@project),
"tags-path": project_tags_path(@project),
- "has-metrics": "#{@environment.has_metrics?}", deployment_endpoint: project_environment_deployments_path(@project, @environment, format: :json) } }
+ "has-metrics": "#{@environment.has_metrics?}" } }
diff --git a/config/prometheus/cluster_metrics.yml b/config/prometheus/cluster_metrics.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cb4735f8856f8d4f35efa6765e2b933d7cfaaf07
--- /dev/null
+++ b/config/prometheus/cluster_metrics.yml
@@ -0,0 +1,25 @@
+- group: Cluster Health
+ priority: 1
+ metrics:
+ - title: "CPU Usage"
+ y_label: "CPU"
+ required_metrics: ['container_cpu_usage_seconds_total']
+ weight: 1
+ queries:
+ - query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{id="/"}[15m])) by (job)) without (job)'
+ label: Usage
+ unit: "cores"
+ - query_range: 'sum(kube_node_status_capacity_cpu_cores{kubernetes_namespace="gitlab-managed-apps"})'
+ label: Capacity
+ unit: "cores"
+ - title: "Memory usage"
+ y_label: "Memory"
+ required_metrics: ['container_memory_usage_bytes']
+ weight: 1
+ queries:
+ - query_range: 'avg(sum(container_memory_usage_bytes{id="/"}) by (job)) without (job) / 2^30'
+ label: Usage
+ unit: "GiB"
+ - query_range: 'sum(kube_node_status_capacity_memory_bytes{kubernetes_namespace="gitlab-managed-apps"})/2^30'
+ label: Capacity
+ unit: "GiB"
\ No newline at end of file
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 5820ccfa342b8826bf865314c6a5ad23ade376ff..c8e0a09570ac3c33c3b987d07bb6d62956ccf837 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -244,6 +244,7 @@
member do
get :status, format: :json
+ get :metrics, format: :json
scope :applications do
post '/:application', to: 'clusters/applications#create', as: :install_applications
diff --git a/ee/app/assets/javascripts/pages/projects/clusters/show/cluster_health.js b/ee/app/assets/javascripts/pages/projects/clusters/show/cluster_health.js
new file mode 100644
index 0000000000000000000000000000000000000000..8afe1aabdcf0e8338bcb1899b5951d2ff1a74ecd
--- /dev/null
+++ b/ee/app/assets/javascripts/pages/projects/clusters/show/cluster_health.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import Dashboard from '~/monitoring/components/dashboard.vue';
+
+export default () => {
+ const el = document.getElementById('prometheus-graphs');
+
+ if (el && el.dataset) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render(createElement) {
+ return createElement(Dashboard, {
+ props: {
+ ...el.dataset,
+ showLegend: false,
+ showPanels: false,
+ forceSmallGraph: true,
+ },
+ });
+ },
+ });
+ }
+};
diff --git a/ee/app/assets/javascripts/pages/projects/clusters/show/index.js b/ee/app/assets/javascripts/pages/projects/clusters/show/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..873c18c8ab0b087650e3fbc1cda8b163c85b56c7
--- /dev/null
+++ b/ee/app/assets/javascripts/pages/projects/clusters/show/index.js
@@ -0,0 +1,4 @@
+import '~/pages/projects/clusters/show';
+import initClusterHealth from './cluster_health';
+
+document.addEventListener('DOMContentLoaded', initClusterHealth);
diff --git a/ee/app/models/license.rb b/ee/app/models/license.rb
index 721ea3d48946327ed8a88e4ac4f131cb2c8a7a19..04b95f178f3c362aaa6a85ef04653de3d6f02a6f 100644
--- a/ee/app/models/license.rb
+++ b/ee/app/models/license.rb
@@ -60,6 +60,7 @@ class License < ActiveRecord::Base
EEU_FEATURES = EEP_FEATURES + %i[
sast
sast_container
+ cluster_health
dast
epics
ide
diff --git a/ee/app/views/projects/clusters/_health.html.haml b/ee/app/views/projects/clusters/_health.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3416fd9f227b4071d9591476985accb31a4d564b
--- /dev/null
+++ b/ee/app/views/projects/clusters/_health.html.haml
@@ -0,0 +1,21 @@
+
+%section.settings.no-animate.expanded.cluster-health-graphs#cluster-health
+ %h4= s_('ClusterIntegration|Kubernetes cluster health')
+
+ - if @cluster&.application_prometheus&.installed?
+ #prometheus-graphs{ data: { "settings-path": edit_project_service_path(@project, 'prometheus'),
+ "clusters-path": project_clusters_path(@project),
+ "documentation-path": help_page_path('administration/monitoring/prometheus/index.md'),
+ "empty-getting-started-svg-path": image_path('illustrations/monitoring/getting_started.svg'),
+ "empty-loading-svg-path": image_path('illustrations/monitoring/loading.svg'),
+ "empty-unable-to-connect-svg-path": image_path('illustrations/monitoring/unable_to_connect.svg'),
+ "metrics-endpoint": metrics_namespace_project_cluster_path( format: :json ),
+ "project-path": project_path(@project),
+ "tags-path": project_tags_path(@project) } }
+
+ - else
+ .settings-content
+ %p= s_("ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data.")
+
+ %a.btn.btn-default{ href: '#cluster-applications' }
+ = s_('ClusterIntegration|Install Prometheus')
diff --git a/ee/changelogs/unreleased/5029-support-cluster-metrics.yml b/ee/changelogs/unreleased/5029-support-cluster-metrics.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d07ead28befc610822cc467d908b10385a6fea5b
--- /dev/null
+++ b/ee/changelogs/unreleased/5029-support-cluster-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Query cluster status
+merge_request: 4701
+author:
+type: added
diff --git a/ee/lib/gitlab/prometheus/queries/cluster_query.rb b/ee/lib/gitlab/prometheus/queries/cluster_query.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1eff80db14763eeb565c76022ade69fce0cdc422
--- /dev/null
+++ b/ee/lib/gitlab/prometheus/queries/cluster_query.rb
@@ -0,0 +1,14 @@
+module Gitlab
+ module Prometheus
+ module Queries
+ class ClusterQuery < BaseQuery
+ include QueryAdditionalMetrics
+
+ def query
+ AdditionalMetricsParser.load_groups_from_yaml('cluster_metrics.yml')
+ .map(&query_group(base_query_context(8.hours.ago, Time.now)))
+ end
+ end
+ end
+ end
+end
diff --git a/ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb b/ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..44ef5ac03dbfd1b76cb0e7c25ec1286fc700908b
--- /dev/null
+++ b/ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Gitlab::Prometheus::Queries::ClusterQuery do
+ let(:client) { double('prometheus_client', query_range: nil) }
+ subject { described_class.new(client) }
+
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'load cluster metrics from yaml' do
+ expect(Gitlab::Prometheus::AdditionalMetricsParser).to receive(:load_groups_from_yaml).with('cluster_metrics.yml').and_call_original
+
+ subject.query
+ end
+
+ it 'sends queries to prometheus' do
+ subject.query
+
+ expect(client).to have_received(:query_range).with(anything, start: 8.hours.ago, stop: Time.now).at_least(1)
+ end
+end
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 15ce418d0d6e4a93c5abfd173af407adbf342cad..edd58bc38e122b494a17120f93309b6d5ef82e81 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -155,6 +155,93 @@ def go
end
end
+ describe 'GET metrics' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
+
+ describe 'functionality' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context "Can't query Prometheus" do
+ it 'returns not found' do
+ go
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'can query Prometheus' do
+ let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true, query: nil) }
+
+ before do
+ allow(controller).to receive(:prometheus_adapter).and_return(prometheus_adapter)
+ end
+
+ it 'queries cluster metrics' do
+ go
+
+ expect(prometheus_adapter).to have_received(:query).with(:cluster)
+ end
+
+ context 'when response has content' do
+ let(:query_response) { { response: nil } }
+
+ before do
+ allow(prometheus_adapter).to receive(:query).and_return(query_response)
+ end
+
+ it 'returns prometheus query response' do
+ go
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(query_response.to_json)
+ end
+ end
+
+ context 'when response has no content' do
+ let(:query_response) { {} }
+
+ before do
+ allow(prometheus_adapter).to receive(:query).and_return(query_response)
+ end
+
+ it 'returns prometheus query response' do
+ go
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+ end
+ end
+
+ def go
+ get :metrics, format: :json,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: cluster
+ end
+
+ describe 'security' do
+ let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true, query: nil) }
+ before do
+ allow(controller).to receive(:prometheus_adapter).and_return(prometheus_adapter)
+ end
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(project) }
+ it { expect { go }.to be_allowed_for(:master).of(project) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_denied_for(:reporter).of(project) }
+ it { expect { go }.to be_denied_for(:guest).of(project) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
describe 'PUT update' do
context 'when cluster is provided by GCP' do
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
diff --git a/spec/controllers/projects/prometheus/metrics_controller_spec.rb b/spec/controllers/projects/prometheus/metrics_controller_spec.rb
index b2b245dba90eb80a3abb7afd7b9ea8611e858afb..5725aa6a78d229b5dd0694294af9fe9e336cfb99 100644
--- a/spec/controllers/projects/prometheus/metrics_controller_spec.rb
+++ b/spec/controllers/projects/prometheus/metrics_controller_spec.rb
@@ -7,6 +7,8 @@
let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true) }
before do
+ allow(controller).to receive(:project).and_return(project)
+
project.add_master(user)
sign_in(user)
end
diff --git a/spec/javascripts/fixtures/environments.rb b/spec/javascripts/fixtures/environments.rb
deleted file mode 100644
index d2457d75419b61f0ce2ce79ae5b7d1d5c038f9f3..0000000000000000000000000000000000000000
--- a/spec/javascripts/fixtures/environments.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'spec_helper'
-
-describe Projects::EnvironmentsController, '(JavaScript fixtures)', type: :controller do
- include JavaScriptFixturesHelpers
-
- let(:admin) { create(:admin) }
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project_empty_repo, namespace: namespace, path: 'environments-project') }
- let(:environment) { create(:environment, name: 'production', project: project) }
-
- render_views
-
- before(:all) do
- clean_frontend_fixtures('environments/metrics')
- end
-
- before do
- sign_in(admin)
- end
-
- it 'environments/metrics/metrics.html.raw' do |example|
- get :metrics,
- namespace_id: project.namespace,
- project_id: project,
- id: environment.id
-
- expect(response).to be_success
- store_frontend_fixture(response, example.description)
- end
-end
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index eb8f6bbe50d286043ae6e623d5087d85e3ebf99d..29b355307ef04f6f39374b9a2f7504d8745a5b4c 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -5,24 +5,35 @@ import axios from '~/lib/utils/axios_utils';
import { metricsGroupsAPIResponse, mockApiEndpoint } from './mock_data';
describe('Dashboard', () => {
- const fixtureName = 'environments/metrics/metrics.html.raw';
let DashboardComponent;
- let component;
- preloadFixtures(fixtureName);
+
+ const propsData = {
+ hasMetrics: false,
+ documentationPath: '/path/to/docs',
+ settingsPath: '/path/to/settings',
+ clustersPath: '/path/to/clusters',
+ tagsPath: '/path/to/tags',
+ projectPath: '/path/to/project',
+ metricsEndpoint: mockApiEndpoint,
+ deploymentEndpoint: null,
+ emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
+ emptyLoadingSvgPath: '/path/to/loading.svg',
+ emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
+ };
beforeEach(() => {
- loadFixtures(fixtureName);
+ setFixtures('
');
DashboardComponent = Vue.extend(Dashboard);
});
describe('no metrics are available yet', () => {
it('shows a getting started empty state when no metrics are present', () => {
- component = new DashboardComponent({
- el: document.querySelector('#prometheus-graphs'),
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData,
});
- component.$mount();
- expect(component.$el.querySelector('#prometheus-graphs')).toBe(null);
+ expect(component.$el.querySelector('.prometheus-graphs')).toBe(null);
expect(component.state).toEqual('gettingStarted');
});
});
@@ -30,11 +41,8 @@ describe('Dashboard', () => {
describe('requests information to the server', () => {
let mock;
beforeEach(() => {
- document.querySelector('#prometheus-graphs').setAttribute('data-has-metrics', 'true');
mock = new MockAdapter(axios);
- mock.onGet(mockApiEndpoint).reply(200, {
- metricsGroupsAPIResponse,
- });
+ mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
});
afterEach(() => {
@@ -42,14 +50,43 @@ describe('Dashboard', () => {
});
it('shows up a loading state', (done) => {
- component = new DashboardComponent({
- el: document.querySelector('#prometheus-graphs'),
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true },
});
- component.$mount();
+
Vue.nextTick(() => {
expect(component.state).toEqual('loading');
done();
});
});
+
+ it('hides the legend when showLegend is false', (done) => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showLegend: false },
+ });
+
+ setTimeout(() => {
+ expect(component.showEmptyState).toEqual(false);
+ expect(component.$el.querySelector('.legend-group')).toEqual(null);
+ expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
+ done();
+ });
+ });
+
+ it('hides the group panels when showPanels is false', (done) => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showPanels: false },
+ });
+
+ setTimeout(() => {
+ expect(component.showEmptyState).toEqual(false);
+ expect(component.$el.querySelector('.prometheus-panel')).toEqual(null);
+ expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
+ done();
+ });
+ });
});
});
diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb
index f4b9c57e71a3e76ed360d65b98b7914b728981df..10c3ea634d76575903431404a2f672f2dfd66add 100644
--- a/spec/models/concerns/prometheus_adapter_spec.rb
+++ b/spec/models/concerns/prometheus_adapter_spec.rb
@@ -4,14 +4,15 @@
include PrometheusHelpers
include ReactiveCachingHelpers
- class TestClass
- include PrometheusAdapter
- end
-
let(:project) { create(:prometheus_project) }
let(:service) { project.prometheus_service }
- let(:described_class) { TestClass }
+ let(:described_class) do
+ Class.new do
+ include PrometheusAdapter
+ end
+ end
+
let(:environment_query) { Gitlab::Prometheus::Queries::EnvironmentQuery }
describe '#query' do
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index c8af359eebd85a4c86a21b43ca87c23c040875df..eb86ddc257f56328e4fe7917470baeaecf6a2e27 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -547,7 +547,7 @@
let(:project) { create(:prometheus_project) }
subject { environment.additional_metrics }
- context 'when the environment has additional metrics' do
+ context 'when the environment has metrics' do
before do
allow(environment).to receive(:has_metrics?).and_return(true)
end