Commit 5d16ee7b authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'kubernetes-http-response-code' into 'master'

Show HTTP response code for Kubernetes errors

Closes #53628

See merge request gitlab-org/gitlab-ce!22964
parents f2ef5e2e 14b3033a
...@@ -173,9 +173,7 @@ module Clusters ...@@ -173,9 +173,7 @@ module Clusters
kubeclient = build_kube_client! kubeclient = build_kube_client!
kubeclient.get_pods(namespace: actual_namespace).as_json kubeclient.get_pods(namespace: actual_namespace).as_json
rescue Kubeclient::HttpError => err rescue Kubeclient::ResourceNotFoundError
raise err unless err.error_code == 404
[] []
end end
......
...@@ -203,9 +203,7 @@ class KubernetesService < DeploymentService ...@@ -203,9 +203,7 @@ class KubernetesService < DeploymentService
kubeclient = build_kube_client! kubeclient = build_kube_client!
kubeclient.get_pods(namespace: actual_namespace).as_json kubeclient.get_pods(namespace: actual_namespace).as_json
rescue Kubeclient::HttpError => err rescue Kubeclient::ResourceNotFoundError
raise err unless err.error_code == 404
[] []
end end
......
...@@ -15,8 +15,8 @@ module Clusters ...@@ -15,8 +15,8 @@ module Clusters
check_timeout check_timeout
end end
rescue Kubeclient::HttpError => e rescue Kubeclient::HttpError => e
Rails.logger.error "Kubernetes error: #{e.class.name} #{e.message}" Rails.logger.error("Kubernetes error: #{e.error_code} #{e.message}")
app.make_errored!("Kubernetes error") unless app.errored? app.make_errored!("Kubernetes error: #{e.error_code}") unless app.errored?
end end
private private
...@@ -53,7 +53,7 @@ module Clusters ...@@ -53,7 +53,7 @@ module Clusters
def remove_installation_pod def remove_installation_pod
helm_api.delete_pod!(install_command.pod_name) helm_api.delete_pod!(install_command.pod_name)
rescue => e rescue => e
Rails.logger.error "Kubernetes error: #{e.class.name} #{e.message}" Rails.logger.error("Kubernetes error: #{e.class.name} #{e.message}")
# no-op # no-op
end end
......
...@@ -13,8 +13,8 @@ module Clusters ...@@ -13,8 +13,8 @@ module Clusters
ClusterWaitForAppInstallationWorker.perform_in( ClusterWaitForAppInstallationWorker.perform_in(
ClusterWaitForAppInstallationWorker::INTERVAL, app.name, app.id) ClusterWaitForAppInstallationWorker::INTERVAL, app.name, app.id)
rescue Kubeclient::HttpError => e rescue Kubeclient::HttpError => e
Rails.logger.error "Kubernetes error: #{e.class.name} #{e.message}" Rails.logger.error("Kubernetes error: #{e.error_code} #{e.message}")
app.make_errored!("Kubernetes error.") app.make_errored!("Kubernetes error: #{e.error_code}")
rescue StandardError => e rescue StandardError => e
Rails.logger.error "Can't start installation process: #{e.class.name} #{e.message}" Rails.logger.error "Can't start installation process: #{e.class.name} #{e.message}"
app.make_errored!("Can't start installation process.") app.make_errored!("Can't start installation process.")
......
...@@ -21,10 +21,7 @@ module Clusters ...@@ -21,10 +21,7 @@ module Clusters
def get_secret def get_secret
kubeclient.get_secret(service_account_token_name, namespace).as_json kubeclient.get_secret(service_account_token_name, namespace).as_json
rescue Kubeclient::HttpError => err rescue Kubeclient::ResourceNotFoundError
raise err unless err.error_code == 404
nil
end end
end end
end end
......
---
title: Show HTTP response code for Kubernetes errors
merge_request: 22964
author:
type: other
...@@ -89,22 +89,14 @@ module Gitlab ...@@ -89,22 +89,14 @@ module Gitlab
end end
def service_account_exists?(resource) def service_account_exists?(resource)
resource_exists? do kubeclient.get_service_account(resource.metadata.name, resource.metadata.namespace)
kubeclient.get_service_account(resource.metadata.name, resource.metadata.namespace) rescue ::Kubeclient::ResourceNotFoundError
end false
end end
def cluster_role_binding_exists?(resource) def cluster_role_binding_exists?(resource)
resource_exists? do kubeclient.get_cluster_role_binding(resource.metadata.name)
kubeclient.get_cluster_role_binding(resource.metadata.name) rescue ::Kubeclient::ResourceNotFoundError
end
end
def resource_exists?
yield
rescue ::Kubeclient::HttpError => e
raise e unless e.error_code == 404
false false
end end
end end
......
...@@ -10,9 +10,7 @@ module Gitlab ...@@ -10,9 +10,7 @@ module Gitlab
def exists? def exists?
@client.get_namespace(name) @client.get_namespace(name)
rescue ::Kubeclient::HttpError => ke rescue ::Kubeclient::ResourceNotFoundError
raise ke unless ke.error_code == 404
false false
end end
......
...@@ -88,8 +88,8 @@ describe Gitlab::Kubernetes::Helm::Api do ...@@ -88,8 +88,8 @@ describe Gitlab::Kubernetes::Helm::Api do
context 'service account and cluster role binding does not exist' do context 'service account and cluster role binding does not exist' do
before do before do
expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_raise(Kubeclient::HttpError.new(404, 'Not found', nil)) expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_raise(Kubeclient::HttpError.new(404, 'Not found', nil)) expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
end end
it 'creates a service account, followed the cluster role binding on kubeclient' do it 'creates a service account, followed the cluster role binding on kubeclient' do
...@@ -103,7 +103,7 @@ describe Gitlab::Kubernetes::Helm::Api do ...@@ -103,7 +103,7 @@ describe Gitlab::Kubernetes::Helm::Api do
context 'service account already exists' do context 'service account already exists' do
before do before do
expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_return(service_account_resource) expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_return(service_account_resource)
expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_raise(Kubeclient::HttpError.new(404, 'Not found', nil)) expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
end end
it 'updates the service account, followed by creating the cluster role binding' do it 'updates the service account, followed by creating the cluster role binding' do
......
...@@ -9,7 +9,7 @@ describe Gitlab::Kubernetes::Namespace do ...@@ -9,7 +9,7 @@ describe Gitlab::Kubernetes::Namespace do
describe '#exists?' do describe '#exists?' do
context 'when namespace do not exits' do context 'when namespace do not exits' do
let(:exception) { ::Kubeclient::HttpError.new(404, "namespace #{name} not found", nil) } let(:exception) { ::Kubeclient::ResourceNotFoundError.new(404, "namespace #{name} not found", nil) }
it 'returns false' do it 'returns false' do
expect(client).to receive(:get_namespace).with(name).once.and_raise(exception) expect(client).to receive(:get_namespace).with(name).once.and_raise(exception)
......
...@@ -19,6 +19,10 @@ describe Clusters::Applications::CheckInstallationProgressService do ...@@ -19,6 +19,10 @@ describe Clusters::Applications::CheckInstallationProgressService do
shared_examples 'a not yet terminated installation' do |a_phase| shared_examples 'a not yet terminated installation' do |a_phase|
let(:phase) { a_phase } let(:phase) { a_phase }
before do
expect(service).to receive(:installation_phase).once.and_return(phase)
end
context "when phase is #{a_phase}" do context "when phase is #{a_phase}" do
context 'when not timeouted' do context 'when not timeouted' do
it 'reschedule a new check' do it 'reschedule a new check' do
...@@ -50,8 +54,6 @@ describe Clusters::Applications::CheckInstallationProgressService do ...@@ -50,8 +54,6 @@ describe Clusters::Applications::CheckInstallationProgressService do
end end
before do before do
expect(service).to receive(:installation_phase).once.and_return(phase)
allow(service).to receive(:installation_errors).and_return(errors) allow(service).to receive(:installation_errors).and_return(errors)
allow(service).to receive(:remove_installation_pod).and_return(nil) allow(service).to receive(:remove_installation_pod).and_return(nil)
end end
...@@ -60,6 +62,10 @@ describe Clusters::Applications::CheckInstallationProgressService do ...@@ -60,6 +62,10 @@ describe Clusters::Applications::CheckInstallationProgressService do
context 'when installation POD succeeded' do context 'when installation POD succeeded' do
let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED } let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED }
before do
expect(service).to receive(:installation_phase).once.and_return(phase)
end
it_behaves_like 'a terminated installation' it_behaves_like 'a terminated installation'
it 'make the application installed' do it 'make the application installed' do
...@@ -76,6 +82,10 @@ describe Clusters::Applications::CheckInstallationProgressService do ...@@ -76,6 +82,10 @@ describe Clusters::Applications::CheckInstallationProgressService do
let(:phase) { Gitlab::Kubernetes::Pod::FAILED } let(:phase) { Gitlab::Kubernetes::Pod::FAILED }
let(:errors) { 'test installation failed' } let(:errors) { 'test installation failed' }
before do
expect(service).to receive(:installation_phase).once.and_return(phase)
end
it_behaves_like 'a terminated installation' it_behaves_like 'a terminated installation'
it 'make the application errored' do it 'make the application errored' do
...@@ -87,5 +97,22 @@ describe Clusters::Applications::CheckInstallationProgressService do ...@@ -87,5 +97,22 @@ describe Clusters::Applications::CheckInstallationProgressService do
end end
RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase } RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase }
context 'when installation raises a Kubeclient::HttpError' do
let(:cluster) { create(:cluster, :provided_by_user, :project) }
before do
application.update!(cluster: cluster)
expect(service).to receive(:installation_phase).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil))
end
it 'shows the response code from the error' do
service.execute
expect(application).to be_errored
expect(application.status_reason).to eq('Kubernetes error: 401')
end
end
end end
end end
...@@ -42,7 +42,7 @@ describe Clusters::Applications::InstallService do ...@@ -42,7 +42,7 @@ describe Clusters::Applications::InstallService do
service.execute service.execute
expect(application).to be_errored expect(application).to be_errored
expect(application.status_reason).to match('Kubernetes error.') expect(application.status_reason).to match('Kubernetes error: 500')
end end
end end
......
...@@ -19,13 +19,16 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do ...@@ -19,13 +19,16 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
subject { described_class.new(kubeclient, service_account_token_name, namespace).execute } subject { described_class.new(kubeclient, service_account_token_name, namespace).execute }
before do
stub_kubeclient_discover(api_url)
end
context 'when params correct' do context 'when params correct' do
let(:decoded_token) { 'xxx.token.xxx' } let(:decoded_token) { 'xxx.token.xxx' }
let(:token) { Base64.encode64(decoded_token) } let(:token) { Base64.encode64(decoded_token) }
context 'when gitlab-token exists' do context 'when gitlab-token exists' do
before do before do
stub_kubeclient_discover(api_url)
stub_kubeclient_get_secret( stub_kubeclient_get_secret(
api_url, api_url,
{ {
...@@ -39,9 +42,17 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do ...@@ -39,9 +42,17 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
it { is_expected.to eq(decoded_token) } it { is_expected.to eq(decoded_token) }
end end
context 'when there is a 500 error' do
before do
stub_kubeclient_get_secret_error(api_url, service_account_token_name, namespace: namespace, status: 500)
end
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
end
context 'when gitlab-token does not exist' do context 'when gitlab-token does not exist' do
before do before do
allow(kubeclient).to receive(:get_secret).and_raise(Kubeclient::HttpError.new(404, 'Not found', nil)) stub_kubeclient_get_secret_error(api_url, service_account_token_name, namespace: namespace, status: 404)
end end
it { is_expected.to be_nil } it { is_expected.to be_nil }
......
...@@ -41,9 +41,9 @@ module KubernetesHelpers ...@@ -41,9 +41,9 @@ module KubernetesHelpers
.to_return(kube_response(kube_v1_secret_body(options))) .to_return(kube_response(kube_v1_secret_body(options)))
end end
def stub_kubeclient_get_secret_error(api_url, name, namespace: 'default') def stub_kubeclient_get_secret_error(api_url, name, namespace: 'default', status: 404)
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{name}") WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{name}")
.to_return(status: [404, "Internal Server Error"]) .to_return(status: [status, "Internal Server Error"])
end end
def stub_kubeclient_create_service_account(api_url, namespace: 'default') def stub_kubeclient_create_service_account(api_url, namespace: 'default')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment