diff options
Diffstat (limited to 'spec/models/clusters')
-rw-r--r-- | spec/models/clusters/applications/knative_spec.rb | 76 | ||||
-rw-r--r-- | spec/models/clusters/cluster_spec.rb | 230 | ||||
-rw-r--r-- | spec/models/clusters/platforms/kubernetes_spec.rb | 29 | ||||
-rw-r--r-- | spec/models/clusters/project_spec.rb | 1 |
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 |