diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-18 03:09:43 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-18 03:09:43 +0000 |
commit | b4b9b3854eddd2a4829113ebfc1812c3a332a7d9 (patch) | |
tree | 6a21e491917e1606d81329af710459b0217eb1a4 /app | |
parent | 2e31c85a97183814ffa7ba5cc58f7bbad668fb2b (diff) | |
download | gitlab-ce-b4b9b3854eddd2a4829113ebfc1812c3a332a7d9.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
14 files changed, 148 insertions, 106 deletions
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue index b0acd69bae0..03019e4c25e 100644 --- a/app/assets/javascripts/logs/components/environment_logs.vue +++ b/app/assets/javascripts/logs/components/environment_logs.vue @@ -5,15 +5,17 @@ import { GlSprintf, GlAlert, GlDropdown, + GlDropdownDivider, GlDropdownItem, GlFormGroup, GlSearchBoxByClick, GlInfiniteScroll, } from '@gitlab/ui'; +import { s__ } from '~/locale'; import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; import LogControlButtons from './log_control_buttons.vue'; -import { timeRanges, defaultTimeRange } from '~/monitoring/constants'; +import { timeRanges, defaultTimeRange } from '~/vue_shared/constants'; import { timeRangeFromUrl } from '~/monitoring/utils'; import { formatDate } from '../utils'; @@ -22,6 +24,7 @@ export default { GlSprintf, GlAlert, GlDropdown, + GlDropdownDivider, GlDropdownItem, GlFormGroup, GlSearchBoxByClick, @@ -90,6 +93,16 @@ export default { shouldShowElasticStackCallout() { return !this.isElasticStackCalloutDismissed && this.disableAdvancedControls; }, + + podDropdownText() { + if (this.pods.current) { + return this.pods.current; + } else if (this.advancedFeaturesEnabled) { + // "All pods" is a valid option when advanced querying is available + return s__('Environments|All pods'); + } + return s__('Environments|No pod selected'); + }, }, mounted() { this.setInitData({ @@ -178,11 +191,17 @@ export default { > <gl-dropdown id="pods-dropdown" - :text="pods.current || s__('Environments|No pods to display')" + :text="podDropdownText" :disabled="environments.isLoading" class="d-flex gl-h-32 js-pods-dropdown" toggle-class="dropdown-menu-toggle" > + <template v-if="advancedFeaturesEnabled"> + <gl-dropdown-item key="all-pods" @click="showPodLogs(null)"> + {{ s__('Environments|All pods') }} + </gl-dropdown-item> + <gl-dropdown-divider /> + </template> <gl-dropdown-item v-for="podName in pods.options" :key="podName" diff --git a/app/assets/javascripts/logs/stores/actions.js b/app/assets/javascripts/logs/stores/actions.js index 4544ebdfec1..834462573cc 100644 --- a/app/assets/javascripts/logs/stores/actions.js +++ b/app/assets/javascripts/logs/stores/actions.js @@ -82,7 +82,6 @@ export const setTimeRange = ({ dispatch, commit }, timeRange) => { export const showEnvironment = ({ dispatch, commit }, environmentName) => { commit(types.SET_PROJECT_ENVIRONMENT, environmentName); - commit(types.SET_CURRENT_POD_NAME, null); dispatch('fetchLogs'); }; @@ -107,16 +106,16 @@ export const fetchEnvironments = ({ commit, dispatch }, environmentsPath) => { }; export const fetchLogs = ({ commit, state }) => { - commit(types.REQUEST_PODS_DATA); commit(types.REQUEST_LOGS_DATA); return requestLogsUntilData(state) .then(({ data }) => { const { pod_name, pods, logs, cursor } = data; + commit(types.RECEIVE_LOGS_DATA_SUCCESS, { logs, cursor }); + commit(types.SET_CURRENT_POD_NAME, pod_name); commit(types.RECEIVE_PODS_DATA_SUCCESS, pods); - commit(types.RECEIVE_LOGS_DATA_SUCCESS, { logs, cursor }); }) .catch(() => { commit(types.RECEIVE_PODS_DATA_ERROR); diff --git a/app/assets/javascripts/logs/stores/getters.js b/app/assets/javascripts/logs/stores/getters.js index 58f2dbf4835..8770306fdd6 100644 --- a/app/assets/javascripts/logs/stores/getters.js +++ b/app/assets/javascripts/logs/stores/getters.js @@ -1,7 +1,7 @@ import { formatDate } from '../utils'; -const mapTrace = ({ timestamp = null, message = '' }) => - [timestamp ? formatDate(timestamp) : '', message].join(' | '); +const mapTrace = ({ timestamp = null, pod = '', message = '' }) => + [timestamp ? formatDate(timestamp) : '', pod, message].join(' | '); export const trace = state => state.logs.lines.map(mapTrace).join('\n'); diff --git a/app/assets/javascripts/logs/stores/mutation_types.js b/app/assets/javascripts/logs/stores/mutation_types.js index 5ff49135e41..7e7771a9df8 100644 --- a/app/assets/javascripts/logs/stores/mutation_types.js +++ b/app/assets/javascripts/logs/stores/mutation_types.js @@ -14,6 +14,5 @@ export const REQUEST_LOGS_DATA_PREPEND = 'REQUEST_LOGS_DATA_PREPEND'; export const RECEIVE_LOGS_DATA_PREPEND_SUCCESS = 'RECEIVE_LOGS_DATA_PREPEND_SUCCESS'; export const RECEIVE_LOGS_DATA_PREPEND_ERROR = 'RECEIVE_LOGS_DATA_PREPEND_ERROR'; -export const REQUEST_PODS_DATA = 'REQUEST_PODS_DATA'; export const RECEIVE_PODS_DATA_SUCCESS = 'RECEIVE_PODS_DATA_SUCCESS'; export const RECEIVE_PODS_DATA_ERROR = 'RECEIVE_PODS_DATA_ERROR'; diff --git a/app/assets/javascripts/logs/stores/mutations.js b/app/assets/javascripts/logs/stores/mutations.js index d94d71cd25a..d77c2894a05 100644 --- a/app/assets/javascripts/logs/stores/mutations.js +++ b/app/assets/javascripts/logs/stores/mutations.js @@ -1,8 +1,9 @@ import * as types from './mutation_types'; import { convertToFixedRange } from '~/lib/utils/datetime_range'; -const mapLine = ({ timestamp, message }) => ({ +const mapLine = ({ timestamp, pod, message }) => ({ timestamp, + pod, message, }); @@ -21,6 +22,10 @@ export default { // Environments Data [types.SET_PROJECT_ENVIRONMENT](state, environmentName) { state.environments.current = environmentName; + + // Clear current pod options + state.pods.current = null; + state.pods.options = []; }, [types.REQUEST_ENVIRONMENTS_DATA](state) { state.environments.options = []; @@ -81,9 +86,6 @@ export default { [types.SET_CURRENT_POD_NAME](state, podName) { state.pods.current = podName; }, - [types.REQUEST_PODS_DATA](state) { - state.pods.options = []; - }, [types.RECEIVE_PODS_DATA_SUCCESS](state, podOptions) { state.pods.options = podOptions; }, diff --git a/app/assets/javascripts/logs/stores/state.js b/app/assets/javascripts/logs/stores/state.js index e058f15b6b4..2c8f47294cc 100644 --- a/app/assets/javascripts/logs/stores/state.js +++ b/app/assets/javascripts/logs/stores/state.js @@ -1,4 +1,4 @@ -import { timeRanges, defaultTimeRange } from '~/monitoring/constants'; +import { timeRanges, defaultTimeRange } from '~/vue_shared/constants'; import { convertToFixedRange } from '~/lib/utils/datetime_range'; export default () => ({ diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index a0bd45bef5e..dbfb3e97c20 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -31,7 +31,8 @@ import DashboardsDropdown from './dashboards_dropdown.vue'; import TrackEventDirective from '~/vue_shared/directives/track_event'; import { getAddMetricTrackingOptions, timeRangeToUrl, timeRangeFromUrl } from '../utils'; -import { defaultTimeRange, timeRanges, metricStates } from '../constants'; +import { metricStates } from '../constants'; +import { defaultTimeRange, timeRanges } from '~/vue_shared/constants'; export default { components: { diff --git a/app/assets/javascripts/monitoring/components/embed.vue b/app/assets/javascripts/monitoring/components/embed.vue index 826b73908a4..6182b570e76 100644 --- a/app/assets/javascripts/monitoring/components/embed.vue +++ b/app/assets/javascripts/monitoring/components/embed.vue @@ -3,7 +3,8 @@ import { mapActions, mapState, mapGetters } from 'vuex'; import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue'; import { convertToFixedRange } from '~/lib/utils/datetime_range'; import { timeRangeFromUrl, removeTimeRangeParams } from '../utils'; -import { sidebarAnimationDuration, defaultTimeRange } from '../constants'; +import { sidebarAnimationDuration } from '../constants'; +import { defaultTimeRange } from '~/vue_shared/constants'; let sidebarMutationObserver; diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js index ddf6c9878df..cc7f5af2259 100644 --- a/app/assets/javascripts/monitoring/constants.js +++ b/app/assets/javascripts/monitoring/constants.js @@ -1,5 +1,3 @@ -import { __ } from '~/locale'; - export const PROMETHEUS_TIMEOUT = 120000; // TWO_MINUTES /** @@ -89,37 +87,3 @@ export const dateFormats = { timeOfDay: 'h:MM TT', default: 'dd mmm yyyy, h:MMTT', }; - -export const timeRanges = [ - { - label: __('30 minutes'), - duration: { seconds: 60 * 30 }, - }, - { - label: __('3 hours'), - duration: { seconds: 60 * 60 * 3 }, - }, - { - label: __('8 hours'), - duration: { seconds: 60 * 60 * 8 }, - default: true, - }, - { - label: __('1 day'), - duration: { seconds: 60 * 60 * 24 * 1 }, - }, - { - label: __('3 days'), - duration: { seconds: 60 * 60 * 24 * 3 }, - }, - { - label: __('1 week'), - duration: { seconds: 60 * 60 * 24 * 7 * 1 }, - }, - { - label: __('1 month'), - duration: { seconds: 60 * 60 * 24 * 30 }, - }, -]; - -export const defaultTimeRange = timeRanges.find(tr => tr.default); diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue index 9ac687f5e2c..7b09337eb15 100644 --- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue +++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue @@ -43,6 +43,11 @@ export default { required: false, default: () => defaultTimeRanges, }, + customEnabled: { + type: Boolean, + required: false, + default: true, + }, }, data() { return { @@ -166,6 +171,7 @@ export default { > <div class="d-flex justify-content-between gl-p-2"> <gl-form-group + v-if="customEnabled" :label="__('Custom range')" label-for="custom-from-time" label-class="gl-pb-1" diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js new file mode 100644 index 00000000000..63ce4212717 --- /dev/null +++ b/app/assets/javascripts/vue_shared/constants.js @@ -0,0 +1,56 @@ +import { __ } from '~/locale'; + +const INTERVALS = { + minute: 'minute', + hour: 'hour', + day: 'day', +}; + +export const timeRanges = [ + { + label: __('30 minutes'), + duration: { seconds: 60 * 30 }, + name: 'thirtyMinutes', + interval: INTERVALS.minute, + }, + { + label: __('3 hours'), + duration: { seconds: 60 * 60 * 3 }, + name: 'threeHours', + interval: INTERVALS.hour, + }, + { + label: __('8 hours'), + duration: { seconds: 60 * 60 * 8 }, + name: 'eightHours', + default: true, + interval: INTERVALS.hour, + }, + { + label: __('1 day'), + duration: { seconds: 60 * 60 * 24 * 1 }, + name: 'oneDay', + interval: INTERVALS.hour, + }, + { + label: __('3 days'), + duration: { seconds: 60 * 60 * 24 * 3 }, + name: 'threeDays', + interval: INTERVALS.hour, + }, + { + label: __('1 week'), + duration: { seconds: 60 * 60 * 24 * 7 * 1 }, + name: 'oneWeek', + interval: INTERVALS.day, + }, + { + label: __('1 month'), + duration: { seconds: 60 * 60 * 24 * 30 }, + name: 'oneMonth', + interval: INTERVALS.day, + }, +]; + +export const defaultTimeRange = timeRanges.find(tr => tr.default); +export const getTimeWindow = timeWindowName => timeRanges.find(tr => tr.name === timeWindowName); diff --git a/app/services/pod_logs/base_service.rb b/app/services/pod_logs/base_service.rb index d94d4e92eb6..8cc8fb913a2 100644 --- a/app/services/pod_logs/base_service.rb +++ b/app/services/pod_logs/base_service.rb @@ -55,22 +55,10 @@ module PodLogs return error(_('Cluster does not exist')) if cluster.nil? return error(_('Namespace is empty')) if namespace.blank? - success(result) - end - - def check_param_lengths(_result) - pod_name = params['pod_name'].presence - container_name = params['container_name'].presence + result[:pod_name] = params['pod_name'].presence + result[:container_name] = params['container_name'].presence - if pod_name&.length.to_i > K8S_NAME_MAX_LENGTH - return error(_('pod_name cannot be larger than %{max_length}'\ - ' chars' % { max_length: K8S_NAME_MAX_LENGTH })) - elsif container_name&.length.to_i > K8S_NAME_MAX_LENGTH - return error(_('container_name cannot be larger than'\ - ' %{max_length} chars' % { max_length: K8S_NAME_MAX_LENGTH })) - end - - success(pod_name: pod_name, container_name: container_name) + success(result) end def get_raw_pods(result) @@ -85,40 +73,6 @@ module PodLogs success(result) end - def check_pod_name(result) - # If pod_name is not received as parameter, get the pod logs of the first - # pod of this namespace. - result[:pod_name] ||= result[:pods].first - - unless result[:pod_name] - return error(_('No pods available')) - end - - unless result[:pods].include?(result[:pod_name]) - return error(_('Pod does not exist')) - end - - success(result) - end - - def check_container_name(result) - pod_details = result[:raw_pods].first { |p| p.metadata.name == result[:pod_name] } - containers = pod_details.spec.containers.map(&:name) - - # select first container if not specified - result[:container_name] ||= containers.first - - unless result[:container_name] - return error(_('No containers available')) - end - - unless containers.include?(result[:container_name]) - return error(_('Container does not exist')) - end - - success(result) - end - def pod_logs(result) raise NotImplementedError end diff --git a/app/services/pod_logs/elasticsearch_service.rb b/app/services/pod_logs/elasticsearch_service.rb index 3bb6e2bd846..11862de4ade 100644 --- a/app/services/pod_logs/elasticsearch_service.rb +++ b/app/services/pod_logs/elasticsearch_service.rb @@ -3,11 +3,8 @@ module PodLogs class ElasticsearchService < PodLogs::BaseService steps :check_arguments, - :check_param_lengths, :get_raw_pods, :get_pod_names, - :check_pod_name, - :check_container_name, :check_times, :check_search, :check_cursor, @@ -53,7 +50,7 @@ module PodLogs response = ::Gitlab::Elasticsearch::Logs.new(client).pod_logs( namespace, - result[:pod_name], + pod_name: result[:pod_name], container_name: result[:container_name], search: result[:search], start_time: result[:start], diff --git a/app/services/pod_logs/kubernetes_service.rb b/app/services/pod_logs/kubernetes_service.rb index 6c8ed74f8e1..92ebb84b877 100644 --- a/app/services/pod_logs/kubernetes_service.rb +++ b/app/services/pod_logs/kubernetes_service.rb @@ -8,7 +8,6 @@ module PodLogs EncodingHelperError = Class.new(StandardError) steps :check_arguments, - :check_param_lengths, :get_raw_pods, :get_pod_names, :check_pod_name, @@ -22,6 +21,50 @@ module PodLogs private + def check_pod_name(result) + # If pod_name is not received as parameter, get the pod logs of the first + # pod of this namespace. + result[:pod_name] ||= result[:pods].first + + unless result[:pod_name] + return error(_('No pods available')) + end + + unless result[:pod_name].length.to_i <= K8S_NAME_MAX_LENGTH + return error(_('pod_name cannot be larger than %{max_length}'\ + ' chars' % { max_length: K8S_NAME_MAX_LENGTH })) + end + + unless result[:pods].include?(result[:pod_name]) + return error(_('Pod does not exist')) + end + + success(result) + end + + def check_container_name(result) + pod_details = result[:raw_pods].first { |p| p.metadata.name == result[:pod_name] } + containers = pod_details.spec.containers.map(&:name) + + # select first container if not specified + result[:container_name] ||= containers.first + + unless result[:container_name] + return error(_('No containers available')) + end + + unless result[:container_name].length.to_i <= K8S_NAME_MAX_LENGTH + return error(_('container_name cannot be larger than'\ + ' %{max_length} chars' % { max_length: K8S_NAME_MAX_LENGTH })) + end + + unless containers.include?(result[:container_name]) + return error(_('Container does not exist')) + end + + success(result) + end + def pod_logs(result) result[:logs] = cluster.kubeclient.get_pod_log( result[:pod_name], @@ -62,7 +105,8 @@ module PodLogs values = line.split(' ', 2) { timestamp: values[0], - message: values[1] + message: values[1], + pod: result[:pod_name] } end |