Backports relevant changes made in https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5163 to CE
This commit is contained in:
		
							parent
							
								
									4063141223
								
							
						
					
					
						commit
						eb7c08c7a6
					
				|  | @ -4,4 +4,23 @@ module EnvironmentsHelper | |||
|       endpoint: project_environments_path(@project, format: :json) | ||||
|     } | ||||
|   end | ||||
| 
 | ||||
|   def metrics_data(project, environment) | ||||
|     { | ||||
|       "settings-path" => edit_project_service_path(project, 'prometheus'), | ||||
|       "clusters-path" => project_clusters_path(project), | ||||
|       "current-environment-name": environment.name, | ||||
|       "documentation-path" => help_page_path('administration/monitoring/prometheus/index.md'), | ||||
|       "empty-getting-started-svg-path" => image_path('illustrations/monitoring/getting_started.svg'), | ||||
|       "empty-loading-svg-path" => image_path('illustrations/monitoring/loading.svg'), | ||||
|       "empty-no-data-svg-path" => image_path('illustrations/monitoring/no_data.svg'), | ||||
|       "empty-unable-to-connect-svg-path" => image_path('illustrations/monitoring/unable_to_connect.svg'), | ||||
|       "metrics-endpoint" => additional_metrics_project_environment_path(project, environment, format: :json), | ||||
|       "deployment-endpoint" => project_environment_deployments_path(project, environment, format: :json), | ||||
|       "environments-endpoint": project_environments_path(project, format: :json), | ||||
|       "project-path" => project_path(project), | ||||
|       "tags-path" => project_tags_path(project), | ||||
|       "has-metrics" => "#{environment.has_metrics?}" | ||||
|     } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -21,6 +21,14 @@ module Clusters | |||
|         end | ||||
|       end | ||||
| 
 | ||||
|       def ready_status | ||||
|         [:installed] | ||||
|       end | ||||
| 
 | ||||
|       def ready? | ||||
|         ready_status.include?(status_name) | ||||
|       end | ||||
| 
 | ||||
|       def chart | ||||
|         'stable/prometheus' | ||||
|       end | ||||
|  |  | |||
|  | @ -24,11 +24,10 @@ module PrometheusAdapter | |||
|     def query(query_name, *args) | ||||
|       return unless can_query? | ||||
| 
 | ||||
|       query_class = Gitlab::Prometheus::Queries.const_get("#{query_name.to_s.classify}Query") | ||||
|       query_class = query_klass_for(query_name) | ||||
|       query_args = build_query_args(*args) | ||||
| 
 | ||||
|       args.map!(&:id) | ||||
| 
 | ||||
|       with_reactive_cache(query_class.name, *args, &query_class.method(:transform_reactive_result)) | ||||
|       with_reactive_cache(query_class.name, *query_args, &query_class.method(:transform_reactive_result)) | ||||
|     end | ||||
| 
 | ||||
|     # Cache metrics for specific environment | ||||
|  | @ -44,5 +43,13 @@ module PrometheusAdapter | |||
|     rescue Gitlab::PrometheusClient::Error => err | ||||
|       { success: false, result: err.message } | ||||
|     end | ||||
| 
 | ||||
|     def query_klass_for(query_name) | ||||
|       Gitlab::Prometheus::Queries.const_get("#{query_name.to_s.classify}Query") | ||||
|     end | ||||
| 
 | ||||
|     def build_query_args(*args) | ||||
|       args.map(&:id) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ class InternalId < ActiveRecord::Base | |||
|   belongs_to :project | ||||
|   belongs_to :namespace | ||||
| 
 | ||||
|   enum usage: { issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4, ci_pipelines: 5 } | ||||
|   enum usage: { issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4, ci_pipelines: 5, prometheus_alerts: 6 } | ||||
| 
 | ||||
|   validates :usage, presence: true | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,17 +50,17 @@ module Clusters | |||
|       end | ||||
| 
 | ||||
|       def remove_installation_pod | ||||
|         helm_api.delete_installation_pod!(install_command.pod_name) | ||||
|         helm_api.delete_pod!(install_command.pod_name) | ||||
|       rescue | ||||
|         # no-op | ||||
|       end | ||||
| 
 | ||||
|       def installation_phase | ||||
|         helm_api.installation_status(install_command.pod_name) | ||||
|         helm_api.status(install_command.pod_name) | ||||
|       end | ||||
| 
 | ||||
|       def installation_errors | ||||
|         helm_api.installation_log(install_command.pod_name) | ||||
|         helm_api.log(install_command.pod_name) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ module Prometheus | |||
|       return unless deployment_platform.respond_to?(:cluster) | ||||
| 
 | ||||
