Commit 591f0cbe authored by Thong Kuah's avatar Thong Kuah

Extract prometheus_client out into shared concern

For later re-use, with Prometheus Cluster integration.
This also makes it much easier to delete
app/models/clusters/applications/prometheus.rb when the time comes
parent 3c2c533b
......@@ -3,7 +3,7 @@
module Clusters
module Applications
class Prometheus < ApplicationRecord
include PrometheusAdapter
include ::Clusters::Concerns::PrometheusClient
VERSION = '10.4.1'
......@@ -58,14 +58,6 @@ module Clusters
'https://gitlab-org.gitlab.io/cluster-integration/helm-stable-archive'
end
def service_name
'prometheus-prometheus-server'
end
def service_port
80
end
def install_command
helm_command_module::InstallCommand.new(
name: name,
......@@ -106,29 +98,6 @@ module Clusters
files.merge('values.yaml': replaced_values)
end
def prometheus_client
return unless kube_client
proxy_url = kube_client.proxy_url('service', service_name, service_port, Gitlab::Kubernetes::Helm::NAMESPACE)
# ensures headers containing auth data are appended to original k8s client options
options = kube_client.rest_client.options
.merge(prometheus_client_default_options)
.merge(headers: kube_client.headers)
Gitlab::PrometheusClient.new(proxy_url, options)
rescue Kubeclient::HttpError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ENETUNREACH
# If users have mistakenly set parameters or removed the depended clusters,
# `proxy_url` could raise an exception because gitlab can not communicate with the cluster.
# Since `PrometheusAdapter#can_query?` is eargely loaded on environement pages in gitlab,
# we need to silence the exceptions
end
def configured?
kube_client.present? && available?
rescue Gitlab::UrlBlocker::BlockedUrlError
false
end
def generate_alert_manager_token!
unless alert_manager_token.present?
update!(alert_manager_token: generate_token)
......@@ -146,10 +115,6 @@ module Clusters
.perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
end
def kube_client
cluster&.kubeclient&.core_client
end
def install_knative_metrics
return [] unless cluster.application_knative_available?
......
# frozen_string_literal: true
module Clusters
module Concerns
module PrometheusClient
extend ActiveSupport::Concern
included do
include PrometheusAdapter
def service_name
'prometheus-prometheus-server'
end
def service_port
80
end
def prometheus_client
return unless kube_client
proxy_url = kube_client.proxy_url('service', service_name, service_port, Gitlab::Kubernetes::Helm::NAMESPACE)
# ensures headers containing auth data are appended to original k8s client options
options = kube_client.rest_client.options
.merge(prometheus_client_default_options)
.merge(headers: kube_client.headers)
Gitlab::PrometheusClient.new(proxy_url, options)
rescue Kubeclient::HttpError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ENETUNREACH
# If users have mistakenly set parameters or removed the depended clusters,
# `proxy_url` could raise an exception because gitlab can not communicate with the cluster.
# Since `PrometheusAdapter#can_query?` is eargely loaded on environement pages in gitlab,
# we need to silence the exceptions
end
def configured?
kube_client.present? && available?
rescue Gitlab::UrlBlocker::BlockedUrlError
false
end
private
def kube_client
cluster&.kubeclient&.core_client
end
end
end
end
end
......@@ -74,85 +74,8 @@ RSpec.describe Clusters::Applications::Prometheus do
end
describe '#prometheus_client' do
shared_examples 'exception caught for prometheus client' do
before do
allow(kube_client).to receive(:proxy_url).and_raise(exception)
end
it 'returns nil' do
expect(subject.prometheus_client).to be_nil
end
end
context 'cluster is nil' do
it 'returns nil' do
expect(subject.cluster).to be_nil
expect(subject.prometheus_client).to be_nil
end
end
context "cluster doesn't have kubeclient" do
let(:cluster) { create(:cluster) }
subject { create(:clusters_applications_prometheus, cluster: cluster) }
it 'returns nil' do
expect(subject.prometheus_client).to be_nil
end
end
context 'cluster has kubeclient' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url }
let(:kube_client) { subject.cluster.kubeclient.core_client }
subject { create(:clusters_applications_prometheus, cluster: cluster) }
before do
subject.cluster.platform_kubernetes.namespace = 'a-namespace'
stub_kubeclient_discover(cluster.platform_kubernetes.api_url)
create(:cluster_kubernetes_namespace,
cluster: cluster,
cluster_project: cluster.cluster_project,
project: cluster.cluster_project.project)
end
it 'creates proxy prometheus_client' do
expect(subject.prometheus_client).to be_instance_of(Gitlab::PrometheusClient)
end
it 'merges proxy_url, options and headers from kube client with prometheus_client options' do
expect(Gitlab::PrometheusClient)
.to(receive(:new))
.with(a_valid_url, kube_client.rest_client.options.merge({
headers: kube_client.headers,
timeout: PrometheusAdapter::DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC
}))
subject.prometheus_client
end
context 'when cluster is not reachable' do
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Kubeclient::HttpError.new(401, 'Unauthorized', nil) }
end
end
context 'when there is a socket error while contacting cluster' do
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Errno::ECONNREFUSED }
end
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Errno::ECONNRESET }
end
end
context 'when the network is unreachable' do
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Errno::ENETUNREACH }
end
end
include_examples '#prometheus_client shared' do
let(:factory) { :clusters_applications_prometheus }
end
end
......
# frozen_string_literal: true
# Input
# - factory: [:clusters_applications_prometheus, :clusters_integrations_prometheus]
RSpec.shared_examples '#prometheus_client shared' do
shared_examples 'exception caught for prometheus client' do
before do
allow(kube_client).to receive(:proxy_url).and_raise(exception)
end
it 'returns nil' do
expect(subject.prometheus_client).to be_nil
end
end
context 'cluster is nil' do
it 'returns nil' do
expect(subject.cluster).to be_nil
expect(subject.prometheus_client).to be_nil
end
end
context "cluster doesn't have kubeclient" do
let(:cluster) { create(:cluster) }
subject { create(factory, cluster: cluster) }
it 'returns nil' do
expect(subject.prometheus_client).to be_nil
end
end
context 'cluster has kubeclient' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url }
let(:kube_client) { subject.cluster.kubeclient.core_client }
subject { create(factory, cluster: cluster) }
before do
subject.cluster.platform_kubernetes.namespace = 'a-namespace'
stub_kubeclient_discover(cluster.platform_kubernetes.api_url)
create(:cluster_kubernetes_namespace,
cluster: cluster,
cluster_project: cluster.cluster_project,
project: cluster.cluster_project.project)
end
it 'creates proxy prometheus_client' do
expect(subject.prometheus_client).to be_instance_of(Gitlab::PrometheusClient)
end
it 'merges proxy_url, options and headers from kube client with prometheus_client options' do
expect(Gitlab::PrometheusClient)
.to(receive(:new))
.with(a_valid_url, kube_client.rest_client.options.merge({
headers: kube_client.headers,
timeout: PrometheusAdapter::DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC
}))
subject.prometheus_client
end
context 'when cluster is not reachable' do
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Kubeclient::HttpError.new(401, 'Unauthorized', nil) }
end
end
context 'when there is a socket error while contacting cluster' do
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Errno::ECONNREFUSED }
end
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Errno::ECONNRESET }
end
end
context 'when the network is unreachable' do
it_behaves_like 'exception caught for prometheus client' do
let(:exception) { Errno::ENETUNREACH }
end
end
end
end
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