Commit e16b3f39 authored by Thong Kuah's avatar Thong Kuah

Merge branch '37964-auto-create-cluster-management-project' into 'master'

Create cluster management project automatically

See merge request gitlab-org/gitlab!23946
parents e0449925 65640529
# frozen_string_literal: true
module Clusters
module Management
class CreateProjectService
CreateError = Class.new(StandardError)
attr_reader :cluster, :current_user
def initialize(cluster, current_user:)
@cluster = cluster
@current_user = current_user
end
def execute
return unless management_project_required?
ActiveRecord::Base.transaction do
project = create_management_project!
update_cluster!(project)
end
end
private
def management_project_required?
Feature.enabled?(:auto_create_cluster_management_project) && cluster.management_project.nil?
end
def project_params
{
name: project_name,
description: project_description,
namespace_id: namespace.id,
visibility_level: Gitlab::VisibilityLevel::PRIVATE
}
end
def project_name
"#{cluster.name} Cluster Management"
end
def project_description
"This project is automatically generated and will be used to manage your Kubernetes cluster. [More information](#{docs_path})"
end
def docs_path
Rails.application.routes.url_helpers.help_page_path('user/clusters/management_project')
end
def create_management_project!
::Projects::CreateService.new(current_user, project_params).execute.tap do |project|
errors = project.errors.full_messages
if errors.any?
raise CreateError.new("Failed to create project: #{errors}")
end
end
end
def update_cluster!(project)
unless cluster.update(management_project: project)
raise CreateError.new("Failed to update cluster: #{cluster.errors.full_messages}")
end
end
def namespace
case cluster.cluster_type
when 'project_type'
cluster.project.namespace
when 'group_type'
cluster.group
when 'instance_type'
instance_administrators_group
else
raise NotImplementedError
end
end
def instance_administrators_group
Gitlab::CurrentSettings.instance_administrators_group ||
raise(CreateError.new('Instance administrators group not found'))
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Clusters::Management::CreateProjectService do
let(:cluster) { create(:cluster, :project) }
let(:current_user) { create(:user) }
subject { described_class.new(cluster, current_user: current_user).execute }
shared_examples 'management project is not required' do
it 'does not create a project' do
expect { subject }.not_to change(cluster, :management_project)
end
end
context ':auto_create_cluster_management_project feature flag is disabled' do
before do
stub_feature_flags(auto_create_cluster_management_project: false)
end
include_examples 'management project is not required'
end
context 'cluster already has a management project' do
let(:cluster) { create(:cluster, :management_project) }
include_examples 'management project is not required'
end
shared_examples 'creates a management project' do
let(:project_params) do
{
name: "#{cluster.name} Cluster Management",
description: 'This project is automatically generated and will be used to manage your Kubernetes cluster. [More information](/help/user/clusters/management_project)',
namespace_id: namespace&.id,
visibility_level: Gitlab::VisibilityLevel::PRIVATE
}
end
it 'creates a management project' do
expect(Projects::CreateService).to receive(:new)
.with(current_user, project_params)
.and_call_original
subject
management_project = cluster.management_project
expect(management_project).to be_present
expect(management_project).to be_private
expect(management_project.name).to eq "#{cluster.name} Cluster Management"
expect(management_project.namespace).to eq namespace
end
end
context 'project cluster' do
let(:cluster) { create(:cluster, projects: [project]) }
let(:project) { create(:project, namespace: current_user.namespace) }
let(:namespace) { project.namespace }
include_examples 'creates a management project'
end
context 'group cluster' do
let(:cluster) { create(:cluster, :group, user: current_user) }
let(:namespace) { cluster.group }
before do
namespace.add_user(current_user, Gitlab::Access::MAINTAINER)
end
include_examples 'creates a management project'
end
context 'instance cluster' do
let(:cluster) { create(:cluster, :instance, user: current_user) }
let(:namespace) { create(:group) }
before do
stub_application_setting(instance_administrators_group: namespace)
namespace.add_user(current_user, Gitlab::Access::MAINTAINER)
end
include_examples 'creates a management project'
end
describe 'error handling' do
let(:project) { cluster.project }
before do
allow(Projects::CreateService).to receive(:new)
.and_return(double(execute: project))
end
context 'project is invalid' do
let(:errors) { double(full_messages: ["Error message"]) }
let(:project) { instance_double(Project, errors: errors) }
it { expect { subject }.to raise_error(described_class::CreateError, /Failed to create project/) }
end
context 'instance administrators group is missing' do
let(:cluster) { create(:cluster, :instance) }
it { expect { subject }.to raise_error(described_class::CreateError, /Instance administrators group not found/) }
end
context 'cluster is invalid' do
before do
allow(cluster).to receive(:update).and_return(false)
end
it { expect { subject }.to raise_error(described_class::CreateError, /Failed to update cluster/) }
end
context 'unknown cluster type' do
before do
allow(cluster).to receive(:cluster_type).and_return("unknown_type")
end
it { expect { subject }.to raise_error(NotImplementedError) }
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