diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-10 15:09:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-10 15:09:50 +0000 |
commit | de2fb5b82c92c90f90ed67ced45143c04e934fb8 (patch) | |
tree | ff8e5e642580de7bb596d90dd0e7f739f44ca540 /app | |
parent | c6a33b298229f9e04933be43d6176c476ef03012 (diff) | |
download | gitlab-ce-de2fb5b82c92c90f90ed67ced45143c04e934fb8.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
17 files changed, 335 insertions, 13 deletions
diff --git a/app/assets/javascripts/jira_import/components/jira_import_app.vue b/app/assets/javascripts/jira_import/components/jira_import_app.vue index 6efac949979..437239ce0be 100644 --- a/app/assets/javascripts/jira_import/components/jira_import_app.vue +++ b/app/assets/javascripts/jira_import/components/jira_import_app.vue @@ -1,10 +1,12 @@ <script> import getJiraProjects from '../queries/getJiraProjects.query.graphql'; +import JiraImportForm from './jira_import_form.vue'; import JiraImportSetup from './jira_import_setup.vue'; export default { name: 'JiraImportApp', components: { + JiraImportForm, JiraImportSetup, }, props: { @@ -41,6 +43,6 @@ export default { <template> <div> <jira-import-setup v-if="!isJiraConfigured" :illustration="setupIllustration" /> - <div v-else></div> + <jira-import-form v-else /> </div> </template> diff --git a/app/assets/javascripts/jira_import/components/jira_import_form.vue b/app/assets/javascripts/jira_import/components/jira_import_form.vue new file mode 100644 index 00000000000..4de04efe1b0 --- /dev/null +++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue @@ -0,0 +1,94 @@ +<script> +import { GlAvatar, GlNewButton, GlFormGroup, GlFormSelect, GlLabel } from '@gitlab/ui'; + +export default { + name: 'JiraImportForm', + components: { + GlAvatar, + GlNewButton, + GlFormGroup, + GlFormSelect, + GlLabel, + }, + currentUserAvatarUrl: gon.current_user_avatar_url, + currentUsername: gon.current_username, +}; +</script> + +<template> + <div> + <h3 class="page-title">{{ __('New Jira import') }}</h3> + <hr /> + <form> + <gl-form-group + class="row align-items-center" + :label="__('Import from')" + label-cols-sm="2" + label-for="jira-project-select" + > + <gl-form-select id="jira-project-select" class="mb-2" /> + </gl-form-group> + + <gl-form-group + class="row align-items-center" + :label="__('Issue label')" + label-cols-sm="2" + label-for="jira-project-label" + > + <gl-label + id="jira-project-label" + class="mb-2" + background-color="#428BCA" + title="jira-import::KEY-1" + scoped + /> + </gl-form-group> + + <hr /> + + <p class="offset-md-1"> + {{ + __( + "For each Jira issue successfully imported, we'll create a new GitLab issue with the following data:", + ) + }} + </p> + + <gl-form-group + class="row align-items-center mb-1" + :label="__('Title')" + label-cols-sm="2" + label-for="jira-project-title" + > + <p id="jira-project-title" class="mb-2">{{ __('jira.issue.summary') }}</p> + </gl-form-group> + <gl-form-group + class="row align-items-center mb-1" + :label="__('Reporter')" + label-cols-sm="2" + label-for="jira-project-reporter" + > + <gl-avatar + id="jira-project-reporter" + class="mb-2" + :src="$options.currentUserAvatarUrl" + :size="24" + :aria-label="$options.currentUsername" + /> + </gl-form-group> + <gl-form-group + class="row align-items-center mb-1" + :label="__('Description')" + label-cols-sm="2" + label-for="jira-project-description" + > + <p id="jira-project-description" class="mb-2">{{ __('jira.issue.description.content') }}</p> + </gl-form-group> + + <div class="footer-block row-content-block d-flex justify-content-between"> + <gl-new-button category="primary" variant="success">{{ __('Next') }}</gl-new-button> + <gl-new-button>{{ __('Cancel') }}</gl-new-button> + </div> + </form> + </div> +</template> diff --git a/app/assets/javascripts/pages/projects/services/edit/index.js b/app/assets/javascripts/pages/projects/services/edit/index.js index 49862b64c27..5249709a2a3 100644 --- a/app/assets/javascripts/pages/projects/services/edit/index.js +++ b/app/assets/javascripts/pages/projects/services/edit/index.js @@ -1,5 +1,5 @@ import IntegrationSettingsForm from '~/integrations/integration_settings_form'; -import PrometheusMetrics from 'ee_else_ce/prometheus_metrics/prometheus_metrics'; +import PrometheusMetrics from '~/prometheus_metrics/custom_metrics'; import PrometheusAlerts from '~/prometheus_alerts'; import initAlertsSettings from '~/alerts_service_settings'; diff --git a/app/assets/javascripts/prometheus_metrics/constants.js b/app/assets/javascripts/prometheus_metrics/constants.js index 50f1248456e..0ffd977f04c 100644 --- a/app/assets/javascripts/prometheus_metrics/constants.js +++ b/app/assets/javascripts/prometheus_metrics/constants.js @@ -2,4 +2,5 @@ export default { EMPTY: 'empty', LOADING: 'loading', LIST: 'list', + NO_INTEGRATION: 'no-integration', }; diff --git a/app/assets/javascripts/prometheus_metrics/custom_metrics.js b/app/assets/javascripts/prometheus_metrics/custom_metrics.js new file mode 100644 index 00000000000..36df7837785 --- /dev/null +++ b/app/assets/javascripts/prometheus_metrics/custom_metrics.js @@ -0,0 +1,163 @@ +import $ from 'jquery'; +import { escape, sortBy } from 'lodash'; +import PrometheusMetrics from './prometheus_metrics'; +import PANEL_STATE from './constants'; +import axios from '~/lib/utils/axios_utils'; +import { s__ } from '~/locale'; +import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; + +export default class CustomMetrics extends PrometheusMetrics { + constructor(wrapperSelector) { + super(wrapperSelector); + this.customMetrics = []; + this.environmentsData = []; + this.$els = []; + + this.$wrapperCustomMetrics = $(wrapperSelector); + + this.$monitoredCustomMetricsPanel = this.$wrapperCustomMetrics.find( + '.js-panel-custom-monitored-metrics', + ); + this.$monitoredCustomMetricsCount = this.$monitoredCustomMetricsPanel.find( + '.js-custom-monitored-count', + ); + this.$monitoredCustomMetricsLoading = this.$monitoredCustomMetricsPanel.find( + '.js-loading-custom-metrics', + ); + this.$monitoredCustomMetricsEmpty = this.$monitoredCustomMetricsPanel.find( + '.js-empty-custom-metrics', + ); + this.$monitoredCustomMetricsList = this.$monitoredCustomMetricsPanel.find( + '.js-custom-metrics-list', + ); + this.$monitoredCustomMetricsNoIntegrationText = this.$monitoredCustomMetricsPanel.find( + '.js-no-active-integration-text', + ); + this.$newCustomMetricButton = this.$monitoredCustomMetricsPanel.find('.js-new-metric-button'); + this.$newCustomMetricText = this.$monitoredCustomMetricsPanel.find('.js-new-metric-text'); + this.$flashCustomMetricsContainer = this.$wrapperCustomMetrics.find('.flash-container'); + + this.$els = [ + this.$monitoredCustomMetricsLoading, + this.$monitoredCustomMetricsList, + this.$newCustomMetricButton, + this.$newCustomMetricText, + this.$monitoredCustomMetricsNoIntegrationText, + this.$monitoredCustomMetricsEmpty, + ]; + + this.activeCustomMetricsEndpoint = this.$monitoredCustomMetricsPanel.data( + 'active-custom-metrics', + ); + this.environmentsDataEndpoint = this.$monitoredCustomMetricsPanel.data( + 'environments-data-endpoint', + ); + this.isServiceActive = this.$monitoredCustomMetricsPanel.data('service-active'); + } + + init() { + if (this.isServiceActive) { + this.loadActiveCustomMetrics(); + } else { + this.setNoIntegrationActiveState(); + } + } + + // eslint-disable-next-line class-methods-use-this + setHidden(els) { + els.forEach(el => el.addClass('hidden')); + } + + setVisible(...els) { + this.setHidden(this.$els.filter(el => !els.includes(el))); + els.forEach(el => el.removeClass('hidden')); + } + + showMonitoringCustomMetricsPanelState(stateName) { + switch (stateName) { + case PANEL_STATE.LOADING: + this.setVisible(this.$monitoredCustomMetricsLoading); + break; + case PANEL_STATE.LIST: + this.setVisible(this.$newCustomMetricButton, this.$monitoredCustomMetricsList); + break; + case PANEL_STATE.NO_INTEGRATION: + this.setVisible( + this.$monitoredCustomMetricsNoIntegrationText, + this.$monitoredCustomMetricsEmpty, + ); + break; + default: + this.setVisible( + this.$monitoredCustomMetricsEmpty, + this.$newCustomMetricButton, + this.$newCustomMetricText, + ); + break; + } + } + + populateCustomMetrics() { + const capitalizeGroup = metric => ({ + ...metric, + group: capitalizeFirstCharacter(metric.group), + }); + + const sortedMetrics = sortBy(this.customMetrics.map(capitalizeGroup), ['group', 'title']); + + sortedMetrics.forEach(metric => { + this.$monitoredCustomMetricsList.append(CustomMetrics.customMetricTemplate(metric)); + }); + + this.$monitoredCustomMetricsCount.text(this.customMetrics.length); + this.showMonitoringCustomMetricsPanelState(PANEL_STATE.LIST); + if (!this.environmentsData) { + this.showFlashMessage( + s__( + 'PrometheusService|These metrics will only be monitored after your first deployment to an environment', + ), + ); + } + } + + showFlashMessage(message) { + this.$flashCustomMetricsContainer.removeClass('hidden'); + this.$flashCustomMetricsContainer.find('.flash-text').text(message); + } + + setNoIntegrationActiveState() { + this.showMonitoringCustomMetricsPanelState(PANEL_STATE.NO_INTEGRATION); + this.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY); + } + + loadActiveCustomMetrics() { + super.loadActiveMetrics(); + Promise.all([ + axios.get(this.activeCustomMetricsEndpoint), + axios.get(this.environmentsDataEndpoint), + ]) + .then(([customMetrics, environmentsData]) => { + this.environmentsData = environmentsData.data.environments; + if (!customMetrics.data || !customMetrics.data.metrics) { + this.showMonitoringCustomMetricsPanelState(PANEL_STATE.EMPTY); + } else { + this.customMetrics = customMetrics.data.metrics; + this.populateCustomMetrics(customMetrics.data.metrics); + } + }) + .catch(customMetricError => { + this.showFlashMessage(customMetricError); + this.showMonitoringCustomMetricsPanelState(PANEL_STATE.EMPTY); + }); + } + + static customMetricTemplate(metric) { + return ` + <li class="custom-metric"> + <a href="${escape(metric.edit_path)}" class="custom-metric-link-bold"> + ${escape(metric.group)} / ${escape(metric.title)} (${escape(metric.unit)}) + </a> + </li> + `; + } +} diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb index 21bd2ff9e32..a97216f8a22 100644 --- a/app/helpers/clusters_helper.rb +++ b/app/helpers/clusters_helper.rb @@ -41,6 +41,23 @@ module ClustersHelper end end + def cluster_type_label(cluster_type) + case cluster_type + when 'project_type' + s_('ClusterIntegration|Project cluster') + when 'group_type' + s_('ClusterIntegration|Group cluster') + when 'instance_type' + s_('ClusterIntegration|Instance cluster') + else + Gitlab::ErrorTracking.track_and_raise_for_dev_exception( + ArgumentError.new('Cluster Type Missing'), + cluster_error: { error: 'Cluster Type Missing', cluster_type: cluster_type } + ) + _('Cluster') + end + end + def has_rbac_enabled?(cluster) return cluster.platform_kubernetes_rbac? if cluster.platform_kubernetes diff --git a/app/models/performance_monitoring/prometheus_panel.rb b/app/models/performance_monitoring/prometheus_panel.rb index c03218b4219..0381c5cff10 100644 --- a/app/models/performance_monitoring/prometheus_panel.rb +++ b/app/models/performance_monitoring/prometheus_panel.rb @@ -4,7 +4,7 @@ module PerformanceMonitoring class PrometheusPanel include ActiveModel::Model - attr_accessor :type, :title, :y_label, :weight, :metrics + attr_accessor :type, :title, :y_label, :weight, :metrics, :y_axis validates :title, presence: true validates :metrics, presence: true @@ -20,5 +20,9 @@ module PerformanceMonitoring panel.tap(&:validate!) end + + def id(group_title) + Digest::SHA2.hexdigest([group_title, type, title].join) + end end end diff --git a/app/services/metrics/dashboard/base_service.rb b/app/services/metrics/dashboard/base_service.rb index a19f3f78b3d..219b26defb1 100644 --- a/app/services/metrics/dashboard/base_service.rb +++ b/app/services/metrics/dashboard/base_service.rb @@ -11,6 +11,7 @@ module Metrics SEQUENCE = [ STAGES::CommonMetricsInserter, STAGES::EndpointInserter, + STAGES::PanelIdsInserter, STAGES::Sorter ].freeze diff --git a/app/services/metrics/dashboard/gitlab_alert_embed_service.rb b/app/services/metrics/dashboard/gitlab_alert_embed_service.rb index 5515b84f112..38e89d392ad 100644 --- a/app/services/metrics/dashboard/gitlab_alert_embed_service.rb +++ b/app/services/metrics/dashboard/gitlab_alert_embed_service.rb @@ -10,7 +10,10 @@ module Metrics class GitlabAlertEmbedService < ::Metrics::Dashboard::BaseEmbedService include Gitlab::Utils::StrongMemoize - SEQUENCE = [STAGES::EndpointInserter].freeze + SEQUENCE = [ + STAGES::EndpointInserter, + STAGES::PanelIdsInserter + ].freeze class << self # Determines whether the provided params are sufficient diff --git a/app/services/metrics/dashboard/grafana_metric_embed_service.rb b/app/services/metrics/dashboard/grafana_metric_embed_service.rb index 274057b8262..d58b80162f5 100644 --- a/app/services/metrics/dashboard/grafana_metric_embed_service.rb +++ b/app/services/metrics/dashboard/grafana_metric_embed_service.rb @@ -10,7 +10,8 @@ module Metrics include ReactiveCaching SEQUENCE = [ - ::Gitlab::Metrics::Dashboard::Stages::GrafanaFormatter + ::Gitlab::Metrics::Dashboard::Stages::GrafanaFormatter, + ::Gitlab::Metrics::Dashboard::Stages::PanelIdsInserter ].freeze self.reactive_cache_key = ->(service) { service.cache_key } diff --git a/app/services/metrics/dashboard/predefined_dashboard_service.rb b/app/services/metrics/dashboard/predefined_dashboard_service.rb index 297f00b1be9..f454df63773 100644 --- a/app/services/metrics/dashboard/predefined_dashboard_service.rb +++ b/app/services/metrics/dashboard/predefined_dashboard_service.rb @@ -11,6 +11,7 @@ module Metrics SEQUENCE = [ STAGES::EndpointInserter, + STAGES::PanelIdsInserter, STAGES::Sorter ].freeze diff --git a/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb b/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb index bcdc8a8844f..d97668d1c7c 100644 --- a/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb +++ b/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb @@ -11,6 +11,7 @@ module Metrics SEQUENCE = [ STAGES::CustomMetricsInserter, STAGES::EndpointInserter, + STAGES::PanelIdsInserter, STAGES::Sorter ].freeze diff --git a/app/services/metrics/dashboard/system_dashboard_service.rb b/app/services/metrics/dashboard/system_dashboard_service.rb index 1c9d7f4968a..c28b7b875df 100644 --- a/app/services/metrics/dashboard/system_dashboard_service.rb +++ b/app/services/metrics/dashboard/system_dashboard_service.rb @@ -13,6 +13,7 @@ module Metrics STAGES::CustomMetricsInserter, STAGES::CustomMetricsDetailsInserter, STAGES::EndpointInserter, + STAGES::PanelIdsInserter, STAGES::Sorter ].freeze diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index 4de6b2d2774..8a7b98ab944 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -4,7 +4,7 @@ module Tags class CreateService < BaseService def execute(tag_name, target, message) valid_tag = Gitlab::GitRefValidator.validate(tag_name) - return error('Tag name invalid') unless valid_tag + return error('Tag name invalid', 400) unless valid_tag repository = project.repository message = message&.strip @@ -14,7 +14,7 @@ module Tags begin new_tag = repository.add_tag(current_user, tag_name, target, message) rescue Gitlab::Git::Repository::TagExistsError - return error("Tag #{tag_name} already exists") + return error("Tag #{tag_name} already exists", 409) rescue Gitlab::Git::PreReceiveError => ex return error(ex.message) end @@ -24,7 +24,7 @@ module Tags success.merge(tag: new_tag) else - error("Target #{target} is invalid") + error("Target #{target} is invalid", 400) end end end diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml index 8797178f920..7fc76880480 100644 --- a/app/views/clusters/clusters/show.html.haml +++ b/app/views/clusters/clusters/show.html.haml @@ -41,7 +41,12 @@ .js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } } - %h4= @cluster.name + .d-flex.my-3 + %p.badge.badge-light.p-2.mr-2 + = cluster_type_label(@cluster.cluster_type) + %h4.m-0 + = @cluster.name + = render 'banner' - if cluster_created?(@cluster) @@ -56,7 +61,3 @@ .tab-content.py-3 .tab-pane.active{ role: 'tabpanel' } = render_cluster_info_tab_content(params[:tab], expanded_by_default?) - - - - diff --git a/app/views/projects/services/prometheus/_custom_metrics.html.haml b/app/views/projects/services/prometheus/_custom_metrics.html.haml new file mode 100644 index 00000000000..21f9d1125e0 --- /dev/null +++ b/app/views/projects/services/prometheus/_custom_metrics.html.haml @@ -0,0 +1,30 @@ +- project = local_assigns.fetch(:project) + +.col-lg-3 + %p + = s_('PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope "*" OR a manually configured Prometheus to be available.') + = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus', anchor: 'adding-custom-metrics'), target: '_blank', rel: "noopener noreferrer" + +.col-lg-9 + .card.custom-monitored-metrics.js-panel-custom-monitored-metrics{ data: { active_custom_metrics: project_prometheus_metrics_path(project), environments_data: environments_list_data, service_active: "#{@service.active}" } } + .card-header + %strong + = s_('PrometheusService|Custom metrics') + -# haml-lint:disable NoPlainNodes + %span.badge.badge-pill.js-custom-monitored-count 0 + -# haml-lint:enable NoPlainNodes + = link_to s_('PrometheusService|New metric'), new_project_prometheus_metric_path(project), class: 'btn btn-success js-new-metric-button hidden' + .card-body + .flash-container.hidden + .flash-warning + .flash-text + .loading-metrics.js-loading-custom-metrics + %p.m-3 + = icon('spinner spin', class: 'metrics-load-spinner') + = s_('PrometheusService|Finding custom metrics...') + .empty-metrics.hidden.js-empty-custom-metrics + %p.text-tertiary.m-3.js-no-active-integration-text.hidden + = s_('PrometheusService|Enable Prometheus to define custom metrics, using either option above') + %p.text-tertiary.m-3.js-new-metric-text.hidden + = s_('PrometheusService|No custom metrics have been created. Create one using the button above') + %ul.list-unstyled.metrics-list.hidden.js-custom-metrics-list diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml index 7685dee08fc..3bd5f69f67e 100644 --- a/app/views/projects/services/prometheus/_metrics.html.haml +++ b/app/views/projects/services/prometheus/_metrics.html.haml @@ -1,5 +1,7 @@ - project = local_assigns.fetch(:project) += render 'projects/services/prometheus/custom_metrics', project: project + .col-lg-3 %p = s_('PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters.') |