Commit f133f144 authored by syasonik's avatar syasonik

Port validations from CE

parent d3097abc
...@@ -162,9 +162,19 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -162,9 +162,19 @@ class Projects::EnvironmentsController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.json do format.json do
dashboard = Gitlab::MetricsDashboard::Service.new(@project, environment).get_dashboard result = Gitlab::MetricsDashboard::Service.new(@project, @current_user, environment: environment).get_dashboard
render json: dashboard, status: :ok if result[:status] == :success
render status: :ok, json: {
status: :success,
dashboard: result[:dashboard]
}
else
render status: result[:http_status] || :bad_request, json: {
message: result[:message],
status: result[:status]
}
end
end end
end end
end end
......
...@@ -9,8 +9,7 @@ describe Gitlab::MetricsDashboard::Processor do ...@@ -9,8 +9,7 @@ describe Gitlab::MetricsDashboard::Processor do
describe 'process' do describe 'process' do
let(:process_params) { [dashboard_yml, project, environment] } let(:process_params) { [dashboard_yml, project, environment] }
let(:dashboard_json) { described_class.new(*process_params).process } let(:dashboard) { described_class.new(*process_params).process }
let(:dashboard) { JSON.parse(dashboard_json, symbolize_names: true) }
context 'when the dashboard references persisted metrics with alerts' do context 'when the dashboard references persisted metrics with alerts' do
let!(:alert) { create( :prometheus_alert, project: project, prometheus_metric: persisted_metric ) } let!(:alert) { create( :prometheus_alert, project: project, prometheus_metric: persisted_metric ) }
......
...@@ -18,9 +18,10 @@ module Gitlab ...@@ -18,9 +18,10 @@ module Gitlab
end end
def process def process
stages.each { |stage| stage.new(@dashboard, @project, @environment).transform! } stage_params = [@dashboard, @project, @environment]
stages.each { |stage| stage.new(*stage_params).transform! }
@dashboard.to_json @dashboard
end end
end end
end end
......
...@@ -3,20 +3,17 @@ ...@@ -3,20 +3,17 @@
# Fetches the metrics dashboard layout and supplemented the output with DB info. # Fetches the metrics dashboard layout and supplemented the output with DB info.
module Gitlab module Gitlab
module MetricsDashboard module MetricsDashboard
class Service class Service < ::BaseService
SYSTEM_DASHBOARD_NAME = 'common_metrics' SYSTEM_DASHBOARD_NAME = 'common_metrics'
SYSTEM_DASHBOARD_PATH = Rails.root.join('config', 'prometheus', "#{SYSTEM_DASHBOARD_NAME}.yml") SYSTEM_DASHBOARD_PATH = Rails.root.join('config', 'prometheus', "#{SYSTEM_DASHBOARD_NAME}.yml")
def initialize(project, environment)
@project = project
@environment = environment
end
# Returns a DB-supplemented json representation of a dashboard config file. # Returns a DB-supplemented json representation of a dashboard config file.
def get_dashboard def get_dashboard
dashboard = Rails.cache.fetch(cache_key) { system_dashboard } dashboard_string = Rails.cache.fetch(cache_key) { system_dashboard }
dashboard = process_dashboard(dashboard_string)
process_dashboard(dashboard) success(dashboard: dashboard)
end end
private private
...@@ -31,7 +28,7 @@ module Gitlab ...@@ -31,7 +28,7 @@ module Gitlab
end end
def process_dashboard(dashboard) def process_dashboard(dashboard)
Processor.new(dashboard, @project, @environment).process Processor.new(dashboard, project, params[:environment]).process
end end
end end
end end
......
...@@ -4,8 +4,9 @@ module Gitlab ...@@ -4,8 +4,9 @@ module Gitlab
module MetricsDashboard module MetricsDashboard
module Stages module Stages
class CommonMetricsInserter < BaseStage class CommonMetricsInserter < BaseStage
# For each metric in the dashboard config, attempts to find a corresponding # For each metric in the dashboard config, attempts to
# database record. If found, includes the record's id in the dashboard config. # find a corresponding database record. If found,
# includes the record's id in the dashboard config.
def transform! def transform!
common_metrics = ::PrometheusMetric.common common_metrics = ::PrometheusMetric.common
......
...@@ -4,8 +4,9 @@ module Gitlab ...@@ -4,8 +4,9 @@ module Gitlab
module MetricsDashboard module MetricsDashboard
module Stages module Stages
class ProjectMetricsInserter < BaseStage class ProjectMetricsInserter < BaseStage
# Inserts project-specific metrics into the dashboard config. # Inserts project-specific metrics into the dashboard
# If there are no project-specific metrics, this will have no effect. # config. If there are no project-specific metrics,
# this will have no effect.
def transform! def transform!
project.prometheus_metrics.each do |project_metric| project.prometheus_metrics.each do |project_metric|
group = find_or_create_panel_group(dashboard[:panel_groups], project_metric) group = find_or_create_panel_group(dashboard[:panel_groups], project_metric)
...@@ -16,8 +17,8 @@ module Gitlab ...@@ -16,8 +17,8 @@ module Gitlab
private private
# Looks for a panel_group corresponding to the provided metric object. # Looks for a panel_group corresponding to the
# If unavailable, inserts one. # provided metric object. If unavailable, inserts one.
# @param panel_groups [Array<Hash>] # @param panel_groups [Array<Hash>]
# @param metric [PrometheusMetric] # @param metric [PrometheusMetric]
def find_or_create_panel_group(panel_groups, metric) def find_or_create_panel_group(panel_groups, metric)
...@@ -30,8 +31,8 @@ module Gitlab ...@@ -30,8 +31,8 @@ module Gitlab
panel_group panel_group
end end
# Looks for a panel corresponding to the provided metric object. # Looks for a panel corresponding to the provided
# If unavailable, inserts one. # metric object. If unavailable, inserts one.
# @param panels [Array<Hash>] # @param panels [Array<Hash>]
# @param metric [PrometheusMetric] # @param metric [PrometheusMetric]
def find_or_create_panel(panels, metric) def find_or_create_panel(panels, metric)
...@@ -44,8 +45,8 @@ module Gitlab ...@@ -44,8 +45,8 @@ module Gitlab
panel panel
end end
# Looks for a metric corresponding to the provided metric object. # Looks for a metric corresponding to the provided
# If unavailable, inserts one. # metric object. If unavailable, inserts one.
# @param metrics [Array<Hash>] # @param metrics [Array<Hash>]
# @param metric [PrometheusMetric] # @param metric [PrometheusMetric]
def find_or_create_metric(metrics, metric) def find_or_create_metric(metrics, metric)
......
...@@ -479,32 +479,8 @@ describe Projects::EnvironmentsController do ...@@ -479,32 +479,8 @@ describe Projects::EnvironmentsController do
get :metrics_dashboard, params: environment_params(format: :json) get :metrics_dashboard, params: environment_params(format: :json)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to include('dashboard', 'order', 'panel_groups') expect(json_response.keys).to contain_exactly('dashboard', 'status')
expect(json_response['panel_groups']).to all( include('group', 'priority', 'panels') ) expect(json_response['dashboard']).to be_an_instance_of(Hash)
end
end
end
describe 'metrics_dashboard' do
context 'when prometheus endpoint is disabled' do
before do
stub_feature_flags(environment_metrics_use_prometheus_endpoint: false)
end
it 'responds with status code 403' do
get :metrics_dashboard, params: environment_params(format: :json)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when prometheus endpoint is enabled' do
it 'returns a json representation of the environment dashboard' do
get :metrics_dashboard, params: environment_params(format: :json)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to include('dashboard', 'order', 'panel_groups')
expect(json_response['panel_groups']).to all( include('group', 'priority', 'panels') )
end end
end end
end end
......
{
"type": "object",
"required": [
"dashboard",
"order",
"panel_groups"
],
"properties": {
"dashboard": { "type": "string" },
"order": { "type": "number" },
"panel_groups": {
"type": "array",
"items": { "$ref": "spec/fixtures/lib/gitlab/metrics_dashboard/schemas/panel_groups.json" }
}
},
"additionalProperties": false
}
{
"type": "object",
"required": [
"unit",
"label"
],
"oneOf": [
{ "required": ["query"] },
{ "required": ["query_range"] }
],
"properties": {
"id": { "type": "string" },
"query_range": { "type": "string" },
"query": { "type": "string" },
"unit": { "type": "string" },
"label": { "type": "string" },
"track": { "type": "string" }
},
"additionalProperties": false
}
{
"type": "object",
"required": [
"group",
"priority",
"panels"
],
"properties": {
"group": { "type": "string" },
"priority": { "type": "number" },
"panels": {
"type": "array",
"items": { "$ref": "panels.json" }
}
},
"additionalProperties": false
}
{
"type": "object",
"required": [
"title",
"y_label",
"weight",
"metrics"
],
"properties": {
"title": { "type": "string" },
"type": { "type": "string" },
"y_label": { "type": "string" },
"weight": { "type": "number" },
"metrics": {
"type": "array",
"items": { "$ref": "metrics.json" }
}
},
"additionalProperties": false
}
...@@ -9,8 +9,7 @@ describe Gitlab::MetricsDashboard::Processor do ...@@ -9,8 +9,7 @@ describe Gitlab::MetricsDashboard::Processor do
describe 'process' do describe 'process' do
let(:process_params) { [dashboard_yml, project, environment] } let(:process_params) { [dashboard_yml, project, environment] }
let(:dashboard_json) { described_class.new(*process_params).process } let(:dashboard) { described_class.new(*process_params).process }
let(:dashboard) { JSON.parse(dashboard_json, symbolize_names: true) }
context 'when dashboard config corresponds to common metrics' do context 'when dashboard config corresponds to common metrics' do
let!(:common_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') } let!(:common_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') }
......
...@@ -7,12 +7,15 @@ describe Gitlab::MetricsDashboard::Service, :use_clean_rails_memory_store_cachin ...@@ -7,12 +7,15 @@ describe Gitlab::MetricsDashboard::Service, :use_clean_rails_memory_store_cachin
let(:environment) { build(:environment) } let(:environment) { build(:environment) }
describe 'get_dashboard' do describe 'get_dashboard' do
let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics_dashboard/schemas/dashboard.json')) }
it 'returns a json representation of the environment dashboard' do it 'returns a json representation of the environment dashboard' do
dashboard = described_class.new(project, environment).get_dashboard result = described_class.new(project, environment).get_dashboard
json = JSON.parse(dashboard, symbolize_names: true)
expect(result.keys).to contain_exactly(:dashboard, :status)
expect(result[:status]).to eq(:success)
expect(json).to include(:dashboard, :order, :panel_groups) expect(JSON::Validator.fully_validate(dashboard_schema, result[:dashboard])).to be_empty
expect(json[:panel_groups]).to all( include(:group, :priority, :panels) )
end end
it 'caches the dashboard for subsequent calls' do it 'caches the dashboard for subsequent calls' do
......
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