|       cluster = deployment_platform.cluster | ||||
|       return unless cluster.application_prometheus&.installed? | ||||
|       return unless cluster.application_prometheus&.ready? | ||||
| 
 | ||||
|       cluster.application_prometheus | ||||
|     end | ||||
|  |  | |||
|  | @ -2,17 +2,11 @@ | |||
| - page_title "Metrics for environment", @environment.name | ||||
| 
 | ||||
| .prometheus-container{ class: container_class } | ||||
|   #prometheus-graphs{ data: { "settings-path": edit_project_service_path(@project, 'prometheus'), | ||||
|     "clusters-path": project_clusters_path(@project), | ||||
|     "current-environment-name": @environment.name, | ||||
|     "documentation-path": help_page_path('administration/monitoring/prometheus/index.md'), | ||||
|     "empty-getting-started-svg-path": image_path('illustrations/monitoring/getting_started.svg'), | ||||
|     "empty-loading-svg-path": image_path('illustrations/monitoring/loading.svg'), | ||||
|     "empty-no-data-svg-path": image_path('illustrations/monitoring/no_data.svg'), | ||||
|     "empty-unable-to-connect-svg-path": image_path('illustrations/monitoring/unable_to_connect.svg'), | ||||
|     "metrics-endpoint": additional_metrics_project_environment_path(@project, @environment, format: :json), | ||||
|     "deployment-endpoint": project_environment_deployments_path(@project, @environment, format: :json), | ||||
|     "environments-endpoint": project_environments_path(@project, format: :json), | ||||
|     "project-path": project_path(@project), | ||||
|     "tags-path": project_tags_path(@project), | ||||
|     "has-metrics": "#{@environment.has_metrics?}" } } | ||||
|   .top-area | ||||
|     .row | ||||
|       .col-sm-6 | ||||
|         %h3 | ||||
|           Environment: | ||||
|           = link_to @environment.name, environment_path(@environment) | ||||
| 
 | ||||
|   #prometheus-graphs{ data: metrics_data(@project, @environment) } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| module Gitlab | ||||
|   module Kubernetes | ||||
|     class ConfigMap | ||||
|       def initialize(name, values) | ||||
|       def initialize(name, values = "") | ||||
|         @name = name | ||||
|         @values = values | ||||
|       end | ||||
|  | @ -13,6 +13,10 @@ module Gitlab | |||
|         resource | ||||
|       end | ||||
| 
 | ||||
|       def config_map_name | ||||
|         "values-content-configuration-#{name}" | ||||
|       end | ||||
| 
 | ||||
|       private | ||||
| 
 | ||||
|       attr_reader :name, :values | ||||
|  | @ -25,10 +29,6 @@ module Gitlab | |||
|         } | ||||
|       end | ||||
| 
 | ||||
|       def config_map_name | ||||
|         "values-content-configuration-#{name}" | ||||
|       end | ||||
| 
 | ||||
|       def namespace | ||||
|         Gitlab::Kubernetes::Helm::NAMESPACE | ||||
|       end | ||||
|  |  | |||
|  | @ -2,15 +2,17 @@ module Gitlab | |||
|   module Kubernetes | ||||
|     module Helm | ||||
|       class Api | ||||
|         attr_reader :kubeclient, :namespace | ||||
| 
 | ||||
|         def initialize(kubeclient) | ||||
|           @kubeclient = kubeclient | ||||
|           @namespace = Gitlab::Kubernetes::Namespace.new(Gitlab::Kubernetes::Helm::NAMESPACE, kubeclient) | ||||
|         end | ||||
| 
 | ||||
|         def install(command) | ||||
|           @namespace.ensure_exists! | ||||
|           namespace.ensure_exists! | ||||
|           create_config_map(command) if command.config_map? | ||||
|           @kubeclient.create_pod(command.pod_resource) | ||||
|           kubeclient.create_pod(command.pod_resource) | ||||
|         end | ||||
| 
 | ||||
|         ## | ||||
|  | @ -20,23 +22,23 @@ module Gitlab | |||
|         # | ||||
|         # values: "Pending", "Running", "Succeeded", "Failed", "Unknown" | ||||
|         # | ||||
|         def installation_status(pod_name) | ||||
|           @kubeclient.get_pod(pod_name, @namespace.name).status.phase | ||||
|         def status(pod_name) | ||||
|           kubeclient.get_pod(pod_name, namespace.name).status.phase | ||||
|         end | ||||
| 
 | ||||
