Commit 6fd70b24 authored by James Fargher's avatar James Fargher

Allow projects to use instance level clusters

There are two cluster hierarchies one for the deployment platform and
one for controllers. The main difference is that deployment platforms do
not check user permissions and only return the first match.
parent 57c6c7d3
...@@ -8,10 +8,18 @@ class Admin::ClustersController < Clusters::ClustersController ...@@ -8,10 +8,18 @@ class Admin::ClustersController < Clusters::ClustersController
private private
def clusterable def clusterable
@clusterable ||= InstanceClusterablePresenter.fabricate(Clusters::Instance.new, current_user: current_user) @clusterable ||= InstanceClusterablePresenter.fabricate(cluster_instance, current_user: current_user)
end
def cluster_instance
@cluster_instance ||= Clusters::Instance.new
end end
def check_instance_clusters_feature_flag! def check_instance_clusters_feature_flag!
render_404 unless Feature.enabled?(:instance_clusters, default_enabled: true) render_404 unless instance_clusters_enabled?
end
def instance_clusters_enabled?
cluster_instance.instance_clusters_enabled?
end end
end end
...@@ -115,10 +115,12 @@ module Clusters ...@@ -115,10 +115,12 @@ module Clusters
} }
def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc) def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
return [] if clusterable.is_a?(Instance)
hierarchy_groups = clusterable.ancestors_upto(hierarchy_order: hierarchy_order).eager_load(:clusters) hierarchy_groups = clusterable.ancestors_upto(hierarchy_order: hierarchy_order).eager_load(:clusters)
hierarchy_groups = hierarchy_groups.merge(current_scope) if current_scope hierarchy_groups = hierarchy_groups.merge(current_scope) if current_scope
hierarchy_groups.flat_map(&:clusters) hierarchy_groups.flat_map(&:clusters) + Instance.new.clusters
end end
def status_name def status_name
......
...@@ -8,4 +8,8 @@ class Clusters::Instance ...@@ -8,4 +8,8 @@ class Clusters::Instance
def feature_available?(feature) def feature_available?(feature)
::Feature.enabled?(feature, default_enabled: true) ::Feature.enabled?(feature, default_enabled: true)
end end
def instance_clusters_enabled?
::Feature.enabled?(:instance_clusters, default_enabled: true)
end
end end
...@@ -14,6 +14,7 @@ module DeploymentPlatform ...@@ -14,6 +14,7 @@ module DeploymentPlatform
def find_deployment_platform(environment) def find_deployment_platform(environment)
find_cluster_platform_kubernetes(environment: environment) || find_cluster_platform_kubernetes(environment: environment) ||
find_group_cluster_platform_kubernetes_with_feature_guard(environment: environment) || find_group_cluster_platform_kubernetes_with_feature_guard(environment: environment) ||
find_instance_cluster_platform_kubernetes_with_feature_guard(environment: environment) ||
find_kubernetes_service_integration || find_kubernetes_service_integration ||
build_cluster_and_deployment_platform build_cluster_and_deployment_platform
end end
...@@ -36,6 +37,22 @@ module DeploymentPlatform ...@@ -36,6 +37,22 @@ module DeploymentPlatform
.first&.platform_kubernetes .first&.platform_kubernetes
end end
def find_instance_cluster_platform_kubernetes_with_feature_guard(environment: nil)
return unless instance_clusters_enabled?
find_instance_cluster_platform_kubernetes(environment: environment)
end
# EE would override this and utilize environment argument
def find_instance_cluster_platform_kubernetes(environment: nil)
Clusters::Instance.new.clusters.enabled.default_environment
.first&.platform_kubernetes
end
def instance_clusters_enabled?
Feature.enabled?(:instance_clusters, default_enabled: true)
end
def find_kubernetes_service_integration def find_kubernetes_service_integration
services.deployment.reorder(nil).find_by(active: true) services.deployment.reorder(nil).find_by(active: true)
end end
......
...@@ -25,5 +25,13 @@ module EE ...@@ -25,5 +25,13 @@ module EE
.ancestor_clusters_for_clusterable(self, hierarchy_order: :desc) .ancestor_clusters_for_clusterable(self, hierarchy_order: :desc)
.last&.platform_kubernetes .last&.platform_kubernetes
end end
override :find_instance_cluster_platform_kubernetes
def find_instance_cluster_platform_kubernetes(environment: nil)
return super unless environment && feature_available?(:multiple_clusters)
Clusters::Instance.new.clusters.enabled.on_environment(environment)
.first&.platform_kubernetes
end
end end
end end
...@@ -122,6 +122,44 @@ describe EE::DeploymentPlatform do ...@@ -122,6 +122,44 @@ describe EE::DeploymentPlatform do
end end
end end
context 'with instance clusters' do
let!(:default_cluster) do
create(:cluster, :provided_by_user, :instance, environment_scope: '*')
end
let!(:cluster) do
create(:cluster, :provided_by_user, :instance, environment_scope: 'review/*')
end
let(:environment) { 'review/name' }
subject { project.deployment_platform(environment: environment) }
context 'when environment scope is exactly matched' do
before do
cluster.update!(environment_scope: 'review/name')
end
it_behaves_like 'matching environment scope'
end
context 'when environment scope is matched by wildcard' do
before do
cluster.update!(environment_scope: 'review/*')
end
it_behaves_like 'matching environment scope'
end
context 'when environment scope does not match' do
before do
cluster.update!(environment_scope: 'review/*/special')
end
it_behaves_like 'not matching environment scope'
end
end
context 'when environment is specified' do context 'when environment is specified' do
let!(:default_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: '*') } let!(:default_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: '*') }
let!(:cluster) { create(:cluster, :provided_by_user, environment_scope: 'review/*', projects: [project]) } let!(:cluster) { create(:cluster, :provided_by_user, environment_scope: 'review/*', projects: [project]) }
......
...@@ -8,11 +8,15 @@ describe ClusterAncestorsFinder, '#execute' do ...@@ -8,11 +8,15 @@ describe ClusterAncestorsFinder, '#execute' do
let(:user) { create(:user) } let(:user) { create(:user) }
let!(:project_cluster) do let!(:project_cluster) do
create(:cluster, :provided_by_user, cluster_type: :project_type, projects: [project]) create(:cluster, :provided_by_user, :project, projects: [project])
end end
let!(:group_cluster) do let!(:group_cluster) do
create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [group]) create(:cluster, :provided_by_user, :group, groups: [group])
end
let!(:instance_cluster) do
create(:cluster, :provided_by_user, :instance)
end end
subject { described_class.new(clusterable, user).execute } subject { described_class.new(clusterable, user).execute }
...@@ -25,7 +29,7 @@ describe ClusterAncestorsFinder, '#execute' do ...@@ -25,7 +29,7 @@ describe ClusterAncestorsFinder, '#execute' do
end end
it 'returns the project clusters followed by group clusters' do it 'returns the project clusters followed by group clusters' do
is_expected.to eq([project_cluster, group_cluster]) is_expected.to eq([project_cluster, group_cluster, instance_cluster])
end end
context 'nested groups', :nested_groups do context 'nested groups', :nested_groups do
...@@ -33,11 +37,11 @@ describe ClusterAncestorsFinder, '#execute' do ...@@ -33,11 +37,11 @@ describe ClusterAncestorsFinder, '#execute' do
let(:parent_group) { create(:group) } let(:parent_group) { create(:group) }
let!(:parent_group_cluster) do let!(:parent_group_cluster) do
create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [parent_group]) create(:cluster, :provided_by_user, :group, groups: [parent_group])
end end
it 'returns the project clusters followed by group clusters ordered ascending the hierarchy' do it 'returns the project clusters followed by group clusters ordered ascending the hierarchy' do
is_expected.to eq([project_cluster, group_cluster, parent_group_cluster]) is_expected.to eq([project_cluster, group_cluster, parent_group_cluster, instance_cluster])
end end
end end
end end
...@@ -58,7 +62,7 @@ describe ClusterAncestorsFinder, '#execute' do ...@@ -58,7 +62,7 @@ describe ClusterAncestorsFinder, '#execute' do
end end
it 'returns the list of group clusters' do it 'returns the list of group clusters' do
is_expected.to eq([group_cluster]) is_expected.to eq([group_cluster, instance_cluster])
end end
context 'nested groups', :nested_groups do context 'nested groups', :nested_groups do
...@@ -66,12 +70,21 @@ describe ClusterAncestorsFinder, '#execute' do ...@@ -66,12 +70,21 @@ describe ClusterAncestorsFinder, '#execute' do
let(:parent_group) { create(:group) } let(:parent_group) { create(:group) }
let!(:parent_group_cluster) do let!(:parent_group_cluster) do
create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [parent_group]) create(:cluster, :provided_by_user, :group, groups: [parent_group])
end end
it 'returns the list of group clusters ordered ascending the hierarchy' do it 'returns the list of group clusters ordered ascending the hierarchy' do
is_expected.to eq([group_cluster, parent_group_cluster]) is_expected.to eq([group_cluster, parent_group_cluster, instance_cluster])
end end
end end
end end
context 'for an instance' do
let(:clusterable) { Clusters::Instance.new }
let(:user) { create(:admin) }
it 'returns the list of instance clusters' do
is_expected.to eq([instance_cluster])
end
end
end end
...@@ -325,6 +325,15 @@ describe Clusters::Cluster do ...@@ -325,6 +325,15 @@ describe Clusters::Cluster do
end end
end end
context 'when group and instance have configured kubernetes clusters' do
let(:project) { create(:project, group: group) }
let!(:instance_cluster) { create(:cluster, :provided_by_gcp, :instance) }
it 'returns clusters in order, descending the hierachy' do
is_expected.to eq([group_cluster, instance_cluster])
end
end
context 'when sub-group has configured kubernetes cluster', :nested_groups do context 'when sub-group has configured kubernetes cluster', :nested_groups do
let(:sub_group_cluster) { create(:cluster, :provided_by_gcp, :group) } let(:sub_group_cluster) { create(:cluster, :provided_by_gcp, :group) }
let(:sub_group) { sub_group_cluster.group } let(:sub_group) { sub_group_cluster.group }
......
...@@ -9,6 +9,7 @@ describe Clusters::InstancePolicy do ...@@ -9,6 +9,7 @@ describe Clusters::InstancePolicy do
describe 'rules' do describe 'rules' do
context 'when user' do context 'when user' do
it { expect(policy).to be_disallowed :read_cluster }
it { expect(policy).to be_disallowed :update_cluster } it { expect(policy).to be_disallowed :update_cluster }
it { expect(policy).to be_disallowed :admin_cluster } it { expect(policy).to be_disallowed :admin_cluster }
end end
...@@ -16,6 +17,7 @@ describe Clusters::InstancePolicy do ...@@ -16,6 +17,7 @@ describe Clusters::InstancePolicy do
context 'when admin' do context 'when admin' do
let(:user) { create(:admin) } let(:user) { create(:admin) }
it { expect(policy).to be_allowed :read_cluster }
it { expect(policy).to be_allowed :update_cluster } it { expect(policy).to be_allowed :update_cluster }
it { expect(policy).to be_allowed :admin_cluster } it { expect(policy).to be_allowed :admin_cluster }
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