2020-03-13 15:44:24 +05:30
# frozen_string_literal: true
# Copies system dashboard definition in .yml file into designated
# .yml file inside `.gitlab/dashboards`
module Metrics
module Dashboard
class CloneDashboardService < :: BaseService
2020-04-22 19:07:51 +05:30
include Stepable
2020-07-28 23:09:34 +05:30
include Gitlab :: Utils :: StrongMemoize
2020-04-22 19:07:51 +05:30
2020-03-13 15:44:24 +05:30
ALLOWED_FILE_TYPE = '.yml'
2020-10-24 23:57:45 +05:30
USER_DASHBOARDS_DIR = :: Gitlab :: Metrics :: Dashboard :: RepoDashboardFinder :: DASHBOARD_ROOT
2020-07-28 23:09:34 +05:30
SEQUENCES = {
:: Metrics :: Dashboard :: SystemDashboardService :: DASHBOARD_PATH = > [
:: Gitlab :: Metrics :: Dashboard :: Stages :: CommonMetricsInserter ,
2020-10-24 23:57:45 +05:30
:: Gitlab :: Metrics :: Dashboard :: Stages :: CustomMetricsInserter
2020-07-28 23:09:34 +05:30
] . freeze ,
:: Metrics :: Dashboard :: SelfMonitoringDashboardService :: DASHBOARD_PATH = > [
:: Gitlab :: Metrics :: Dashboard :: Stages :: CustomMetricsInserter
] . freeze ,
:: Metrics :: Dashboard :: ClusterDashboardService :: DASHBOARD_PATH = > [
2020-10-24 23:57:45 +05:30
:: Gitlab :: Metrics :: Dashboard :: Stages :: CommonMetricsInserter
2020-07-28 23:09:34 +05:30
] . freeze
} . freeze
2020-04-22 19:07:51 +05:30
steps :check_push_authorized ,
2020-07-28 23:09:34 +05:30
:check_branch_name ,
:check_file_type ,
:check_dashboard_template ,
:create_file ,
:refresh_repository_method_caches
2020-03-13 15:44:24 +05:30
def execute
2020-04-22 19:07:51 +05:30
execute_steps
end
private
def check_push_authorized ( result )
return error ( _ ( 'You are not allowed to push into this branch. Create another branch or open a merge request.' ) , :forbidden ) unless push_authorized?
success ( result )
end
def check_branch_name ( result )
return error ( _ ( 'There was an error creating the dashboard, branch name is invalid.' ) , :bad_request ) unless valid_branch_name?
return error ( _ ( 'There was an error creating the dashboard, branch named: %{branch} already exists.' ) % { branch : params [ :branch ] } , :bad_request ) unless new_or_default_branch?
success ( result )
end
2020-03-13 15:44:24 +05:30
2020-04-22 19:07:51 +05:30
def check_file_type ( result )
return error ( _ ( 'The file name should have a .yml extension' ) , :bad_request ) unless target_file_type_valid?
2020-03-13 15:44:24 +05:30
2020-04-22 19:07:51 +05:30
success ( result )
end
2020-07-28 23:09:34 +05:30
# Only allow out of the box metrics dashboards to be cloned. This can be
# changed to allow cloning of any metrics dashboard, if desired.
# However, only metrics dashboards should be allowed. If any file is
# allowed to be cloned, this will become a security risk.
2020-04-22 19:07:51 +05:30
def check_dashboard_template ( result )
2020-07-28 23:09:34 +05:30
return error ( _ ( 'Not found.' ) , :not_found ) unless dashboard_service & . out_of_the_box_dashboard?
2020-04-22 19:07:51 +05:30
success ( result )
end
def create_file ( result )
create_file_response = :: Files :: CreateService . new ( project , current_user , dashboard_attrs ) . execute
if create_file_response [ :status ] == :success
success ( result . merge ( create_file_response ) )
else
wrap_error ( create_file_response )
2020-03-13 15:44:24 +05:30
end
end
2020-04-22 19:07:51 +05:30
def refresh_repository_method_caches ( result )
repository . refresh_method_caches ( [ :metrics_dashboard ] )
success ( result . merge ( http_status : :created , dashboard : dashboard_details ) )
end
2020-03-13 15:44:24 +05:30
2020-07-28 23:09:34 +05:30
def dashboard_service
strong_memoize ( :dashboard_service ) do
Gitlab :: Metrics :: Dashboard :: ServiceSelector . call ( dashboard_service_options )
end
end
2020-03-13 15:44:24 +05:30
def dashboard_attrs
{
commit_message : params [ :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 dashboard_details
{
path : new_dashboard_path ,
2020-04-22 19:07:51 +05:30
display_name : :: Metrics :: Dashboard :: CustomDashboardService . name_for_path ( new_dashboard_path ) ,
2020-03-13 15:44:24 +05:30
default : false ,
system_dashboard : false
}
end
def push_authorized?
2020-10-24 23:57:45 +05:30
Gitlab :: UserAccess . new ( current_user , container : project ) . can_push_to_branch? ( branch )
2020-03-13 15:44:24 +05:30
end
def dashboard_template
2020-04-22 19:07:51 +05:30
@dashboard_template || = params [ :dashboard ]
2020-03-13 15:44:24 +05:30
end
def branch
2020-04-22 19:07:51 +05:30
@branch || = params [ :branch ]
2020-03-13 15:44:24 +05:30
end
def new_or_default_branch?
! repository . branch_exists? ( params [ :branch ] ) || project . default_branch == params [ :branch ]
end
def valid_branch_name?
Gitlab :: GitRefValidator . validate ( params [ :branch ] )
end
def new_dashboard_path
@new_dashboard_path || = File . join ( USER_DASHBOARDS_DIR , file_name )
end
def file_name
2020-04-22 19:07:51 +05:30
@file_name || = File . basename ( params [ :file_name ] )
2020-03-13 15:44:24 +05:30
end
def target_file_type_valid?
File . extname ( params [ :file_name ] ) == ALLOWED_FILE_TYPE
end
2020-04-22 19:07:51 +05:30
def wrap_error ( result )
if result [ :message ] == 'A file with this name already exists'
error ( _ ( " A file with '%{file_name}' already exists in %{branch} branch " ) % { file_name : file_name , branch : branch } , :bad_request )
else
result
end
end
2020-03-13 15:44:24 +05:30
def new_dashboard_content
:: Gitlab :: Metrics :: Dashboard :: Processor
. new ( project , raw_dashboard , sequence , { } )
. process . deep_stringify_keys . to_yaml
end
def repository
@repository || = project . repository
end
def raw_dashboard
2020-07-28 23:09:34 +05:30
dashboard_service . new ( project , current_user , dashboard_service_options ) . raw_dashboard
end
def dashboard_service_options
{
embedded : false ,
dashboard_path : dashboard_template
}
2020-03-13 15:44:24 +05:30
end
def sequence
2020-07-28 23:09:34 +05:30
SEQUENCES [ dashboard_template ] || [ ]
2020-03-13 15:44:24 +05:30
end
end
end
end