|         def installation_log(pod_name) | ||||
|           @kubeclient.get_pod_log(pod_name, @namespace.name).body | ||||
|         def log(pod_name) | ||||
|           kubeclient.get_pod_log(pod_name, namespace.name).body | ||||
|         end | ||||
| 
 | ||||
|         def delete_installation_pod!(pod_name) | ||||
|           @kubeclient.delete_pod(pod_name, @namespace.name) | ||||
|         def delete_pod!(pod_name) | ||||
|           kubeclient.delete_pod(pod_name, namespace.name) | ||||
|         end | ||||
| 
 | ||||
|         private | ||||
| 
 | ||||
|         def create_config_map(command) | ||||
|           command.config_map_resource.tap do |config_map_resource| | ||||
|             @kubeclient.create_config_map(config_map_resource) | ||||
|             kubeclient.create_config_map(config_map_resource) | ||||
|           end | ||||
|         end | ||||
|       end | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ module Gitlab | |||
|           Deployment.find_by(id: deployment_id).try do |deployment| | ||||
|             query_metrics( | ||||
|               deployment.project, | ||||
|               deployment.environment, | ||||
|               common_query_context( | ||||
|                 deployment.environment, | ||||
|                 timeframe_start: (deployment.created_at - 30.minutes).to_f, | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ module Gitlab | |||
|           ::Environment.find_by(id: environment_id).try do |environment| | ||||
|             query_metrics( | ||||
|               environment.project, | ||||
|               environment, | ||||
|               common_query_context(environment, timeframe_start: 8.hours.ago.to_f, timeframe_end: Time.now.to_f) | ||||
|             ) | ||||
|           end | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ module Gitlab | |||
|   module Prometheus | ||||
|     module Queries | ||||
|       module QueryAdditionalMetrics | ||||
|         def query_metrics(project, query_context) | ||||
|         def query_metrics(project, environment, query_context) | ||||
|           matched_metrics(project).map(&query_group(query_context)) | ||||
|             .select(&method(:group_with_any_metrics)) | ||||
|         end | ||||
|  |  | |||
|  | @ -22,4 +22,10 @@ describe Gitlab::Kubernetes::ConfigMap do | |||
|       is_expected.to eq(resource) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#config_map_name' do | ||||
|     it 'returns the config_map name' do | ||||
|       expect(config_map.config_map_name).to eq("values-content-configuration-#{application.name}") | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -49,33 +49,33 @@ describe Gitlab::Kubernetes::Helm::Api do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#installation_status' do | ||||
|   describe '#status' do | ||||
|     let(:phase) { Gitlab::Kubernetes::Pod::RUNNING } | ||||
|     let(:pod) { Kubeclient::Resource.new(status: { phase: phase }) } # partial representation | ||||
| 
 | ||||
|     it 'fetches POD phase from kubernetes cluster' do | ||||
|       expect(client).to receive(:get_pod).with(command.pod_name, gitlab_namespace).once.and_return(pod) | ||||
| 
 | ||||
|       expect(subject.installation_status(command.pod_name)).to eq(phase) | ||||
|       expect(subject.status(command.pod_name)).to eq(phase) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#installation_log' do | ||||
|   describe '#log' do | ||||
|     let(:log) { 'some output' } | ||||
|     let(:response) { RestClient::Response.new(log) } | ||||
| 
 | ||||
|     it 'fetches POD phase from kubernetes cluster' do | ||||
|       expect(client).to receive(:get_pod_log).with(command.pod_name, gitlab_namespace).once.and_return(response) | ||||
| 
 | ||||
|       expect(subject.installation_log(command.pod_name)).to eq(log) | ||||
|       expect(subject.log(command.pod_name)).to eq(log) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#delete_installation_pod!' do | ||||
|   describe '#delete_pod!' do | ||||
|     it 'deletes the POD from kubernetes cluster' do | ||||
|       expect(client).to receive(:delete_pod).with(command.pod_name, gitlab_namespace).once | ||||
| 
 | ||||
|       subject.delete_installation_pod!(command.pod_name) | ||||
|       subject.delete_pod!(command.pod_name) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -34,6 +34,47 @@ describe Clusters::Applications::Prometheus do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#ready' do | ||||
|     let(:project) { create(:project) } | ||||
|     let(:cluster) { create(:cluster, projects: [project]) } | ||||
| 
 | ||||
|     it 'returns true when installed' do | ||||
|       application = build(:clusters_applications_prometheus, :installed, cluster: cluster) | ||||
| 
 | ||||
|       expect(application.ready?).to be true | ||||
|     end | ||||
| 
 | ||||
|     it 'returns false when not_installable' do | ||||
|       application = build(:clusters_applications_prometheus, :not_installable, cluster: cluster) | ||||
| 
 | ||||
|       expect(application.ready?).to be false | ||||
|     end | ||||
| 
 | ||||
|     it 'returns false when installable' do | ||||
|       application = build(:clusters_applications_prometheus, :installable, cluster: cluster) | ||||
| 
 | ||||
|       expect(application.ready?).to be false | ||||
|     end | ||||
| 
 | ||||
|     it 'returns false when scheduled' do | ||||
|       application = build(:clusters_applications_prometheus, :scheduled, cluster: cluster) | ||||
| 
 | ||||
|       expect(application.ready?).to be false | ||||
|     end | ||||
| 
 | ||||
|     it 'returns false when installing' do | ||||
|       application = build(:clusters_applications_prometheus, :installing, cluster: cluster) | ||||
| 
 | ||||
|       expect(application.ready?).to be false | ||||
|     end | ||||
| 
 | ||||
|     it 'returns false when errored' do | ||||
|       application = build(:clusters_applications_prometheus, :errored, cluster: cluster) | ||||
| 
 | ||||
|       expect(application.ready?).to be false | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#prometheus_client' do | ||||
|     context 'cluster is nil' do | ||||
|       it 'returns nil' do | ||||
|  | @ -102,15 +143,17 @@ describe Clusters::Applications::Prometheus do | |||
|     let(:kubeclient) { double('kubernetes client') } | ||||
|     let(:prometheus) { create(:clusters_applications_prometheus) } | ||||
| 
 | ||||
|     subject { prometheus.install_command } | ||||
| 
 | ||||
|     it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) } | ||||
|     it 'returns an instance of Gitlab::Kubernetes::Helm::InstallCommand' do | ||||
|       expect(prometheus.install_command).to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) | ||||
|     end | ||||
| 
 | ||||
