398 lines
13 KiB
Ruby
398 lines
13 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe DeploymentPlatform do
|
|
let(:project) { create(:project) }
|
|
|
|
describe '#deployment_platform' do
|
|
subject { project.deployment_platform }
|
|
|
|
context 'multiple clusters' do
|
|
let(:group) { create(:group) }
|
|
let(:project) { create(:project, group: group) }
|
|
|
|
shared_examples 'certificate_based_clusters is disabled' do
|
|
before do
|
|
stub_feature_flags(certificate_based_clusters: false)
|
|
end
|
|
|
|
it { is_expected.to be_nil }
|
|
end
|
|
|
|
shared_examples 'matching environment scope' do
|
|
it 'returns environment specific cluster' do
|
|
is_expected.to eq(cluster.platform_kubernetes)
|
|
end
|
|
|
|
it_behaves_like 'certificate_based_clusters is disabled'
|
|
end
|
|
|
|
shared_examples 'not matching environment scope' do
|
|
it 'returns default cluster' do
|
|
is_expected.to eq(default_cluster.platform_kubernetes)
|
|
end
|
|
|
|
it_behaves_like 'certificate_based_clusters is disabled'
|
|
end
|
|
|
|
context 'multiple clusters use the same management project' do
|
|
let(:management_project) { create(:project, group: group) }
|
|
|
|
let!(:default_cluster) do
|
|
create(:cluster_for_group, groups: [group], environment_scope: '*', management_project: management_project)
|
|
end
|
|
|
|
let!(:cluster) do
|
|
create(:cluster_for_group, groups: [group], environment_scope: 'review/*', management_project: management_project)
|
|
end
|
|
|
|
let(:environment) { 'review/name' }
|
|
|
|
subject { management_project.deployment_platform(environment: environment) }
|
|
|
|
it_behaves_like 'matching environment scope'
|
|
end
|
|
|
|
context 'when project does not have a cluster but has group clusters' do
|
|
let!(:default_cluster) do
|
|
create(
|
|
:cluster,
|
|
:provided_by_user,
|
|
cluster_type: :group_type,
|
|
groups: [group],
|
|
environment_scope: '*'
|
|
)
|
|
end
|
|
|
|
let!(:cluster) do
|
|
create(
|
|
:cluster,
|
|
:provided_by_user,
|
|
cluster_type: :group_type,
|
|
environment_scope: 'review/*',
|
|
groups: [group]
|
|
)
|
|
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
|
|
|
|
context 'when group belongs to a parent group' do
|
|
let(:parent_group) { create(:group) }
|
|
let(:group) { create(:group, parent: parent_group) }
|
|
|
|
context 'when parent_group has a cluster with default scope' do
|
|
let!(:parent_group_cluster) do
|
|
create(
|
|
:cluster,
|
|
:provided_by_user,
|
|
cluster_type: :group_type,
|
|
environment_scope: '*',
|
|
groups: [parent_group]
|
|
)
|
|
end
|
|
|
|
it_behaves_like 'matching environment scope'
|
|
end
|
|
|
|
context 'when parent_group has a cluster that is an exact match' do
|
|
let!(:parent_group_cluster) do
|
|
create(
|
|
:cluster,
|
|
:provided_by_user,
|
|
cluster_type: :group_type,
|
|
environment_scope: 'review/name',
|
|
groups: [parent_group]
|
|
)
|
|
end
|
|
|
|
it_behaves_like 'matching environment scope'
|
|
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
|
|
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!(:group_default_cluster) do
|
|
create(
|
|
:cluster,
|
|
:provided_by_user,
|
|
cluster_type: :group_type,
|
|
groups: [group],
|
|
environment_scope: '*'
|
|
)
|
|
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
|
|
|
|
context 'when environment scope has _' do
|
|
it 'does not treat it as wildcard' do
|
|
cluster.update!(environment_scope: 'foo_bar/*')
|
|
|
|
is_expected.to eq(default_cluster.platform_kubernetes)
|
|
end
|
|
|
|
context 'when environment name contains an underscore' do
|
|
let(:environment) { 'foo_bar/test' }
|
|
|
|
it 'matches literally for _' do
|
|
cluster.update!(environment_scope: 'foo_bar/*')
|
|
|
|
is_expected.to eq(cluster.platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
|
|
# The environment name and scope cannot have % at the moment,
|
|
# but we're considering relaxing it and we should also make sure
|
|
# it doesn't break in case some data sneaked in somehow as we're
|
|
# not checking this integrity in database level.
|
|
context 'when environment scope has %' do
|
|
it 'does not treat it as wildcard' do
|
|
cluster.update_attribute(:environment_scope, '*%*')
|
|
|
|
is_expected.to eq(default_cluster.platform_kubernetes)
|
|
end
|
|
|
|
context 'when environment name contains a percent char' do
|
|
let(:environment) { 'foo%bar/test' }
|
|
|
|
it 'matches literally for %' do
|
|
cluster.update_attribute(:environment_scope, 'foo%bar/*')
|
|
|
|
is_expected.to eq(cluster.platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when perfectly matched cluster exists' do
|
|
let!(:perfectly_matched_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: 'review/name') }
|
|
|
|
it 'returns perfectly matched cluster as highest precedence' do
|
|
is_expected.to eq(perfectly_matched_cluster.platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with multiple clusters and multiple environments' do
|
|
let!(:cluster_1) { create(:cluster, :provided_by_user, projects: [project], environment_scope: 'staging/*') }
|
|
let!(:cluster_2) { create(:cluster, :provided_by_user, projects: [project], environment_scope: 'test/*') }
|
|
|
|
let(:environment_1) { 'staging/name' }
|
|
let(:environment_2) { 'test/name' }
|
|
|
|
it 'returns the appropriate cluster' do
|
|
expect(project.deployment_platform(environment: environment_1)).to eq(cluster_1.platform_kubernetes)
|
|
expect(project.deployment_platform(environment: environment_2)).to eq(cluster_2.platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with no Kubernetes configuration on CI/CD, no Kubernetes Service' do
|
|
it { is_expected.to be_nil }
|
|
end
|
|
|
|
context 'when project is the cluster\'s management project ' do
|
|
let(:another_project) { create(:project, namespace: project.namespace) }
|
|
|
|
let!(:cluster_with_management_project) do
|
|
create(:cluster, :provided_by_user, projects: [another_project], management_project: project)
|
|
end
|
|
|
|
it 'returns the cluster with management project' do
|
|
is_expected.to eq(cluster_with_management_project.platform_kubernetes)
|
|
end
|
|
end
|
|
|
|
context 'when project has configured kubernetes from CI/CD > Clusters' do
|
|
let!(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
|
|
let(:platform_kubernetes) { cluster.platform_kubernetes }
|
|
|
|
it 'returns the Kubernetes platform' do
|
|
expect(subject).to eq(platform_kubernetes)
|
|
end
|
|
|
|
context 'with a group level kubernetes cluster' do
|
|
let(:group_cluster) { create(:cluster, :provided_by_gcp, :group) }
|
|
|
|
before do
|
|
project.update!(group: group_cluster.group)
|
|
end
|
|
|
|
it 'returns the Kubernetes platform from the project cluster' do
|
|
expect(subject).to eq(platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when group has configured kubernetes cluster' do
|
|
let!(:group_cluster) { create(:cluster, :provided_by_gcp, :group) }
|
|
let(:group) { group_cluster.group }
|
|
|
|
before do
|
|
project.update!(group: group)
|
|
end
|
|
|
|
it 'returns the Kubernetes platform' do
|
|
is_expected.to eq(group_cluster.platform_kubernetes)
|
|
end
|
|
|
|
context 'when project is the cluster\'s management project ' do
|
|
let(:another_project) { create(:project, namespace: project.namespace) }
|
|
|
|
let!(:cluster_with_management_project) do
|
|
create(:cluster, :provided_by_user, projects: [another_project], management_project: project)
|
|
end
|
|
|
|
it 'returns the cluster with management project' do
|
|
is_expected.to eq(cluster_with_management_project.platform_kubernetes)
|
|
end
|
|
end
|
|
|
|
context 'when project is not the cluster\'s management project' do
|
|
let(:another_project) { create(:project, group: group) }
|
|
let!(:cluster_with_management_project) { create(:cluster, :provided_by_user, management_project: another_project) }
|
|
|
|
it 'returns the group cluster' do
|
|
is_expected.to eq(group_cluster.platform_kubernetes)
|
|
end
|
|
end
|
|
|
|
context 'when child group has configured kubernetes cluster' do
|
|
let(:child_group1) { create(:group, parent: group) }
|
|
let!(:child_group1_cluster) { create(:cluster_for_group, groups: [child_group1]) }
|
|
|
|
before do
|
|
project.update!(group: child_group1)
|
|
end
|
|
|
|
it 'returns the Kubernetes platform for the child group' do
|
|
is_expected.to eq(child_group1_cluster.platform_kubernetes)
|
|
end
|
|
|
|
context 'deeply nested group' do
|
|
let(:child_group2) { create(:group, parent: child_group1) }
|
|
let!(:child_group2_cluster) { create(:cluster_for_group, groups: [child_group2]) }
|
|
|
|
before do
|
|
project.update!(group: child_group2)
|
|
end
|
|
|
|
it 'returns most nested group cluster Kubernetes platform' do
|
|
is_expected.to eq(child_group2_cluster.platform_kubernetes)
|
|
end
|
|
|
|
context 'cluster in the middle of hierarchy is disabled' do
|
|
before do
|
|
child_group2_cluster.update!(enabled: false)
|
|
end
|
|
|
|
it 'returns closest enabled Kubenetes platform' do
|
|
is_expected.to eq(child_group1_cluster.platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when instance has configured kubernetes cluster' do
|
|
let!(:instance_cluster) { create(:cluster, :provided_by_user, :instance) }
|
|
|
|
it 'returns the Kubernetes platform' do
|
|
is_expected.to eq(instance_cluster.platform_kubernetes)
|
|
end
|
|
end
|
|
end
|
|
end
|