Commit 734d5ba1 authored by Mikolaj Wawrzyniak's avatar Mikolaj Wawrzyniak

Move cluster health prometheus api proxy to core

In order to allow all users to utilize health dashboard
for thier clustres we need to move proxying promethues api requests to
the core.
parent 42603e9b
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
class Clusters::ClustersController < Clusters::BaseController class Clusters::ClustersController < Clusters::BaseController
include RoutableActions include RoutableActions
include Metrics::Dashboard::PrometheusApiProxy
before_action :cluster, only: [:cluster_status, :show, :update, :destroy, :clear_cache] before_action :cluster, only: [:cluster_status, :show, :update, :destroy, :clear_cache]
before_action :generate_gcp_authorize_url, only: [:new] before_action :generate_gcp_authorize_url, only: [:new]
...@@ -290,6 +291,29 @@ class Clusters::ClustersController < Clusters::BaseController ...@@ -290,6 +291,29 @@ class Clusters::ClustersController < Clusters::BaseController
@gcp_cluster = cluster.present(current_user: current_user) @gcp_cluster = cluster.present(current_user: current_user)
end end
def proxyable
cluster.cluster
end
# During first iteration of dashboard variables implementation
# cluster health case was omitted. Existing service for now is tied to
# environment, which is not always present for cluster health dashboard.
# It is planned to break coupling to environment https://gitlab.com/gitlab-org/gitlab/-/issues/213833.
# It is also planned to move cluster health to metrics dashboard section https://gitlab.com/gitlab-org/gitlab/-/issues/220214
# but for now I've used dummy class to stub variable substitution service, as there are no variables
# in cluster health dashboard
def proxy_variable_substitution_service
@empty_service ||= Class.new(BaseService) do
def initialize(proxyable, params)
@proxyable, @params = proxyable, params
end
def execute
success(params: @params)
end
end
end
def user_cluster def user_cluster
cluster = Clusters::BuildService.new(clusterable.subject).execute cluster = Clusters::BuildService.new(clusterable.subject).execute
cluster.build_platform_kubernetes cluster.build_platform_kubernetes
......
...@@ -103,6 +103,7 @@ class GroupPolicy < BasePolicy ...@@ -103,6 +103,7 @@ class GroupPolicy < BasePolicy
enable :admin_list enable :admin_list
enable :admin_issue enable :admin_issue
enable :read_metrics_dashboard_annotation enable :read_metrics_dashboard_annotation
enable :read_prometheus
end end
rule { maintainer }.policy do rule { maintainer }.policy do
......
...@@ -190,7 +190,6 @@ Rails.application.routes.draw do ...@@ -190,7 +190,6 @@ Rails.application.routes.draw do
Gitlab.ee do Gitlab.ee do
get :metrics, format: :json get :metrics, format: :json
get :metrics_dashboard get :metrics_dashboard
get :'/prometheus/api/v1/*proxy_path', to: 'clusters#prometheus_proxy', as: :prometheus_api
get :environments, format: :json get :environments, format: :json
end end
...@@ -200,6 +199,7 @@ Rails.application.routes.draw do ...@@ -200,6 +199,7 @@ Rails.application.routes.draw do
delete '/:application', to: 'clusters/applications#destroy', as: :uninstall_applications delete '/:application', to: 'clusters/applications#destroy', as: :uninstall_applications
end end
get :'/prometheus/api/v1/*proxy_path', to: 'clusters#prometheus_proxy', as: :prometheus_api
get :cluster_status, format: :json get :cluster_status, format: :json
delete :clear_cache delete :clear_cache
end end
......
...@@ -8,7 +8,6 @@ module EE ...@@ -8,7 +8,6 @@ module EE
prepended do prepended do
before_action :expire_etag_cache, only: [:show] before_action :expire_etag_cache, only: [:show]
before_action :authorize_read_prometheus!, only: :prometheus_proxy
end end
def metrics def metrics
...@@ -27,31 +26,6 @@ module EE ...@@ -27,31 +26,6 @@ module EE
end end
end end
def prometheus_proxy
result = ::Prometheus::ProxyService.new(
cluster.cluster,
proxy_method,
proxy_path,
proxy_params
).execute
if result.nil?
return render status: :no_content, json: {
status: _('processing'),
message: _('Not ready yet. Try again later.')
}
end
if result[:status] == :success
render status: result[:http_status], json: result[:body]
else
render(
status: result[:http_status] || :bad_request,
json: { status: result[:status], message: result[:message] }
)
end
end
def environments def environments
respond_to do |format| respond_to do |format|
format.json do format.json do
...@@ -91,18 +65,6 @@ module EE ...@@ -91,18 +65,6 @@ module EE
cluster.application_prometheus cluster.application_prometheus
end end
def proxy_method
request.method
end
def proxy_path
params[:proxy_path]
end
def proxy_params
params.permit!
end
end end
end end
end end
...@@ -97,7 +97,6 @@ module EE ...@@ -97,7 +97,6 @@ module EE
rule { reporter }.policy do rule { reporter }.policy do
enable :admin_list enable :admin_list
enable :admin_board enable :admin_board
enable :read_prometheus
enable :view_productivity_analytics enable :view_productivity_analytics
enable :view_type_of_work_charts enable :view_type_of_work_charts
enable :read_group_timelogs enable :read_group_timelogs
......
...@@ -28,34 +28,6 @@ RSpec.describe Admin::ClustersController do ...@@ -28,34 +28,6 @@ RSpec.describe Admin::ClustersController do
allow(::Clusters::Instance).to receive(:new).and_return(cluster.instance) allow(::Clusters::Instance).to receive(:new).and_return(cluster.instance)
end end
context 'with inappropriate requests' do
context 'with anoymous user' do
before do
sign_out(user)
end
it 'renders not found' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'with non-admin user' do
let(:user) { create(:user) }
before do
sign_in(user)
end
it 'renders not found' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
describe 'GET #metrics_dashboard' do describe 'GET #metrics_dashboard' do
it_behaves_like 'the default dashboard' it_behaves_like 'the default dashboard'
end end
......
...@@ -25,34 +25,6 @@ RSpec.describe Projects::ClustersController do ...@@ -25,34 +25,6 @@ RSpec.describe Projects::ClustersController do
clusterable.add_maintainer(user) clusterable.add_maintainer(user)
end end
context 'with inappropriate requests' do
context 'with annoymous user' do
before do
sign_out(user)
end
it 'redirects to signin page' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to redirect_to(new_user_session_path)
end
end
context 'with invalid clusterable id' do
before do
sign_in(user)
end
let(:other_clusterable) { create(:project) }
it 'returns 404' do
get :prometheus_proxy, params: prometheus_proxy_params(id: other_clusterable.id)
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
describe 'security' do describe 'security' do
let(:prometheus_adapter) { double(:prometheus_adapter, can_query?: true, query: nil) } let(:prometheus_adapter) { double(:prometheus_adapter, can_query?: true, query: nil) }
......
...@@ -74,118 +74,6 @@ RSpec.shared_examples 'cluster metrics' do ...@@ -74,118 +74,6 @@ RSpec.shared_examples 'cluster metrics' do
end end
end end
describe 'GET #prometheus_proxy' do
let(:prometheus_proxy_service) { instance_double(Prometheus::ProxyService) }
let(:expected_params) do
ActionController::Parameters.new(
prometheus_proxy_params(
proxy_path: 'query',
controller: subject.controller_path,
action: 'prometheus_proxy'
)
).permit!
end
before do
sign_in(user)
end
context 'with valid requests' do
before do
allow(Prometheus::ProxyService).to receive(:new)
.with(cluster, 'GET', 'query', expected_params)
.and_return(prometheus_proxy_service)
allow(prometheus_proxy_service).to receive(:execute)
.and_return(service_result)
end
context 'with success result' do
let(:service_result) { { status: :success, body: prometheus_body } }
let(:prometheus_body) { '{"status":"success"}' }
it 'returns prometheus response' do
prometheus_json_body = Gitlab::Json.parse(prometheus_body)
get :prometheus_proxy, params: prometheus_proxy_params
expect(Prometheus::ProxyService).to have_received(:new)
.with(cluster, 'GET', 'query', expected_params)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq(prometheus_json_body)
end
end
context 'with nil result' do
let(:service_result) { nil }
it 'returns 204 no content' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(json_response['status']).to eq('processing')
expect(json_response['message']).to eq('Not ready yet. Try again later.')
expect(response).to have_gitlab_http_status(:no_content)
end
end
context 'with 404 result' do
let(:service_result) { { http_status: 404, status: :success, body: '{"body": "value"}' } }
it 'returns body' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['body']).to eq('value')
end
end
context 'with error result' do
context 'with http_status' do
let(:service_result) do
{ http_status: :service_unavailable, status: :error, message: 'error message' }
end
it 'sets the http response status code' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:service_unavailable)
expect(json_response['status']).to eq('error')
expect(json_response['message']).to eq('error message')
end
end
context 'without http_status' do
let(:service_result) { { status: :error, message: 'error message' } }
it 'returns bad_request' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response). to have_gitlab_http_status(:bad_request)
expect(json_response['status']).to eq('error')
expect(json_response['message']).to eq('error message')
end
end
end
end
context 'with inappropriate requests' do
context 'without correct permissions' do
let(:user2) { create(:user) }
before do
sign_out(user)
sign_in(user2)
end
it 'returns 404' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
shared_examples 'the default dashboard' do shared_examples 'the default dashboard' do
it 'returns a json object with the correct keys' do it 'returns a json object with the correct keys' do
get :metrics_dashboard, params: metrics_params, format: :json get :metrics_dashboard, params: metrics_params, format: :json
......
...@@ -171,6 +171,29 @@ RSpec.describe Admin::ClustersController do ...@@ -171,6 +171,29 @@ RSpec.describe Admin::ClustersController do
end end
end end
describe 'GET #prometheus_proxy' do
let(:user) { admin }
let(:proxyable) do
create(:cluster, :instance, :provided_by_gcp)
end
it_behaves_like 'metrics dashboard prometheus api proxy' do
context 'with anonymous user' do
let(:prometheus_body) { nil }
before do
sign_out(admin)
end
it 'returns 404' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
describe 'POST #create_gcp' do describe 'POST #create_gcp' do
let(:legacy_abac_param) { 'true' } let(:legacy_abac_param) { 'true' }
let(:params) do let(:params) do
......
...@@ -192,6 +192,35 @@ RSpec.describe Groups::ClustersController do ...@@ -192,6 +192,35 @@ RSpec.describe Groups::ClustersController do
end end
end end
describe 'GET #prometheus_proxy' do
let(:proxyable) do
create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group])
end
it_behaves_like 'metrics dashboard prometheus api proxy' do
let(:proxyable_params) do
{
id: proxyable.id.to_s,
group_id: group.name
}
end
context 'with anonymous user' do
let(:prometheus_body) { nil }
before do
sign_out(user)
end
it 'returns 404' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
describe 'POST create for new cluster' do describe 'POST create for new cluster' do
let(:legacy_abac_param) { 'true' } let(:legacy_abac_param) { 'true' }
let(:params) do let(:params) do
......
...@@ -200,6 +200,36 @@ RSpec.describe Projects::ClustersController do ...@@ -200,6 +200,36 @@ RSpec.describe Projects::ClustersController do
end end
end end
describe 'GET #prometheus_proxy' do
let(:proxyable) do
create(:cluster, :provided_by_gcp, projects: [project])
end
it_behaves_like 'metrics dashboard prometheus api proxy' do
let(:proxyable_params) do
{
id: proxyable.id.to_s,
namespace_id: project.namespace.full_path,
project_id: project.name
}
end
context 'with anonymous user' do
let(:prometheus_body) { nil }
before do
sign_out(user)
end
it 'redirects to signin page' do
get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to redirect_to(new_user_session_path)
end
end
end
end
describe 'POST create for new cluster' do describe 'POST create for new cluster' do
let(:legacy_abac_param) { 'true' } let(:legacy_abac_param) { 'true' }
let(:params) do let(:params) do
......
...@@ -18,7 +18,7 @@ RSpec.shared_context 'GroupPolicy context' do ...@@ -18,7 +18,7 @@ RSpec.shared_context 'GroupPolicy context' do
] ]
end end
let(:read_group_permissions) { %i[read_label read_list read_milestone read_board] } let(:read_group_permissions) { %i[read_label read_list read_milestone read_board] }
let(:reporter_permissions) { %i[admin_label read_container_image read_metrics_dashboard_annotation] } let(:reporter_permissions) { %i[admin_label read_container_image read_metrics_dashboard_annotation read_prometheus] }
let(:developer_permissions) { %i[admin_milestone create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation] } let(:developer_permissions) { %i[admin_milestone create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation] }
let(:maintainer_permissions) do let(:maintainer_permissions) do
%i[ %i[
......
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