diff options
Diffstat (limited to 'spec/services/clusters')
4 files changed, 267 insertions, 25 deletions
diff --git a/spec/services/clusters/applications/check_installation_progress_service_spec.rb b/spec/services/clusters/applications/check_installation_progress_service_spec.rb index 45b8ce94815..19446ce1cf8 100644 --- a/spec/services/clusters/applications/check_installation_progress_service_spec.rb +++ b/spec/services/clusters/applications/check_installation_progress_service_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Clusters::Applications::CheckInstallationProgressService do +describe Clusters::Applications::CheckInstallationProgressService, '#execute' do RESCHEDULE_PHASES = Gitlab::Kubernetes::Pod::PHASES - [Gitlab::Kubernetes::Pod::SUCCEEDED, Gitlab::Kubernetes::Pod::FAILED].freeze let(:application) { create(:clusters_applications_helm, :installing) } @@ -21,24 +21,39 @@ describe Clusters::Applications::CheckInstallationProgressService do expect(ClusterWaitForAppInstallationWorker).to receive(:perform_in).once expect(service).not_to receive(:remove_installation_pod) - service.execute + expect do + service.execute + + application.reload + end.not_to change(application, :status) - expect(application).to be_installing expect(application.status_reason).to be_nil end end + end + end - context 'when timeouted' do - let(:application) { create(:clusters_applications_helm, :timeouted) } + shared_examples 'error logging' do + context 'when installation raises a Kubeclient::HttpError' do + let(:cluster) { create(:cluster, :provided_by_user, :project) } - it 'make the application errored' do - expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in) + before do + application.update!(cluster: cluster) - service.execute + expect(service).to receive(:installation_phase).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil)) + end - expect(application).to be_errored - expect(application.status_reason).to eq("Installation timed out. Check pod logs for install-helm for more details.") - end + it 'shows the response code from the error' do + service.execute + + expect(application).to be_errored.or(be_update_errored) + expect(application.status_reason).to eq('Kubernetes error: 401') + end + + it 'should log error' do + expect(service.send(:logger)).to receive(:error) + + service.execute end end end @@ -48,10 +63,15 @@ describe Clusters::Applications::CheckInstallationProgressService do allow(service).to receive(:remove_installation_pod).and_return(nil) end - describe '#execute' do + context 'when application is updating' do + let(:application) { create(:clusters_applications_helm, :updating) } + + include_examples 'error logging' + + RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase } + context 'when installation POD succeeded' do let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED } - before do expect(service).to receive(:installation_phase).once.and_return(phase) end @@ -67,7 +87,7 @@ describe Clusters::Applications::CheckInstallationProgressService do service.execute - expect(application).to be_installed + expect(application).to be_updated expect(application.status_reason).to be_nil end end @@ -83,33 +103,86 @@ describe Clusters::Applications::CheckInstallationProgressService do it 'make the application errored' do service.execute - expect(application).to be_errored - expect(application.status_reason).to eq("Installation failed. Check pod logs for install-helm for more details.") + expect(application).to be_update_errored + expect(application.status_reason).to eq('Operation failed. Check pod logs for install-helm for more details.') end end - RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase } + context 'when timed out' do + let(:application) { create(:clusters_applications_helm, :timeouted, :updating) } - context 'when installation raises a Kubeclient::HttpError' do - let(:cluster) { create(:cluster, :provided_by_user, :project) } + before do + expect(service).to receive(:installation_phase).once.and_return(phase) + end + + it 'make the application errored' do + expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in) + + service.execute + + expect(application).to be_update_errored + expect(application.status_reason).to eq('Operation timed out. Check pod logs for install-helm for more details.') + end + end + end + + context 'when application is installing' do + include_examples 'error logging' + + RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase } + context 'when installation POD succeeded' do + let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED } before do - application.update!(cluster: cluster) + expect(service).to receive(:installation_phase).once.and_return(phase) + end - expect(service).to receive(:installation_phase).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil)) + it 'removes the installation POD' do + expect(service).to receive(:remove_installation_pod).once + + service.execute end - it 'shows the response code from the error' do + it 'make the application installed' do + expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in) + + service.execute + + expect(application).to be_installed + expect(application.status_reason).to be_nil + end + end + + context 'when installation POD failed' do + let(:phase) { Gitlab::Kubernetes::Pod::FAILED } + let(:errors) { 'test installation failed' } + + before do + expect(service).to receive(:installation_phase).once.and_return(phase) + end + + it 'make the application errored' do service.execute expect(application).to be_errored - expect(application.status_reason).to eq('Kubernetes error: 401') + expect(application.status_reason).to eq('Operation failed. Check pod logs for install-helm for more details.') + end + end + + context 'when timed out' do + let(:application) { create(:clusters_applications_helm, :timeouted) } + + before do + expect(service).to receive(:installation_phase).once.and_return(phase) end - it 'should log error' do - expect(service.send(:logger)).to receive(:error) + it 'make the application errored' do + expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in) service.execute + + expect(application).to be_errored + expect(application.status_reason).to eq('Operation timed out. Check pod logs for install-helm for more details.') end end end diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb index 1a2ca23748a..3f621ed5944 100644 --- a/spec/services/clusters/applications/create_service_spec.rb +++ b/spec/services/clusters/applications/create_service_spec.rb @@ -13,6 +13,7 @@ describe Clusters::Applications::CreateService do describe '#execute' do before do allow(ClusterInstallAppWorker).to receive(:perform_async) + allow(ClusterUpgradeAppWorker).to receive(:perform_async) end subject { service.execute(test_request) } @@ -31,6 +32,22 @@ describe Clusters::Applications::CreateService do subject end + context 'application already installed' do + let!(:application) { create(:clusters_applications_helm, :installed, cluster: cluster) } + + it 'does not create a new application' do + expect do + subject + end.not_to change(Clusters::Applications::Helm, :count) + end + + it 'schedules an upgrade for the application' do + expect(Clusters::Applications::ScheduleInstallationService).to receive(:new).with(application).and_call_original + + subject + end + end + context 'cert manager application' do let(:params) do { diff --git a/spec/services/clusters/applications/schedule_installation_service_spec.rb b/spec/services/clusters/applications/schedule_installation_service_spec.rb index 21797edd533..8380932dfaa 100644 --- a/spec/services/clusters/applications/schedule_installation_service_spec.rb +++ b/spec/services/clusters/applications/schedule_installation_service_spec.rb @@ -49,5 +49,29 @@ describe Clusters::Applications::ScheduleInstallationService do it_behaves_like 'a failing service' end + + context 'when application is installed' do + let(:application) { create(:clusters_applications_helm, :installed) } + + it 'schedules an upgrade via worker' do + expect(ClusterUpgradeAppWorker).to receive(:perform_async).with(application.name, application.id).once + + service.execute + + expect(application).to be_scheduled + end + end + + context 'when application is updated' do + let(:application) { create(:clusters_applications_helm, :updated) } + + it 'schedules an upgrade via worker' do + expect(ClusterUpgradeAppWorker).to receive(:perform_async).with(application.name, application.id).once + + service.execute + + expect(application).to be_scheduled + end + end end end diff --git a/spec/services/clusters/applications/upgrade_service_spec.rb b/spec/services/clusters/applications/upgrade_service_spec.rb new file mode 100644 index 00000000000..1822fc38dbd --- /dev/null +++ b/spec/services/clusters/applications/upgrade_service_spec.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Clusters::Applications::UpgradeService do + describe '#execute' do + let(:application) { create(:clusters_applications_helm, :scheduled) } + let!(:install_command) { application.install_command } + let(:service) { described_class.new(application) } + let(:helm_client) { instance_double(Gitlab::Kubernetes::Helm::Api) } + + before do + allow(service).to receive(:install_command).and_return(install_command) + allow(service).to receive(:helm_api).and_return(helm_client) + end + + context 'when there are no errors' do + before do + expect(helm_client).to receive(:update).with(install_command) + allow(ClusterWaitForAppInstallationWorker).to receive(:perform_in).and_return(nil) + end + + it 'make the application updating' do + expect(application.cluster).not_to be_nil + service.execute + + expect(application).to be_updating + end + + it 'schedule async installation status check' do + expect(ClusterWaitForAppInstallationWorker).to receive(:perform_in).once + + service.execute + end + end + + context 'when kubernetes cluster communication fails' do + let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) } + + before do + expect(helm_client).to receive(:update).with(install_command).and_raise(error) + end + + it 'make the application errored' do + service.execute + + expect(application).to be_update_errored + expect(application.status_reason).to match('Kubernetes error: 500') + end + + it 'logs errors' do + expect(service.send(:logger)).to receive(:error).with( + { + exception: 'Kubeclient::HttpError', + message: 'system failure', + service: 'Clusters::Applications::UpgradeService', + app_id: application.id, + project_ids: application.cluster.project_ids, + group_ids: [], + error_code: 500 + } + ) + + expect(Gitlab::Sentry).to receive(:track_acceptable_exception).with( + error, + extra: { + exception: 'Kubeclient::HttpError', + message: 'system failure', + service: 'Clusters::Applications::UpgradeService', + app_id: application.id, + project_ids: application.cluster.project_ids, + group_ids: [], + error_code: 500 + } + ) + + service.execute + end + end + + context 'a non kubernetes error happens' do + let(:application) { create(:clusters_applications_helm, :scheduled) } + let(:error) { StandardError.new('something bad happened') } + + before do + expect(application).to receive(:make_updating!).once.and_raise(error) + end + + it 'make the application errored' do + expect(helm_client).not_to receive(:update) + + service.execute + + expect(application).to be_update_errored + expect(application.status_reason).to eq("Can't start upgrade process.") + end + + it 'logs errors' do + expect(service.send(:logger)).to receive(:error).with( + { + exception: 'StandardError', + error_code: nil, + message: 'something bad happened', + service: 'Clusters::Applications::UpgradeService', + app_id: application.id, + project_ids: application.cluster.projects.pluck(:id), + group_ids: [] + } + ) + + expect(Gitlab::Sentry).to receive(:track_acceptable_exception).with( + error, + extra: { + exception: 'StandardError', + error_code: nil, + message: 'something bad happened', + service: 'Clusters::Applications::UpgradeService', + app_id: application.id, + project_ids: application.cluster.projects.pluck(:id), + group_ids: [] + } + ) + + service.execute + end + end + end +end |