Commit ed5add1c authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent de2fb5b8
# frozen_string_literal: true
module Resolvers
module Metrics
class DashboardResolver < Resolvers::BaseResolver
argument :path, GraphQL::STRING_TYPE,
required: true,
description: "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'"
type Types::Metrics::DashboardType, null: true
alias_method :environment, :object
def resolve(**args)
return unless environment
::PerformanceMonitoring::PrometheusDashboard.find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment })
end
end
end
end
......@@ -15,5 +15,9 @@ module Types
field :state, GraphQL::STRING_TYPE, null: false,
description: 'State of the environment, for example: available/stopped'
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
description: 'Metrics dashboard schema for the environment',
resolver: Resolvers::Metrics::DashboardResolver
end
end
# frozen_string_literal: true
module Types
module Metrics
# rubocop: disable Graphql/AuthorizeTypes
# Authorization is performed at environment level
class DashboardType < ::Types::BaseObject
graphql_name 'MetricsDashboard'
field :path, GraphQL::STRING_TYPE, null: true,
description: 'Path to a file with the dashboard definition'
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
......@@ -4,12 +4,13 @@ module PerformanceMonitoring
class PrometheusDashboard
include ActiveModel::Model
attr_accessor :dashboard, :panel_groups
attr_accessor :dashboard, :panel_groups, :path, :environment, :priority
validates :dashboard, presence: true
validates :panel_groups, presence: true
def self.from_json(json_content)
class << self
def from_json(json_content)
dashboard = new(
dashboard: json_content['dashboard'],
panel_groups: json_content['panel_groups'].map { |group| PrometheusPanelGroup.from_json(group) }
......@@ -18,13 +19,26 @@ module PerformanceMonitoring
dashboard.tap(&:validate!)
end
def find_for(project:, user:, path:, options: {})
dashboard_response = Gitlab::Metrics::Dashboard::Finder.find(project, user, options.merge(dashboard_path: path))
return unless dashboard_response[:status] == :success
new(
{
path: path,
environment: options[:environment]
}.merge(dashboard_response[:dashboard])
)
end
end
def to_yaml
self.as_json(only: valid_attributes).to_yaml
self.as_json(only: yaml_valid_attributes).to_yaml
end
private
def valid_attributes
def yaml_valid_attributes
%w(panel_groups panels metrics group priority type title y_label weight id unit label query query_range dashboard)
end
end
......
......@@ -56,7 +56,8 @@ class PrometheusAlert < ApplicationRecord
"for" => "5m",
"labels" => {
"gitlab" => "hook",
"gitlab_alert_id" => prometheus_metric_id
"gitlab_alert_id" => prometheus_metric_id,
"gitlab_prometheus_alert_id" => id
}
}
end
......
---
title: Prevent wrong environment being used when processing Prometheus alert
merge_request: 29119
author:
type: fixed
---
title: Exclude 'trial_ends_on', 'shared_runners_minutes_limit' & 'extra_shared_runners_minutes_limit' from list of exported Group attributes
merge_request: 29259
author:
type: fixed
---
title: Add graphQL interface to fetch metrics dashboard
merge_request: 29112
author:
type: added
......@@ -178,6 +178,18 @@ Plan.default.limits.update!(ci_pipeline_schedules: 100)
## Instance monitoring and metrics
### Incident Management inbound alert limits
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14932) in GitLab 12.5.
Limiting inbound alerts for an incident reduces the number of alerts (issues)
that can be created within a period of time, which can help prevent overloading
your incident responders with duplicate issues. You can reduce the volume of
alerts in the following ways:
- Max requests per period per project, 3600 seconds by default.
- Rate limit period in seconds, 3600 seconds by default.
### Prometheus Alert JSON payloads
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14929) in GitLab 12.6.
......
......@@ -1882,6 +1882,16 @@ type Environment {
"""
id: ID!
"""
Metrics dashboard schema for the environment
"""
metricsDashboard(
"""
Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'
"""
path: String!
): MetricsDashboard
"""
Human-readable name of the environment
"""
......@@ -5278,6 +5288,13 @@ type Metadata {
version: String!
}
type MetricsDashboard {
"""
Path to a file with the dashboard definition
"""
path: String
}
"""
Represents a milestone.
"""
......
......@@ -5580,6 +5580,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "metricsDashboard",
"description": "Metrics dashboard schema for the environment",
"args": [
{
"name": "path",
"description": "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "MetricsDashboard",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Human-readable name of the environment",
......@@ -15117,6 +15144,33 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "MetricsDashboard",
"description": null,
"fields": [
{
"name": "path",
"description": "Path to a file with the dashboard definition",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Milestone",
......
......@@ -324,6 +324,7 @@ Describes where code is deployed for a project
| Name | Type | Description |
| --- | ---- | ---------- |
| `id` | ID! | ID of the environment |
| `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment |
| `name` | String! | Human-readable name of the environment |
| `state` | String! | State of the environment, for example: available/stopped |
......@@ -815,6 +816,12 @@ Autogenerated return type of MergeRequestSetWip
| `revision` | String! | Revision |
| `version` | String! | Version |
## MetricsDashboard
| Name | Type | Description |
| --- | ---- | ---------- |
| `path` | String | Path to a file with the dashboard definition |
## Milestone
Represents a milestone.
......
......@@ -721,7 +721,7 @@ For example, in order to test new index you can do the following:
Create the index:
```sql
exec CREATE INDEX index_projects_marked_for_deletion ON projects (marked_for_deletion_at) WHERE marked_for_deletion_at IS NOT NULL
exec CREATE INDEX index_projects_last_activity ON projects (last_activity_at) WHERE last_activity_at IS NOT NULL
```
Analyze the table to update its statistics:
......@@ -733,7 +733,7 @@ exec ANALYZE projects
Get the query plan:
```sql
explain SELECT * FROM projects WHERE marked_for_deletion_at < CURRENT_DATE
explain SELECT * FROM projects WHERE last_activity_at < CURRENT_DATE
```
Once done you can rollback your changes:
......
......@@ -309,6 +309,7 @@ The following tables outline the details of expected properties.
| `label` | string | no, but highly encouraged | Defines the legend-label for the query. Should be unique within the panel's metrics. Can contain time series labels as interpolated variables. |
| `query` | string | yes if `query_range` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
| `query_range` | string | yes if `query` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query_range` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
| `step` | number | no, value is calculated if not defined | Defines query resolution step width in float number of seconds. Metrics on the same panel should use the same `step` value. |
##### Dynamic labels
......
......@@ -21,6 +21,12 @@ module Gitlab
end
end
def gitlab_prometheus_alert_id
strong_memoize(:gitlab_prometheus_alert_id) do
payload&.dig('labels', 'gitlab_prometheus_alert_id')
end
end
def title
strong_memoize(:title) do
gitlab_alert&.title || parse_title_from_payload
......@@ -120,12 +126,19 @@ module Gitlab
end
def parse_gitlab_alert_from_payload
return unless metric_id
alerts_found = matching_gitlab_alerts
return if alerts_found.blank? || alerts_found.size > 1
alerts_found.first
end
def matching_gitlab_alerts
return unless metric_id || gitlab_prometheus_alert_id
Projects::Prometheus::AlertsFinder
.new(project: project, metric: metric_id)
.new(project: project, metric: metric_id, id: gitlab_prometheus_alert_id)
.execute
.first
end
def parse_title_from_payload
......
......@@ -14,7 +14,7 @@ module Gitlab
define_histogram :gitlab_redis_diff_caching_memory_usage_bytes do
docstring 'Redis diff caching memory usage by key'
buckets [100, 1000, 10000, 100000, 1000000, 10000000]
buckets [100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000]
end
define_counter :gitlab_redis_diff_caching_hit do
......
......@@ -36,6 +36,9 @@ excluded_attributes:
- :runners_token_encrypted
- :saml_discovery_token
- :visibility_level
- :trial_ends_on
- :shared_runners_minute_limit
- :extra_shared_runners_minutes_limit
epics:
- :state_id
......
This diff is collapsed.
......@@ -19,18 +19,15 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 7,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"saml_discovery_token": "rBKx3ioz",
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"runners_token": "token",
......@@ -1075,18 +1072,15 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 4351,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"saml_discovery_token": "ki3Xnjw3",
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -1649,18 +1643,15 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 4351,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"saml_discovery_token": "m7cx4AZi",
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......
......@@ -19,18 +19,15 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"saml_discovery_token": "rBKx3ioz",
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......
......@@ -20,17 +20,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -61,17 +58,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -102,17 +96,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -143,17 +134,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......
......@@ -20,17 +20,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -61,17 +58,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -102,17 +96,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -143,17 +134,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......
......@@ -20,17 +20,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -61,17 +58,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -102,17 +96,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......@@ -143,17 +134,14 @@
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
......
# frozen_string_literal: true
require 'spec_helper'
describe Resolvers::Metrics::DashboardResolver do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
describe '#resolve' do
subject(:resolve_dashboard) { resolve(described_class, obj: parent_object, args: args, ctx: { current_user: current_user }) }
let(:args) do
{
path: 'config/prometheus/common_metrics.yml'
}
end
context 'for environment' do
let(:project) { create(:project) }
let(:parent_object) { create(:environment, project: project) }
before do
project.add_developer(current_user)
end
it 'use ActiveModel class to find matching dashboard', :aggregate_failures do
expected_arguments = { project: project, user: current_user, path: args[:path], options: { environment: parent_object } }
expect(PerformanceMonitoring::PrometheusDashboard).to receive(:find_for).with(expected_arguments).and_return(PerformanceMonitoring::PrometheusDashboard.new)
expect(resolve_dashboard).to be_instance_of PerformanceMonitoring::PrometheusDashboard
end
context 'without parent object' do
let(:parent_object) { nil }
it 'returns nil', :aggregate_failures do
expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:find_for)
expect(resolve_dashboard).to be_nil
end
end
end
end
end
......@@ -7,7 +7,7 @@ describe GitlabSchema.types['Environment'] do
it 'has the expected fields' do
expected_fields = %w[
name id state
name id state metrics_dashboard
]
expect(described_class).to have_graphql_fields(*expected_fields)
......
# frozen_string_literal: true
require 'spec_helper'
describe GitlabSchema.types['MetricsDashboard'] do
it { expect(described_class.graphql_name).to eq('MetricsDashboard') }
it 'has the expected fields' do
expected_fields = %w[
path
]
expect(described_class).to have_graphql_fields(*expected_fields)
end
end
......@@ -9,11 +9,14 @@ describe Gitlab::Alerting::Alert do
let(:payload) { {} }
shared_context 'gitlab alert' do
let(:gitlab_alert_id) { gitlab_alert.prometheus_metric_id.to_s }
let!(:gitlab_alert) { create(:prometheus_alert, project: project) }
let(:gitlab_alert_id) { gitlab_alert.id }
before do
payload['labels'] = { 'gitlab_alert_id' => gitlab_alert_id }
payload['labels'] = {
'gitlab_alert_id' => gitlab_alert.prometheus_metric_id.to_s,
'gitlab_prometheus_alert_id' => gitlab_alert_id
}
end
end
......@@ -68,6 +71,41 @@ describe Gitlab::Alerting::Alert do
it { is_expected.to be_nil }
end
context 'when two alerts with the same metric exist' do
include_context 'gitlab alert'
let!(:second_gitlab_alert) do
create(:prometheus_alert,
project: project,
prometheus_metric_id: gitlab_alert.prometheus_metric_id
)
end
context 'alert id given in params' do
before do
payload['labels'] = {
'gitlab_alert_id' => gitlab_alert.prometheus_metric_id.to_s,
'gitlab_prometheus_alert_id' => second_gitlab_alert.id
}
end
it { is_expected.to eq(second_gitlab_alert) }
end
context 'metric id given in params' do
# This tests the case when two alerts are found, as metric id
# is not unique.
# Note the metric id was incorrectly named as 'gitlab_alert_id'
# in PrometheusAlert#to_param.
before do
payload['labels'] = { 'gitlab_alert_id' => gitlab_alert.prometheus_metric_id }
end
it { is_expected.to be_nil }
end
end
end
describe '#title' do
......
......@@ -96,7 +96,8 @@ describe PrometheusAlert do
"for" => "5m",
"labels" => {
"gitlab" => "hook",
"gitlab_alert_id" => metric.id
"gitlab_alert_id" => metric.id,
"gitlab_prometheus_alert_id" => subject.id
})
end
end
......
# frozen_string_literal: true
require 'spec_helper'
describe 'Getting Metrics Dashboard' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let(:project) { create(:project) }
let!(:environment) { create(:environment, project: project) }
let(:fields) do
<<~QUERY
#{all_graphql_fields_for('MetricsDashboard'.classify)}
QUERY
end
let(:query) do
%(
query {
project(fullPath:"#{project.full_path}") {
environments(name: "#{environment.name}") {
nodes {
metricsDashboard(path: "#{path}"){
#{fields}
}
}
}
}
}
)
end
context 'for anonymous user' do
before do
post_graphql(query, current_user: current_user)
end
context 'requested dashboard is available' do
let(:path) { 'config/prometheus/common_metrics.yml' }
it_behaves_like 'a working graphql query'
it 'returns nil' do
dashboard = graphql_data.dig('project', 'environments', 'nodes')
expect(dashboard).to be_nil
end
end
end
context 'for user with developer access' do
before do
project.add_developer(current_user)
post_graphql(query, current_user: current_user)
end
context 'requested dashboard is available' do
let(:path) { 'config/prometheus/common_metrics.yml' }
it_behaves_like 'a working graphql query'
it 'returns metrics dashboard' do
dashboard = graphql_data.dig('project', 'environments', 'nodes')[0]['metricsDashboard']
expect(dashboard).to eql("path" => path)
end
end
context 'requested dashboard can not be found' do
let(:path) { 'config/prometheus/i_am_not_here.yml' }
it_behaves_like 'a working graphql query'
it 'return snil' do
dashboard = graphql_data.dig('project', 'environments', 'nodes')[0]['metricsDashboard']
expect(dashboard).to be_nil
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment