Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorReuben Pereira <rpereira@gitlab.com>2019-07-16 22:20:43 +0300
committerStan Hu <stanhu@gmail.com>2019-07-16 22:20:43 +0300
commit0d84010d1c374fe3cfdbc3b067e4502e56b6a8b3 (patch)
tree9e7a5e3c403383d206c77ecc4167983b2ad05ba0 /app
parent58d220bd66fc60cc05b4197328015a7be5593147 (diff)
Don't use transactions and exceptions
Instead return error objects.
Diffstat (limited to 'app')
-rw-r--r--app/models/concerns/stepable.rb35
-rw-r--r--app/services/self_monitoring/project/create_service.rb132
2 files changed, 167 insertions, 0 deletions
diff --git a/app/models/concerns/stepable.rb b/app/models/concerns/stepable.rb
new file mode 100644
index 00000000000..d00a049a004
--- /dev/null
+++ b/app/models/concerns/stepable.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Stepable
+ extend ActiveSupport::Concern
+
+ def steps
+ self.class._all_steps
+ end
+
+ def execute_steps
+ initial_result = {}
+
+ steps.inject(initial_result) do |previous_result, callback|
+ result = method(callback).call
+
+ if result[:status] == :error
+ result[:failed_step] = callback
+
+ break result
+ end
+
+ previous_result.merge(result)
+ end
+ end
+
+ class_methods do
+ def _all_steps
+ @_all_steps ||= []
+ end
+
+ def steps(*methods)
+ _all_steps.concat methods
+ end
+ end
+end
diff --git a/app/services/self_monitoring/project/create_service.rb b/app/services/self_monitoring/project/create_service.rb
new file mode 100644
index 00000000000..e5ef8c15456
--- /dev/null
+++ b/app/services/self_monitoring/project/create_service.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+module SelfMonitoring
+ module Project
+ class CreateService < ::BaseService
+ include Stepable
+
+ DEFAULT_VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
+ DEFAULT_NAME = 'GitLab Instance Administration'
+ DEFAULT_DESCRIPTION = <<~HEREDOC
+ This project is automatically generated and will be used to help monitor this GitLab instance.
+ HEREDOC
+
+ steps :validate_admins,
+ :create_project,
+ :add_project_members,
+ :add_prometheus_manual_configuration
+
+ def initialize
+ super(nil)
+ end
+
+ def execute
+ execute_steps
+ end
+
+ private
+
+ def validate_admins
+ unless instance_admins.any?
+ log_error('No active admin user found')
+ return error('No active admin user found')
+ end
+
+ success
+ end
+
+ def create_project
+ admin_user = project_owner
+ @project = ::Projects::CreateService.new(admin_user, create_project_params).execute
+
+ if project.persisted?
+ success(project: project)
+ else
+ log_error("Could not create self-monitoring project. Errors: #{project.errors.full_messages}")
+ error('Could not create project')
+ end
+ end
+
+ def add_project_members
+ members = project.add_users(project_maintainers, Gitlab::Access::MAINTAINER)
+ errors = members.flat_map { |member| member.errors.full_messages }
+
+ if errors.any?
+ log_error("Could not add admins as members to self-monitoring project. Errors: #{errors}")
+ error('Could not add admins as members')
+ else
+ success
+ end
+ end
+
+ def add_prometheus_manual_configuration
+ return success unless prometheus_enabled?
+ return success unless prometheus_listen_address.present?
+
+ # TODO: Currently, adding the internal prometheus server as a manual configuration
+ # is only possible if the setting to allow webhooks and services to connect
+ # to local network is on.
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/44496 will add
+ # a whitelist that will allow connections to certain ips on the local network.
+
+ service = project.find_or_initialize_service('prometheus')
+
+ unless service.update(prometheus_service_attributes)
+ log_error("Could not save prometheus manual configuration for self-monitoring project. Errors: #{service.errors.full_messages}")
+ return error('Could not save prometheus manual configuration')
+ end
+
+ success
+ end
+
+ def prometheus_enabled?
+ Gitlab.config.prometheus.enable
+ rescue Settingslogic::MissingSetting
+ false
+ end
+
+ def prometheus_listen_address
+ Gitlab.config.prometheus.listen_address
+ rescue Settingslogic::MissingSetting
+ end
+
+ def instance_admins
+ @instance_admins ||= User.admins.active
+ end
+
+ def project_owner
+ instance_admins.first
+ end
+
+ def project_maintainers
+ # Exclude the first so that the project_owner is not added again as a member.
+ instance_admins - [project_owner]
+ end
+
+ def create_project_params
+ {
+ initialize_with_readme: true,
+ visibility_level: DEFAULT_VISIBILITY_LEVEL,
+ name: DEFAULT_NAME,
+ description: DEFAULT_DESCRIPTION
+ }
+ end
+
+ def internal_prometheus_listen_address_uri
+ if prometheus_listen_address.starts_with?('http')
+ prometheus_listen_address
+ else
+ 'http://' + prometheus_listen_address
+ end
+ end
+
+ def prometheus_service_attributes
+ {
+ api_url: internal_prometheus_listen_address_uri,
+ manual_configuration: true,
+ active: true
+ }
+ end
+ end
+ end
+end