|     it 'should be initialized with 3 arguments' do | ||||
|       expect(subject.name).to eq('prometheus') | ||||
|       expect(subject.chart).to eq('stable/prometheus') | ||||
|       expect(subject.version).to eq('6.7.3') | ||||
|       expect(subject.values).to eq(prometheus.values) | ||||
|       command = prometheus.install_command | ||||
| 
 | ||||
|       expect(command.name).to eq('prometheus') | ||||
|       expect(command.chart).to eq('stable/prometheus') | ||||
|       expect(command.version).to eq('6.7.3') | ||||
|       expect(command.values).to eq(prometheus.values) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ RSpec.shared_examples 'additional metrics query' do | |||
| 
 | ||||
|     shared_examples 'query context containing environment slug and filter' do | ||||
|       it 'contains ci_environment_slug' do | ||||
|         expect(subject).to receive(:query_metrics).with(project, hash_including(ci_environment_slug: environment.slug)) | ||||
|         expect(subject).to receive(:query_metrics).with(project, environment, hash_including(ci_environment_slug: environment.slug)) | ||||
| 
 | ||||
|         subject.query(*query_params) | ||||
|       end | ||||
|  | @ -33,6 +33,7 @@ RSpec.shared_examples 'additional metrics query' do | |||
|       it 'contains environment filter' do | ||||
|         expect(subject).to receive(:query_metrics).with( | ||||
|           project, | ||||
|           environment, | ||||
|           hash_including( | ||||
|             environment_filter: "container_name!=\"POD\",environment=\"#{environment.slug}\"" | ||||
|           ) | ||||
|  | @ -50,7 +51,7 @@ RSpec.shared_examples 'additional metrics query' do | |||
|         it_behaves_like 'query context containing environment slug and filter' | ||||
| 
 | ||||
|         it 'query context contains kube_namespace' do | ||||
|           expect(subject).to receive(:query_metrics).with(project, hash_including(kube_namespace: kube_namespace)) | ||||
|           expect(subject).to receive(:query_metrics).with(project, environment, hash_including(kube_namespace: kube_namespace)) | ||||
| 
 | ||||
|           subject.query(*query_params) | ||||
|         end | ||||
|  | @ -74,7 +75,7 @@ RSpec.shared_examples 'additional metrics query' do | |||
|       it_behaves_like 'query context containing environment slug and filter' | ||||
| 
 | ||||
|       it 'query context contains empty kube_namespace' do | ||||
|         expect(subject).to receive(:query_metrics).with(project, hash_including(kube_namespace: '')) | ||||
|         expect(subject).to receive(:query_metrics).with(project, environment, hash_including(kube_namespace: '')) | ||||
| 
 | ||||
|         subject.query(*query_params) | ||||
|       end | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue