summaryrefslogtreecommitdiff
path: root/spec/models/clusters
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/clusters')
-rw-r--r--spec/models/clusters/applications/knative_spec.rb76
-rw-r--r--spec/models/clusters/cluster_spec.rb230
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb29
-rw-r--r--spec/models/clusters/project_spec.rb1
4 files changed, 168 insertions, 168 deletions
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index d5974f47190..b38cf96de7e 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -3,9 +3,6 @@
require 'rails_helper'
describe Clusters::Applications::Knative do
- include KubernetesHelpers
- include ReactiveCachingHelpers
-
let(:knative) { create(:clusters_applications_knative) }
include_examples 'cluster application core specs', :clusters_applications_knative
@@ -146,77 +143,4 @@ describe Clusters::Applications::Knative do
describe 'validations' do
it { is_expected.to validate_presence_of(:hostname) }
end
-
- describe '#service_pod_details' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:service) { cluster.platform_kubernetes }
- let(:knative) { create(:clusters_applications_knative, cluster: cluster) }
-
- let(:namespace) do
- create(:cluster_kubernetes_namespace,
- cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
- end
-
- before do
- stub_kubeclient_discover(service.api_url)
- stub_kubeclient_knative_services
- stub_kubeclient_service_pods
- stub_reactive_cache(knative,
- {
- services: kube_response(kube_knative_services_body),
- pods: kube_response(kube_knative_pods_body(cluster.cluster_project.project.name, namespace.namespace))
- })
- synchronous_reactive_cache(knative)
- end
-
- it 'is able k8s core for pod details' do
- expect(knative.service_pod_details(namespace.namespace, cluster.cluster_project.project.name)).not_to be_nil
- end
- end
-
- describe '#services' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:service) { cluster.platform_kubernetes }
- let(:knative) { create(:clusters_applications_knative, cluster: cluster) }
-
- let(:namespace) do
- create(:cluster_kubernetes_namespace,
- cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
- end
-
- subject { knative.services }
-
- before do
- stub_kubeclient_discover(service.api_url)
- stub_kubeclient_knative_services
- stub_kubeclient_service_pods
- end
-
- it 'has an unintialized cache' do
- is_expected.to be_nil
- end
-
- context 'when using synchronous reactive cache' do
- before do
- stub_reactive_cache(knative,
- {
- services: kube_response(kube_knative_services_body),
- pods: kube_response(kube_knative_pods_body(cluster.cluster_project.project.name, namespace.namespace))
- })
- synchronous_reactive_cache(knative)
- end
-
- it 'has cached services' do
- is_expected.not_to be_nil
- end
-
- it 'matches our namespace' do
- expect(knative.services_for(ns: namespace)).not_to be_nil
- end
- end
- end
end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 58203da5b22..f206bb41f45 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -2,9 +2,14 @@
require 'spec_helper'
-describe Clusters::Cluster do
+describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
+ include ReactiveCachingHelpers
+ include KubernetesHelpers
+
it_behaves_like 'having unique enum values'
+ subject { build(:cluster) }
+
it { is_expected.to belong_to(:user) }
it { is_expected.to have_many(:cluster_projects) }
it { is_expected.to have_many(:projects) }
@@ -17,12 +22,10 @@ describe Clusters::Cluster do
it { is_expected.to have_one(:application_prometheus) }
it { is_expected.to have_one(:application_runner) }
it { is_expected.to have_many(:kubernetes_namespaces) }
- it { is_expected.to have_one(:kubernetes_namespace) }
it { is_expected.to have_one(:cluster_project) }
it { is_expected.to delegate_method(:status).to(:provider) }
it { is_expected.to delegate_method(:status_reason).to(:provider) }
- it { is_expected.to delegate_method(:status_name).to(:provider) }
it { is_expected.to delegate_method(:on_creation?).to(:provider) }
it { is_expected.to delegate_method(:active?).to(:platform_kubernetes).with_prefix }
it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix }
@@ -35,6 +38,11 @@ describe Clusters::Cluster do
it { is_expected.to respond_to :project }
+ it do
+ expect(subject.knative_services_finder(subject.project))
+ .to be_instance_of(Clusters::KnativeServicesFinder)
+ end
+
describe '.enabled' do
subject { described_class.enabled }
@@ -500,28 +508,6 @@ describe Clusters::Cluster do
end
end
- describe '#created?' do
- let(:cluster) { create(:cluster, :provided_by_gcp) }
-
- subject { cluster.created? }
-
- context 'when status_name is :created' do
- before do
- allow(cluster).to receive_message_chain(:provider, :status_name).and_return(:created)
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'when status_name is not :created' do
- before do
- allow(cluster).to receive_message_chain(:provider, :status_name).and_return(:creating)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
describe '#allow_user_defined_namespace?' do
let(:cluster) { create(:cluster, :provided_by_gcp) }
@@ -556,62 +542,15 @@ describe Clusters::Cluster do
end
context 'with no domain on cluster' do
- context 'with a project cluster' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- context 'with domain set at instance level' do
- before do
- stub_application_setting(auto_devops_domain: 'global_domain.com')
-
- it { is_expected.to eq('global_domain.com') }
- end
- end
-
- context 'with domain set on ProjectAutoDevops' do
- before do
- auto_devops = project.build_auto_devops(domain: 'legacy-ado-domain.com')
- auto_devops.save
- end
-
- it { is_expected.to eq('legacy-ado-domain.com') }
- end
-
- context 'with domain set as environment variable on project' do
- before do
- variable = project.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'project-ado-domain.com')
- variable.save
- end
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
- it { is_expected.to eq('project-ado-domain.com') }
+ context 'with domain set at instance level' do
+ before do
+ stub_application_setting(auto_devops_domain: 'global_domain.com')
end
- context 'with domain set as environment variable on the group project' do
- let(:group) { create(:group) }
-
- before do
- project.update(parent_id: group.id)
- variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com')
- variable.save
- end
-
- it { is_expected.to eq('group-ado-domain.com') }
- end
- end
-
- context 'with a group cluster' do
- let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
-
- context 'with domain set as environment variable for the group' do
- let(:group) { cluster.group }
-
- before do
- variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com')
- variable.save
- end
-
- it { is_expected.to eq('group-ado-domain.com') }
- end
+ it { is_expected.to eq('global_domain.com') }
end
end
end
@@ -663,4 +602,139 @@ describe Clusters::Cluster do
it { is_expected.to be_truthy }
end
end
+
+ describe '#status_name' do
+ subject { cluster.status_name }
+
+ context 'the cluster has a provider' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ before do
+ cluster.provider.make_errored!
+ end
+
+ it { is_expected.to eq :errored }
+ end
+
+ context 'there is a cached connection status' do
+ let(:cluster) { create(:cluster, :provided_by_user) }
+
+ before do
+ allow(cluster).to receive(:connection_status).and_return(:connected)
+ end
+
+ it { is_expected.to eq :connected }
+ end
+
+ context 'there is no connection status in the cache' do
+ let(:cluster) { create(:cluster, :provided_by_user) }
+
+ before do
+ allow(cluster).to receive(:connection_status).and_return(nil)
+ end
+
+ it { is_expected.to eq :created }
+ end
+ end
+
+ describe '#connection_status' do
+ let(:cluster) { create(:cluster) }
+ let(:status) { :connected }
+
+ subject { cluster.connection_status }
+
+ it { is_expected.to be_nil }
+
+ context 'with a cached status' do
+ before do
+ stub_reactive_cache(cluster, connection_status: status)
+ end
+
+ it { is_expected.to eq(status) }
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ subject { cluster.calculate_reactive_cache }
+
+ context 'cluster is disabled' do
+ let(:cluster) { create(:cluster, :disabled) }
+
+ it 'does not populate the cache' do
+ expect(cluster).not_to receive(:retrieve_connection_status)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'cluster is enabled' do
+ let(:cluster) { create(:cluster, :provided_by_user, :group) }
+
+ context 'connection to the cluster is successful' do
+ before do
+ stub_kubeclient_discover(cluster.platform.api_url)
+ end
+
+ it { is_expected.to eq(connection_status: :connected) }
+ end
+
+ context 'cluster cannot be reached' do
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(SocketError)
+ end
+
+ it { is_expected.to eq(connection_status: :unreachable) }
+ end
+
+ context 'cluster cannot be authenticated to' do
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(OpenSSL::X509::CertificateError.new("Certificate error"))
+ end
+
+ it { is_expected.to eq(connection_status: :authentication_failure) }
+ end
+
+ describe 'Kubeclient::HttpError' do
+ let(:error_code) { 403 }
+ let(:error_message) { "Forbidden" }
+
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(Kubeclient::HttpError.new(error_code, error_message, nil))
+ end
+
+ it { is_expected.to eq(connection_status: :authentication_failure) }
+
+ context 'generic timeout' do
+ let(:error_message) { 'Timed out connecting to server'}
+
+ it { is_expected.to eq(connection_status: :unreachable) }
+ end
+
+ context 'gateway timeout' do
+ let(:error_message) { '504 Gateway Timeout for GET https://kubernetes.example.com/api/v1'}
+
+ it { is_expected.to eq(connection_status: :unreachable) }
+ end
+ end
+
+ context 'an uncategorised error is raised' do
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(StandardError)
+ end
+
+ it { is_expected.to eq(connection_status: :unknown_failure) }
+
+ it 'notifies Sentry' do
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception)
+ .with(instance_of(StandardError), hash_including(extra: { cluster_id: cluster.id }))
+
+ subject
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index e35d14f2282..c485850c16e 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -15,10 +15,8 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to validate_presence_of(:api_url) }
it { is_expected.to validate_presence_of(:token) }
- it { is_expected.to delegate_method(:project).to(:cluster) }
it { is_expected.to delegate_method(:enabled?).to(:cluster) }
it { is_expected.to delegate_method(:provided_by_user?).to(:cluster) }
- it { is_expected.to delegate_method(:kubernetes_namespace).to(:cluster) }
it_behaves_like 'having unique enum values'
@@ -209,7 +207,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to be_truthy }
end
- describe '#actual_namespace' do
+ describe '#kubernetes_namespace_for' do
let(:cluster) { create(:cluster, :project) }
let(:project) { cluster.project }
@@ -219,7 +217,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
namespace: namespace)
end
- subject { platform.actual_namespace }
+ subject { platform.kubernetes_namespace_for(project) }
context 'with a namespace assigned' do
let(:namespace) { 'namespace-123' }
@@ -305,8 +303,6 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
context 'no namespace provided' do
- let(:namespace) { kubernetes.actual_namespace }
-
it_behaves_like 'setting variables'
it 'sets KUBE_TOKEN' do
@@ -389,7 +385,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
context 'with valid pods' do
- let(:pod) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug) }
+ let(:pod) { kube_pod(environment_slug: environment.slug, namespace: cluster.kubernetes_namespace_for(project), project_slug: project.full_path_slug) }
let(:pod_with_no_terminal) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug, status: "Pending") }
let(:terminals) { kube_terminals(service, pod) }
@@ -419,6 +415,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
let!(:cluster) { create(:cluster, :project, enabled: enabled, platform_kubernetes: service) }
let(:service) { create(:cluster_platform_kubernetes, :configured) }
let(:enabled) { true }
+ let(:namespace) { cluster.kubernetes_namespace_for(cluster.project) }
context 'when cluster is disabled' do
let(:enabled) { false }
@@ -428,8 +425,8 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when kubernetes responds with valid pods and deployments' do
before do
- stub_kubeclient_pods
- stub_kubeclient_deployments
+ stub_kubeclient_pods(namespace)
+ stub_kubeclient_deployments(namespace)
end
it { is_expected.to include(pods: [kube_pod]) }
@@ -437,8 +434,8 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when kubernetes responds with 500s' do
before do
- stub_kubeclient_pods(status: 500)
- stub_kubeclient_deployments(status: 500)
+ stub_kubeclient_pods(namespace, status: 500)
+ stub_kubeclient_deployments(namespace, status: 500)
end
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
@@ -446,12 +443,18 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when kubernetes responds with 404s' do
before do
- stub_kubeclient_pods(status: 404)
- stub_kubeclient_deployments(status: 404)
+ stub_kubeclient_pods(namespace, status: 404)
+ stub_kubeclient_deployments(namespace, status: 404)
end
it { is_expected.to include(pods: []) }
end
+
+ context 'when the cluster is not project level' do
+ let(:cluster) { create(:cluster, :group, platform_kubernetes: service) }
+
+ it { is_expected.to include(pods: []) }
+ end
end
describe '#update_kubernetes_namespace' do
diff --git a/spec/models/clusters/project_spec.rb b/spec/models/clusters/project_spec.rb
index 2f017e69251..671af085d10 100644
--- a/spec/models/clusters/project_spec.rb
+++ b/spec/models/clusters/project_spec.rb
@@ -6,5 +6,4 @@ describe Clusters::Project do
it { is_expected.to belong_to(:cluster) }
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:kubernetes_namespaces) }
- it { is_expected.to have_one(:kubernetes_namespace) }
end