gitlab-org--gitlab-foss/spec/models/concerns/deployment_platform_spec.rb

361 lines
12 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 'matching environment scope' do
it 'returns environment specific cluster' do
is_expected.to eq(cluster.platform_kubernetes)
end
end
shared_examples 'not matching environment scope' do
it 'returns default cluster' do
is_expected.to eq(default_cluster.platform_kubernetes)
end
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