Commit bf2e083d authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch...

Merge branch '35228-create-a-new-endpoint-to-copy-common_metrics-yml-to-the-local-project' into 'master'

Create a new endpoint to copy common_metrics.yml to the local project

Closes #35228

See merge request gitlab-org/gitlab!20616
parents b884bb26 1b72e33f
# frozen_string_literal: true
module Projects
module PerformanceMonitoring
class DashboardsController < ::Projects::ApplicationController
include BlobHelper
before_action :check_repository_available!
before_action :validate_dashboard_template!
before_action :authorize_push!
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::ProjectDashboardService::DASHBOARD_ROOT
DASHBOARD_TEMPLATES = {
::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH => true,
::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH => true
}.freeze
def create
result = ::Files::CreateService.new(project, current_user, dashboard_attrs).execute
if result[:status] == :success
respond_success
else
respond_error(result[:message])
end
end
private
def respond_success
respond_to do |format|
format.html { redirect_to ide_edit_path(project, branch, new_dashboard_path) }
format.json { render json: { redirect_to: ide_edit_path(project, branch, new_dashboard_path) }, status: :created }
end
end
def respond_error(message)
flash[:alert] = message
respond_to do |format|
format.html { redirect_back_or_default(default: namespace_project_environments_path) }
format.json { render json: { error: message }, status: :bad_request }
end
end
def authorize_push!
access_denied!(%q(You can't commit to this project)) unless user_access(project).can_push_to_branch?(branch)
end
def branch
params.require(:branch)
end
def dashboard_attrs
{
commit_message: commit_message,
file_path: new_dashboard_path,
file_content: new_dashboard_content,
encoding: 'text',
branch_name: branch,
start_branch: repository.branch_exists?(branch) ? branch : project.default_branch
}
end
def commit_message
params[:commit_message] || "Create custom dashboard #{params.require(:file_name)}"
end
def new_dashboard_path
File.join(USER_DASHBOARDS_DIR, params.require(:file_name))
end
def new_dashboard_content
File.read params.require(:dashboard)
end
def validate_dashboard_template!
access_denied! unless DASHBOARD_TEMPLATES[params.require(:dashboard)]
end
end
end
end
......@@ -60,6 +60,11 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
resources :subscriptions, only: [:create, :destroy]
namespace :performance_monitoring do
resources :dashboards, only: [:create]
end
resources :licenses, only: [:index, :create, :update], controller: 'security/licenses'
resources :environments, only: [] do
......
# frozen_string_literal: true
require 'spec_helper'
describe Projects::PerformanceMonitoring::DashboardsController do
let_it_be(:user) { create(:user) }
let_it_be(:namespace) { create(:namespace) }
let!(:project) { create(:project, :repository, name: 'dashboard-project', namespace: namespace) }
let(:commit_message) { 'test' }
let(:branch) { "#{Time.current.to_i}_dashboard_new_branch" }
let(:dashboard) { 'config/prometheus/common_metrics.yml' }
let(:file_name) { 'custom_dashboard.yml' }
let(:params) do
{
namespace_id: namespace,
project_id: project,
dashboard: dashboard,
file_name: file_name,
commit_message: commit_message,
branch: branch,
format: :json
}
end
describe 'POST #create' do
context 'authenticated user' do
before do
sign_in(user)
end
context 'project with repository feature' do
context 'with rights to push to the repository' do
before do
project.add_maintainer(user)
end
context 'valid parameters' do
it 'delegates commit creation to service' do
dashboard_attrs = {
commit_message: commit_message,
branch_name: branch,
start_branch: 'master',
encoding: 'text',
file_path: '.gitlab/dashboards/custom_dashboard.yml',
file_content: File.read('config/prometheus/common_metrics.yml')
}
service_instance = instance_double(::Files::CreateService)
expect(::Files::CreateService).to receive(:new).with(project, user, dashboard_attrs).and_return(service_instance)
expect(service_instance).to receive(:execute).and_return(status: :success)
post :create, params: params
end
context 'selected branch already exists' do
it 'responds with :created status code', :aggregate_failures do
post :create, params: params
expect(response).to have_gitlab_http_status :created
params[:file_name] = 'some_new_name.yml'
post :create, params: params
expect(response).to have_gitlab_http_status :created
end
end
context 'request format json' do
it 'returns path to new file' do
allow(::Files::CreateService).to receive(:new).and_return(double(execute: { status: :success }))
post :create, params: params
expect(response).to have_gitlab_http_status :created
expect(json_response).to eq('redirect_to' => "/-/ide/project/#{namespace.path}/#{project.name}/edit/#{branch}/-/.gitlab/dashboards/#{file_name}")
end
context 'files create service failure' do
it 'returns json with failure message' do
allow(::Files::CreateService).to receive(:new).and_return(double(execute: { status: false, message: 'something went wrong' }))
post :create, params: params
expect(response).to have_gitlab_http_status :bad_request
expect(response).to set_flash[:alert].to eq('something went wrong')
expect(json_response).to eq('error' => 'something went wrong')
end
end
end
context 'request format html' do
before do
params.delete(:format)
end
it 'redirects to ide with new file' do
allow(::Files::CreateService).to receive(:new).and_return(double(execute: { status: :success }))
post :create, params: params
expect(response).to redirect_to "/-/ide/project/#{namespace.path}/#{project.name}/edit/#{branch}/-/.gitlab/dashboards/#{file_name}"
end
context 'files create service failure' do
it 'redirects back and sets alert' do
allow(::Files::CreateService).to receive(:new).and_return(double(execute: { status: false, message: 'something went wrong' }))
post :create, params: params
expect(response).to set_flash[:alert].to eq('something went wrong')
expect(response).to redirect_to namespace_project_environments_path
end
end
end
end
context 'invalid dashboard template' do
let(:dashboard) { 'config/database.yml' }
it 'responds 404 not found' do
post :create, params: params
expect(response).to have_gitlab_http_status :not_found
end
end
context 'missing commit message' do
before do
params.delete(:commit_message)
end
it 'use default commit message' do
dashboard_attrs = {
commit_message: 'Create custom dashboard custom_dashboard.yml',
branch_name: branch,
start_branch: 'master',
encoding: 'text',
file_path: ".gitlab/dashboards/custom_dashboard.yml",
file_content: File.read('config/prometheus/common_metrics.yml')
}
service_instance = instance_double(::Files::CreateService)
expect(::Files::CreateService).to receive(:new).with(project, user, dashboard_attrs).and_return(service_instance)
expect(service_instance).to receive(:execute).and_return(status: :success)
post :create, params: params
end
end
context 'missing branch' do
let(:branch) { nil }
it 'raises ActionController::ParameterMissing' do
expect { post :create, params: params }.to raise_error ActionController::ParameterMissing
end
end
end
context 'without rights to push to repository' do
before do
project.add_guest(user)
end
it 'responds with :forbidden status code' do
post :create, params: params
expect(response).to have_gitlab_http_status :forbidden
end
end
end
context 'project without repository feature' do
let!(:project) { create(:project, name: 'dashboard-project', namespace: namespace) }
it 'responds with :not_found status code' do
post :create, params: params
expect(response).to have_gitlab_http_status :not_found
end
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