Commit e795f1c9 authored by Adrien Kohlbecker's avatar Adrien Kohlbecker Committed by Kushal Pandya

Fix logs api etag issues with elasticsearch

Etag cache is not currently getting cleared
parent 64e213a3
---
title: Fix logs api etag issues with elasticsearch
merge_request: 23249
author:
type: fixed
...@@ -11,7 +11,8 @@ export default { ...@@ -11,7 +11,8 @@ export default {
groupEpicsPath: groupEpicsPath:
'/api/:version/groups/:id/epics?include_ancestor_groups=:includeAncestorGroups&include_descendant_groups=:includeDescendantGroups', '/api/:version/groups/:id/epics?include_ancestor_groups=:includeAncestorGroups&include_descendant_groups=:includeDescendantGroups',
epicIssuePath: '/api/:version/groups/:id/epics/:epic_iid/issues/:issue_id', epicIssuePath: '/api/:version/groups/:id/epics/:epic_iid/issues/:issue_id',
podLogsPath: '/:project_full_path/-/logs/k8s.json', k8sPodLogsPath: ':project_path/-/logs/k8s.json',
elasticsearchPodLogsPath: ':project_path/-/logs/elasticsearch.json',
groupPackagesPath: '/api/:version/groups/:id/packages', groupPackagesPath: '/api/:version/groups/:id/packages',
projectPackagesPath: '/api/:version/projects/:id/packages', projectPackagesPath: '/api/:version/projects/:id/packages',
projectPackagePath: '/api/:version/projects/:id/packages/:package_id', projectPackagePath: '/api/:version/projects/:id/packages/:package_id',
...@@ -93,19 +94,24 @@ export default { ...@@ -93,19 +94,24 @@ export default {
* Returns pods logs for an environment with an optional pod and container * Returns pods logs for an environment with an optional pod and container
* *
* @param {Object} params * @param {Object} params
* @param {string} params.projectFullPath - Path of the project, in format `/<namespace>/<project-key>` * @param {Object} param.environment - Environment object
* @param {number} params.environmentId - Id of the environment
* @param {string=} params.podName - Pod name, if not set the backend assumes a default one * @param {string=} params.podName - Pod name, if not set the backend assumes a default one
* @param {string=} params.containerName - Container name, if not set the backend assumes a default one * @param {string=} params.containerName - Container name, if not set the backend assumes a default one
* @param {string=} params.start - Starting date to query the logs in ISO format * @param {string=} params.start - Starting date to query the logs in ISO format
* @param {string=} params.end - Ending date to query the logs in ISO format * @param {string=} params.end - Ending date to query the logs in ISO format
* @returns {Promise} Axios promise for the result of a GET request of logs * @returns {Promise} Axios promise for the result of a GET request of logs
*/ */
getPodLogs({ projectPath, environmentName, podName, containerName, search, start, end }) { getPodLogs({ environment, podName, containerName, search, start, end }) {
const url = this.buildUrl(this.podLogsPath).replace(':project_full_path', projectPath); let baseUrl;
if (environment.enable_advanced_logs_querying) {
baseUrl = this.elasticsearchPodLogsPath;
} else {
baseUrl = this.k8sPodLogsPath;
}
const url = this.buildUrl(baseUrl.replace(':project_path', environment.project_path));
const params = { const params = {
environment_name: environmentName, environment_name: environment.name,
}; };
if (podName) { if (podName) {
......
...@@ -14,10 +14,6 @@ export default { ...@@ -14,10 +14,6 @@ export default {
LogControlButtons, LogControlButtons,
}, },
props: { props: {
projectFullPath: {
type: String,
required: true,
},
environmentName: { environmentName: {
type: String, type: String,
required: false, required: false,
...@@ -45,13 +41,7 @@ export default { ...@@ -45,13 +41,7 @@ export default {
}; };
}, },
computed: { computed: {
...mapState('environmentLogs', [ ...mapState('environmentLogs', ['environments', 'timeWindow', 'logs', 'pods']),
'environments',
'timeWindow',
'logs',
'pods',
'enableAdvancedQuerying',
]),
...mapGetters('environmentLogs', ['trace']), ...mapGetters('environmentLogs', ['trace']),
showLoader() { showLoader() {
return this.logs.isLoading || !this.logs.isComplete; return this.logs.isLoading || !this.logs.isComplete;
...@@ -60,7 +50,10 @@ export default { ...@@ -60,7 +50,10 @@ export default {
return gon.features && gon.features.enableClusterApplicationElasticStack; return gon.features && gon.features.enableClusterApplicationElasticStack;
}, },
advancedFeaturesEnabled() { advancedFeaturesEnabled() {
return this.featureElasticEnabled && this.enableAdvancedQuerying; const environment = this.environments.options.find(
({ name }) => name === this.environments.current,
);
return this.featureElasticEnabled && environment && environment.enable_advanced_logs_querying;
}, },
shouldShowElasticStackCallout() { shouldShowElasticStackCallout() {
return ( return (
...@@ -83,7 +76,6 @@ export default { ...@@ -83,7 +76,6 @@ export default {
}, },
mounted() { mounted() {
this.setInitData({ this.setInitData({
projectPath: this.projectFullPath,
environmentName: this.environmentName, environmentName: this.environmentName,
podName: this.currentPodName, podName: this.currentPodName,
}); });
...@@ -157,7 +149,7 @@ export default { ...@@ -157,7 +149,7 @@ export default {
<gl-dropdown <gl-dropdown
id="pods-dropdown" id="pods-dropdown"
:text="pods.current || s__('Environments|No pods to display')" :text="pods.current || s__('Environments|No pods to display')"
:disabled="logs.isLoading" :disabled="environments.isLoading"
class="d-flex gl-h-32 js-pods-dropdown" class="d-flex gl-h-32 js-pods-dropdown"
toggle-class="dropdown-menu-toggle" toggle-class="dropdown-menu-toggle"
> >
......
...@@ -24,11 +24,9 @@ const requestLogsUntilData = params => ...@@ -24,11 +24,9 @@ const requestLogsUntilData = params =>
}); });
}); });
export const setInitData = ({ dispatch, commit }, { projectPath, environmentName, podName }) => { export const setInitData = ({ commit }, { environmentName, podName }) => {
commit(types.SET_PROJECT_PATH, projectPath);
commit(types.SET_PROJECT_ENVIRONMENT, environmentName); commit(types.SET_PROJECT_ENVIRONMENT, environmentName);
commit(types.SET_CURRENT_POD_NAME, podName); commit(types.SET_CURRENT_POD_NAME, podName);
dispatch('fetchLogs');
}; };
export const showPodLogs = ({ dispatch, commit }, podName) => { export const showPodLogs = ({ dispatch, commit }, podName) => {
...@@ -52,13 +50,14 @@ export const showEnvironment = ({ dispatch, commit }, environmentName) => { ...@@ -52,13 +50,14 @@ export const showEnvironment = ({ dispatch, commit }, environmentName) => {
dispatch('fetchLogs'); dispatch('fetchLogs');
}; };
export const fetchEnvironments = ({ commit }, environmentsPath) => { export const fetchEnvironments = ({ commit, dispatch }, environmentsPath) => {
commit(types.REQUEST_ENVIRONMENTS_DATA); commit(types.REQUEST_ENVIRONMENTS_DATA);
axios axios
.get(environmentsPath) .get(environmentsPath)
.then(({ data }) => { .then(({ data }) => {
commit(types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, data.environments); commit(types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, data.environments);
dispatch('fetchLogs');
}) })
.catch(() => { .catch(() => {
commit(types.RECEIVE_ENVIRONMENTS_DATA_ERROR); commit(types.RECEIVE_ENVIRONMENTS_DATA_ERROR);
...@@ -68,8 +67,7 @@ export const fetchEnvironments = ({ commit }, environmentsPath) => { ...@@ -68,8 +67,7 @@ export const fetchEnvironments = ({ commit }, environmentsPath) => {
export const fetchLogs = ({ commit, state }) => { export const fetchLogs = ({ commit, state }) => {
const params = { const params = {
projectPath: state.projectPath, environment: state.environments.options.find(({ name }) => name === state.environments.current),
environmentName: state.environments.current,
podName: state.pods.current, podName: state.pods.current,
search: state.search, search: state.search,
}; };
...@@ -87,8 +85,7 @@ export const fetchLogs = ({ commit, state }) => { ...@@ -87,8 +85,7 @@ export const fetchLogs = ({ commit, state }) => {
return requestLogsUntilData(params) return requestLogsUntilData(params)
.then(({ data }) => { .then(({ data }) => {
const { pod_name, pods, logs, enable_advanced_querying } = data; const { pod_name, pods, logs } = data;
commit(types.ENABLE_ADVANCED_QUERYING, enable_advanced_querying);
commit(types.SET_CURRENT_POD_NAME, pod_name); commit(types.SET_CURRENT_POD_NAME, pod_name);
commit(types.RECEIVE_PODS_DATA_SUCCESS, pods); commit(types.RECEIVE_PODS_DATA_SUCCESS, pods);
......
export const SET_PROJECT_PATH = 'SET_PROJECT_PATH';
export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT'; export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT';
export const SET_SEARCH = 'SET_SEARCH'; export const SET_SEARCH = 'SET_SEARCH';
export const ENABLE_ADVANCED_QUERYING = 'ENABLE_ADVANCED_QUERYING';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW'; export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA'; export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA';
......
import * as types from './mutation_types'; import * as types from './mutation_types';
export default { export default {
/** Project data */
[types.SET_PROJECT_PATH](state, projectPath) {
state.projectPath = projectPath;
},
/** Search data */ /** Search data */
[types.SET_SEARCH](state, searchQuery) { [types.SET_SEARCH](state, searchQuery) {
state.search = searchQuery; state.search = searchQuery;
}, },
/** Log source supports advanced features */
[types.ENABLE_ADVANCED_QUERYING](state, enableAdvancedQuerying) {
state.enableAdvancedQuerying = enableAdvancedQuerying;
},
/** Time Range data */ /** Time Range data */
[types.SET_TIME_WINDOW](state, timeWindowKey) { [types.SET_TIME_WINDOW](state, timeWindowKey) {
state.timeWindow.current = timeWindowKey; state.timeWindow.current = timeWindowKey;
......
import { defaultTimeWindow, timeWindows } from '../constants'; import { defaultTimeWindow, timeWindows } from '../constants';
export default () => ({ export default () => ({
/**
* Current project path
*/
projectPath: '',
/** /**
* Full text search * Full text search
*/ */
search: '', search: '',
/**
* True if log source is elasticsearch
*/
enableAdvancedQuerying: false,
/** /**
* Time range (Show last) * Time range (Show last)
*/ */
......
...@@ -17,6 +17,16 @@ module Projects ...@@ -17,6 +17,16 @@ module Projects
end end
def k8s def k8s
render_logs
end
def elasticsearch
render_logs
end
private
def render_logs
::Gitlab::UsageCounters::PodLogs.increment(project.id) ::Gitlab::UsageCounters::PodLogs.increment(project.id)
::Gitlab::PollingInterval.set_header(response, interval: 3_000) ::Gitlab::PollingInterval.set_header(response, interval: 3_000)
...@@ -31,8 +41,6 @@ module Projects ...@@ -31,8 +41,6 @@ module Projects
end end
end end
private
def index_params def index_params
params.permit(:environment_name) params.permit(:environment_name)
end end
......
...@@ -34,7 +34,6 @@ module EE ...@@ -34,7 +34,6 @@ module EE
{ {
"environment-name": environment.name, "environment-name": environment.name,
"environments-path": project_environments_path(project, format: :json), "environments-path": project_environments_path(project, format: :json),
"project-full-path": project.full_path,
"environment-id": environment.id, "environment-id": environment.id,
"cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack') "cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack')
} }
......
...@@ -72,9 +72,14 @@ module EE ...@@ -72,9 +72,14 @@ module EE
environment = ::Environment.find_by(id: opts['environment_id']) environment = ::Environment.find_by(id: opts['environment_id'])
return unless environment return unless environment
method = elastic_stack_available? ? :elasticsearch_project_logs_path : :k8s_project_logs_path
::Gitlab::EtagCaching::Store.new.tap do |store| ::Gitlab::EtagCaching::Store.new.tap do |store|
store.touch( store.touch(
::Gitlab::Routing.url_helpers.k8s_project_logs_path( # not using send with untrusted input, this is better for readability
# rubocop:disable GitlabSecurity/PublicSend
::Gitlab::Routing.url_helpers.send(
method,
environment.project, environment.project,
environment_name: environment.name, environment_name: environment.name,
pod_name: opts['pod_name'], pod_name: opts['pod_name'],
...@@ -86,11 +91,14 @@ module EE ...@@ -86,11 +91,14 @@ module EE
end end
end end
def elastic_stack_available?
::Feature.enabled?(:enable_cluster_application_elastic_stack) && !!cluster.application_elastic_stack
end
private private
def pod_logs(pod_name, namespace, container: nil, search: nil, start_time: nil, end_time: nil) def pod_logs(pod_name, namespace, container: nil, search: nil, start_time: nil, end_time: nil)
enable_advanced_querying = ::Feature.enabled?(:enable_cluster_application_elastic_stack) && !!elastic_stack_client logs = if elastic_stack_available?
logs = if enable_advanced_querying
elastic_stack_pod_logs(namespace, pod_name, container, search, start_time, end_time) elastic_stack_pod_logs(namespace, pod_name, container, search, start_time, end_time)
else else
platform_pod_logs(namespace, pod_name, container) platform_pod_logs(namespace, pod_name, container)
...@@ -100,8 +108,7 @@ module EE ...@@ -100,8 +108,7 @@ module EE
logs: logs, logs: logs,
status: :success, status: :success,
pod_name: pod_name, pod_name: pod_name,
container_name: container, container_name: container
enable_advanced_querying: enable_advanced_querying
} }
end end
......
...@@ -11,10 +11,18 @@ module EE ...@@ -11,10 +11,18 @@ module EE
expose :project_path do |environment| expose :project_path do |environment|
project_path(environment.project) project_path(environment.project)
end end
expose :enable_advanced_logs_querying, if: -> (*) { can_read_pod_logs? } do |environment|
environment.deployment_platform&.elastic_stack_available?
end
end end
private private
def can_read_pod_logs?
can?(current_user, :read_pod_logs, environment.project)
end
def can_read_deploy_board? def can_read_deploy_board?
can?(current_user, :read_deploy_board, environment.project) can?(current_user, :read_deploy_board, environment.project)
end end
......
...@@ -9,7 +9,7 @@ class PodLogsService < ::BaseService ...@@ -9,7 +9,7 @@ class PodLogsService < ::BaseService
PARAMS = %w(pod_name container_name search start end).freeze PARAMS = %w(pod_name container_name search start end).freeze
SUCCESS_RETURN_KEYS = [:status, :logs, :pod_name, :container_name, :pods, :enable_advanced_querying].freeze SUCCESS_RETURN_KEYS = [:status, :logs, :pod_name, :container_name, :pods].freeze
steps :check_param_lengths, steps :check_param_lengths,
:check_deployment_platform, :check_deployment_platform,
...@@ -95,7 +95,7 @@ class PodLogsService < ::BaseService ...@@ -95,7 +95,7 @@ class PodLogsService < ::BaseService
return { status: :processing } unless response return { status: :processing } unless response
result.merge!(response.slice(:pod_name, :container_name, :logs, :enable_advanced_querying)) result.merge!(response.slice(:pod_name, :container_name, :logs))
if response[:status] == :error if response[:status] == :error
error(response[:error]).reverse_merge(result) error(response[:error]).reverse_merge(result)
......
...@@ -63,6 +63,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -63,6 +63,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :logs, only: [:index] do resources :logs, only: [:index] do
collection do collection do
get :k8s get :k8s
get :elasticsearch
end end
end end
......
...@@ -12,6 +12,10 @@ module EE ...@@ -12,6 +12,10 @@ module EE
::Gitlab::EtagCaching::Router::Route.new( ::Gitlab::EtagCaching::Router::Route.new(
%r(#{::Gitlab::EtagCaching::Router::RESERVED_WORDS_PREFIX}/logs/k8s\.json(\?.*)?\z), %r(#{::Gitlab::EtagCaching::Router::RESERVED_WORDS_PREFIX}/logs/k8s\.json(\?.*)?\z),
'k8s_pod_logs' 'k8s_pod_logs'
),
::Gitlab::EtagCaching::Router::Route.new(
%r(#{::Gitlab::EtagCaching::Router::RESERVED_WORDS_PREFIX}/logs/elasticsearch\.json(\?.*)?\z),
'elasticsearch_pod_logs'
) )
].freeze ].freeze
......
...@@ -165,11 +165,16 @@ describe('Api', () => { ...@@ -165,11 +165,16 @@ describe('Api', () => {
}); });
describe('getPodLogs', () => { describe('getPodLogs', () => {
const projectPath = 'root/test-project'; const projectPath = '/root/test-project';
const environmentName = 'production'; const environmentName = 'production';
const podName = 'pod'; const podName = 'pod';
const containerName = 'container'; const containerName = 'container';
const search = 'foo +bar'; const search = 'foo +bar';
const environment = {
name: environmentName,
enable_advanced_logs_querying: false,
project_path: projectPath,
};
const getRequest = () => mock.history.get[0]; const getRequest = () => mock.history.get[0];
...@@ -182,9 +187,9 @@ describe('Api', () => { ...@@ -182,9 +187,9 @@ describe('Api', () => {
}); });
it('calls `axios.get` with pod_name and container_name', done => { it('calls `axios.get` with pod_name and container_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`; const expectedUrl = `${dummyUrlRoot}${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentName, podName, containerName }) Api.getPodLogs({ environment, podName, containerName })
.then(() => { .then(() => {
expect(getRequest().url).toBe(expectedUrl); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({ expect(getRequest().params).toEqual({
...@@ -198,9 +203,9 @@ describe('Api', () => { ...@@ -198,9 +203,9 @@ describe('Api', () => {
}); });
it('calls `axios.get` without pod_name and container_name', done => { it('calls `axios.get` without pod_name and container_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`; const expectedUrl = `${dummyUrlRoot}${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentName }) Api.getPodLogs({ environment })
.then(() => { .then(() => {
expect(getRequest().url).toBe(expectedUrl); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({ expect(getRequest().params).toEqual({
...@@ -212,9 +217,9 @@ describe('Api', () => { ...@@ -212,9 +217,9 @@ describe('Api', () => {
}); });
it('calls `axios.get` with pod_name', done => { it('calls `axios.get` with pod_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`; const expectedUrl = `${dummyUrlRoot}${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentName, podName }) Api.getPodLogs({ environment, podName })
.then(() => { .then(() => {
expect(getRequest().url).toBe(expectedUrl); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({ expect(getRequest().params).toEqual({
...@@ -227,9 +232,9 @@ describe('Api', () => { ...@@ -227,9 +232,9 @@ describe('Api', () => {
}); });
it('calls `axios.get` with pod_name and search', done => { it('calls `axios.get` with pod_name and search', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`; const expectedUrl = `${dummyUrlRoot}${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentName, podName, search }) Api.getPodLogs({ environment, podName, search })
.then(() => { .then(() => {
expect(getRequest().url).toBe(expectedUrl); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({ expect(getRequest().params).toEqual({
......
...@@ -6,7 +6,6 @@ import EnvironmentLogs from 'ee/logs/components/environment_logs.vue'; ...@@ -6,7 +6,6 @@ import EnvironmentLogs from 'ee/logs/components/environment_logs.vue';
import { createStore } from 'ee/logs/stores'; import { createStore } from 'ee/logs/stores';
import { scrollDown } from '~/lib/utils/scroll_utils'; import { scrollDown } from '~/lib/utils/scroll_utils';
import { import {
mockProjectPath,
mockEnvName, mockEnvName,
mockEnvironments, mockEnvironments,
mockPods, mockPods,
...@@ -26,7 +25,6 @@ describe('EnvironmentLogs', () => { ...@@ -26,7 +25,6 @@ describe('EnvironmentLogs', () => {
let state; let state;
const propsData = { const propsData = {
projectFullPath: mockProjectPath,
environmentName: mockEnvName, environmentName: mockEnvName,
environmentsPath: mockEnvironmentsEndpoint, environmentsPath: mockEnvironmentsEndpoint,
clusterApplicationsDocumentationPath: mockDocumentationPath, clusterApplicationsDocumentationPath: mockDocumentationPath,
...@@ -53,7 +51,6 @@ describe('EnvironmentLogs', () => { ...@@ -53,7 +51,6 @@ describe('EnvironmentLogs', () => {
state.pods.options = mockPods; state.pods.options = mockPods;
state.environments.current = mockEnvName; state.environments.current = mockEnvName;
[state.pods.current] = state.pods.options; [state.pods.current] = state.pods.options;
state.enableAdvancedQuerying = true;
state.logs.isComplete = false; state.logs.isComplete = false;
state.logs.lines = mockLogsResult; state.logs.lines = mockLogsResult;
...@@ -133,7 +130,6 @@ describe('EnvironmentLogs', () => { ...@@ -133,7 +130,6 @@ describe('EnvironmentLogs', () => {
expect(actionMocks.setInitData).toHaveBeenCalledTimes(1); expect(actionMocks.setInitData).toHaveBeenCalledTimes(1);
expect(actionMocks.setInitData).toHaveBeenLastCalledWith({ expect(actionMocks.setInitData).toHaveBeenLastCalledWith({
projectPath: mockProjectPath,
environmentName: mockEnvName, environmentName: mockEnvName,
podName: null, podName: null,
}); });
...@@ -146,11 +142,15 @@ describe('EnvironmentLogs', () => { ...@@ -146,11 +142,15 @@ describe('EnvironmentLogs', () => {
beforeEach(() => { beforeEach(() => {
state.pods.options = []; state.pods.options = [];
state.logs.lines = []; state.logs = {
state.logs.isLoading = true; lines: [],
isLoading: true,
};
state.environments.options = []; state.environments = {
state.environments.isLoading = true; options: [],
isLoading: true,
};
initWrapper(); initWrapper();
}); });
...@@ -179,12 +179,57 @@ describe('EnvironmentLogs', () => { ...@@ -179,12 +179,57 @@ describe('EnvironmentLogs', () => {
}); });
}); });
describe('elastic stack disabled', () => {
beforeEach(() => {
gon.features = gon.features || {};
gon.features.enableClusterApplicationElasticStack = false;
initWrapper();
});
it("doesn't display the search bar", () => {
expect(findSearchBar().exists()).toEqual(false);
expect(wrapper.find('#environments-dropdown-fg').attributes('class')).toEqual('px-1 col-6');
expect(wrapper.find('#pods-dropdown-fg').attributes('class')).toEqual('px-1 col-6');
});
});
describe('ES enabled and legacy environment', () => {
beforeEach(() => {
state.pods.options = [];
state.logs = {
lines: [],
isLoading: false,
};
state.environments = {
options: mockEnvironments,
current: 'staging',
isLoading: false,
};
gon.features = gon.features || {};
gon.features.enableClusterApplicationElasticStack = true;
initWrapper();
});
it('displays a disabled search bar', () => {
expect(findSearchBar().exists()).toEqual(true);
expect(findSearchBar().attributes('disabled')).toEqual('true');
});
});
describe('state with data', () => { describe('state with data', () => {
beforeEach(() => { beforeEach(() => {
actionMocks.setInitData.mockImplementation(mockSetInitData); actionMocks.setInitData.mockImplementation(mockSetInitData);
actionMocks.showPodLogs.mockImplementation(mockShowPodLogs); actionMocks.showPodLogs.mockImplementation(mockShowPodLogs);
actionMocks.fetchEnvironments.mockImplementation(mockFetchEnvs); actionMocks.fetchEnvironments.mockImplementation(mockFetchEnvs);
gon.features = gon.features || {};
gon.features.enableClusterApplicationElasticStack = true;
initWrapper(); initWrapper();
}); });
...@@ -300,11 +345,15 @@ describe('EnvironmentLogs', () => { ...@@ -300,11 +345,15 @@ describe('EnvironmentLogs', () => {
beforeEach(() => { beforeEach(() => {
state.pods.options = []; state.pods.options = [];
state.logs.lines = []; state.logs = {
state.logs.isLoading = true; lines: [],
isLoading: true,
};
state.environments.options = []; state.environments = {
state.environments.isLoading = true; options: [],
isLoading: true,
};
initWrapper(); initWrapper();
}); });
...@@ -323,11 +372,15 @@ describe('EnvironmentLogs', () => { ...@@ -323,11 +372,15 @@ describe('EnvironmentLogs', () => {
beforeEach(() => { beforeEach(() => {
state.pods.options = []; state.pods.options = [];
state.logs.lines = []; state.logs = {
state.logs.isLoading = false; lines: [],
isLoading: false,
};
state.environments.options = []; state.environments = {
state.environments.isLoading = false; options: [],
isLoading: false,
};
state.enableAdvancedQuerying = false; state.enableAdvancedQuerying = false;
......
...@@ -2,20 +2,21 @@ export const mockProjectPath = 'root/autodevops-deploy'; ...@@ -2,20 +2,21 @@ export const mockProjectPath = 'root/autodevops-deploy';
export const mockEnvName = 'production'; export const mockEnvName = 'production';
export const mockEnvironmentsEndpoint = `${mockProjectPath}/environments.json`; export const mockEnvironmentsEndpoint = `${mockProjectPath}/environments.json`;
export const mockEnvId = '99'; export const mockEnvId = '99';
export const mockEnableAdvancedQuerying = true;
export const mockDocumentationPath = '/documentation.md'; export const mockDocumentationPath = '/documentation.md';
const makeMockEnvironment = (id, name) => ({ const makeMockEnvironment = (id, name, advancedQuerying) => ({
id, id,
logs_path: `${mockProjectPath}/environments/${id}/logs`, logs_path: `${mockProjectPath}/environments/${id}/logs`,
project_path: mockProjectPath,
name, name,
enable_advanced_logs_querying: advancedQuerying,
}); });
export const mockEnvironment = makeMockEnvironment(mockEnvId, mockEnvName); export const mockEnvironment = makeMockEnvironment(mockEnvId, mockEnvName, true);
export const mockEnvironments = [ export const mockEnvironments = [
mockEnvironment, mockEnvironment,
makeMockEnvironment(101, 'staging'), makeMockEnvironment(101, 'staging', false),
makeMockEnvironment(102, 'review/a-feature'), makeMockEnvironment(102, 'review/a-feature', false),
]; ];
export const mockPodName = 'production-764c58d697-aaaaa'; export const mockPodName = 'production-764c58d697-aaaaa';
......
...@@ -25,7 +25,6 @@ import { ...@@ -25,7 +25,6 @@ import {
mockLogsResult, mockLogsResult,
mockEnvName, mockEnvName,
mockSearch, mockSearch,
mockEnableAdvancedQuerying,
} from '../mock_data'; } from '../mock_data';
jest.mock('~/flash'); jest.mock('~/flash');
...@@ -54,14 +53,13 @@ describe('Logs Store actions', () => { ...@@ -54,14 +53,13 @@ describe('Logs Store actions', () => {
it('should commit environment and pod name mutation', done => { it('should commit environment and pod name mutation', done => {
testAction( testAction(
setInitData, setInitData,
{ projectPath: mockProjectPath, environmentName: mockEnvName, podName: mockPodName }, { environmentName: mockEnvName, podName: mockPodName },
state, state,
[ [
{ type: types.SET_PROJECT_PATH, payload: mockProjectPath },
{ type: types.SET_PROJECT_ENVIRONMENT, payload: mockEnvName }, { type: types.SET_PROJECT_ENVIRONMENT, payload: mockEnvName },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }, { type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
], ],
[{ type: 'fetchLogs' }], [],
done, done,
); );
}); });
...@@ -108,7 +106,7 @@ describe('Logs Store actions', () => { ...@@ -108,7 +106,7 @@ describe('Logs Store actions', () => {
{ type: types.REQUEST_ENVIRONMENTS_DATA }, { type: types.REQUEST_ENVIRONMENTS_DATA },
{ type: types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, payload: mockEnvironments }, { type: types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, payload: mockEnvironments },
], ],
[], [{ type: 'fetchLogs' }],
done, done,
); );
}); });
...@@ -142,11 +140,11 @@ describe('Logs Store actions', () => { ...@@ -142,11 +140,11 @@ describe('Logs Store actions', () => {
}); });
it('should commit logs and pod data when there is pod name defined', done => { it('should commit logs and pod data when there is pod name defined', done => {
state.projectPath = mockProjectPath; state.environments.options = mockEnvironments;
state.environments.current = mockEnvName; state.environments.current = mockEnvName;
state.pods.current = mockPodName; state.pods.current = mockPodName;
const endpoint = `/${mockProjectPath}/-/logs/k8s.json`; const endpoint = `/${mockProjectPath}/-/logs/elasticsearch.json`;
mock mock
.onGet(endpoint, { .onGet(endpoint, {
...@@ -156,7 +154,6 @@ describe('Logs Store actions', () => { ...@@ -156,7 +154,6 @@ describe('Logs Store actions', () => {
pod_name: mockPodName, pod_name: mockPodName,
pods: mockPods, pods: mockPods,
logs: mockLogsResult, logs: mockLogsResult,
enable_advanced_querying: mockEnableAdvancedQuerying,
}); });
mock.onGet(endpoint).replyOnce(202); // mock reactive cache mock.onGet(endpoint).replyOnce(202); // mock reactive cache
...@@ -168,7 +165,6 @@ describe('Logs Store actions', () => { ...@@ -168,7 +165,6 @@ describe('Logs Store actions', () => {
[ [
{ type: types.REQUEST_PODS_DATA }, { type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA }, { type: types.REQUEST_LOGS_DATA },
{ type: types.ENABLE_ADVANCED_QUERYING, payload: mockEnableAdvancedQuerying },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }, { type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods }, { type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods },
{ type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult }, { type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult },
...@@ -191,11 +187,12 @@ describe('Logs Store actions', () => { ...@@ -191,11 +187,12 @@ describe('Logs Store actions', () => {
getTimeRange.mockReturnValueOnce(mockOneDay); getTimeRange.mockReturnValueOnce(mockOneDay);
state.projectPath = mockProjectPath; state.projectPath = mockProjectPath;
state.environments.options = mockEnvironments;
state.environments.current = mockEnvName; state.environments.current = mockEnvName;
state.pods.current = mockPodName; state.pods.current = mockPodName;
state.timeWindow.current = 'oneDay'; state.timeWindow.current = 'oneDay';
const endpoint = `/${mockProjectPath}/-/logs/k8s.json`; const endpoint = `/${mockProjectPath}/-/logs/elasticsearch.json`;
mock mock
.onGet(endpoint, { .onGet(endpoint, {
...@@ -204,7 +201,6 @@ describe('Logs Store actions', () => { ...@@ -204,7 +201,6 @@ describe('Logs Store actions', () => {
.reply(200, { .reply(200, {
pod_name: mockPodName, pod_name: mockPodName,
pods: mockPods, pods: mockPods,
enable_advanced_querying: true,
logs: mockLogsResult, logs: mockLogsResult,
}); });
...@@ -215,7 +211,6 @@ describe('Logs Store actions', () => { ...@@ -215,7 +211,6 @@ describe('Logs Store actions', () => {
[ [
{ type: types.REQUEST_PODS_DATA }, { type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA }, { type: types.REQUEST_LOGS_DATA },
{ type: types.ENABLE_ADVANCED_QUERYING, payload: true },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }, { type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods }, { type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods },
{ type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult }, { type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult },
...@@ -229,13 +224,12 @@ describe('Logs Store actions', () => { ...@@ -229,13 +224,12 @@ describe('Logs Store actions', () => {
}); });
it('should commit logs and pod data when there is pod name and search', done => { it('should commit logs and pod data when there is pod name and search', done => {
state.projectPath = mockProjectPath; state.environments.options = mockEnvironments;
state.environments.current = mockEnvName; state.environments.current = mockEnvName;
state.pods.current = mockPodName; state.pods.current = mockPodName;
state.advancedFeaturesEnabled = true;
state.search = mockSearch; state.search = mockSearch;
const endpoint = `/${mockProjectPath}/-/logs/k8s.json`; const endpoint = `/${mockProjectPath}/-/logs/elasticsearch.json`;
mock mock
.onGet(endpoint, { .onGet(endpoint, {
...@@ -250,7 +244,6 @@ describe('Logs Store actions', () => { ...@@ -250,7 +244,6 @@ describe('Logs Store actions', () => {
pod_name: mockPodName, pod_name: mockPodName,
pods: mockPods, pods: mockPods,
logs: mockLogsResult, logs: mockLogsResult,
enable_advanced_querying: mockEnableAdvancedQuerying,
}); });
mock.onGet(endpoint).replyOnce(202); // mock reactive cache mock.onGet(endpoint).replyOnce(202); // mock reactive cache
...@@ -262,7 +255,6 @@ describe('Logs Store actions', () => { ...@@ -262,7 +255,6 @@ describe('Logs Store actions', () => {
[ [
{ type: types.REQUEST_PODS_DATA }, { type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA }, { type: types.REQUEST_LOGS_DATA },
{ type: types.ENABLE_ADVANCED_QUERYING, payload: mockEnableAdvancedQuerying },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }, { type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods }, { type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods },
{ type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult }, { type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult },
...@@ -273,10 +265,10 @@ describe('Logs Store actions', () => { ...@@ -273,10 +265,10 @@ describe('Logs Store actions', () => {
}); });
it('should commit logs and pod data when no pod name defined', done => { it('should commit logs and pod data when no pod name defined', done => {
state.projectPath = mockProjectPath; state.environments.options = mockEnvironments;
state.environments.current = mockEnvName; state.environments.current = mockEnvName;
const endpoint = `/${mockProjectPath}/-/logs/k8s.json`; const endpoint = `/${mockProjectPath}/-/logs/elasticsearch.json`;
mock mock
.onGet(endpoint, { params: { environment_name: mockEnvName, ...mockThirtyMinutes } }) .onGet(endpoint, { params: { environment_name: mockEnvName, ...mockThirtyMinutes } })
...@@ -284,7 +276,6 @@ describe('Logs Store actions', () => { ...@@ -284,7 +276,6 @@ describe('Logs Store actions', () => {
pod_name: mockPodName, pod_name: mockPodName,
pods: mockPods, pods: mockPods,
logs: mockLogsResult, logs: mockLogsResult,
enable_advanced_querying: mockEnableAdvancedQuerying,
}); });
mock.onGet(endpoint).replyOnce(202); // mock reactive cache mock.onGet(endpoint).replyOnce(202); // mock reactive cache
...@@ -295,7 +286,6 @@ describe('Logs Store actions', () => { ...@@ -295,7 +286,6 @@ describe('Logs Store actions', () => {
[ [
{ type: types.REQUEST_PODS_DATA }, { type: types.REQUEST_PODS_DATA },
{ type: types.REQUEST_LOGS_DATA }, { type: types.REQUEST_LOGS_DATA },
{ type: types.ENABLE_ADVANCED_QUERYING, payload: mockEnableAdvancedQuerying },
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }, { type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
{ type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods }, { type: types.RECEIVE_PODS_DATA_SUCCESS, payload: mockPods },
{ type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult }, { type: types.RECEIVE_LOGS_DATA_SUCCESS, payload: mockLogsResult },
...@@ -306,10 +296,10 @@ describe('Logs Store actions', () => { ...@@ -306,10 +296,10 @@ describe('Logs Store actions', () => {
}); });
it('should commit logs and pod errors when backend fails', done => { it('should commit logs and pod errors when backend fails', done => {
state.projectPath = mockProjectPath; state.environments.options = mockEnvironments;
state.environments.current = mockEnvName; state.environments.current = mockEnvName;
const endpoint = `/${mockProjectPath}/logs.json?environment_name=${mockEnvName}`; const endpoint = `/${mockProjectPath}/-/logs/elasticsearch.json?environment_name=${mockEnvName}`;
mock.onGet(endpoint).replyOnce(500); mock.onGet(endpoint).replyOnce(500);
testAction( testAction(
......
...@@ -3,14 +3,12 @@ import * as types from 'ee/logs/stores/mutation_types'; ...@@ -3,14 +3,12 @@ import * as types from 'ee/logs/stores/mutation_types';
import logsPageState from 'ee/logs/stores/state'; import logsPageState from 'ee/logs/stores/state';
import { import {
mockProjectPath,
mockEnvName, mockEnvName,
mockEnvironments, mockEnvironments,
mockPods, mockPods,
mockPodName, mockPodName,
mockLogsResult, mockLogsResult,
mockSearch, mockSearch,
mockEnableAdvancedQuerying,
} from '../mock_data'; } from '../mock_data';
describe('Logs Store Mutations', () => { describe('Logs Store Mutations', () => {
...@@ -27,11 +25,6 @@ describe('Logs Store Mutations', () => { ...@@ -27,11 +25,6 @@ describe('Logs Store Mutations', () => {
}); });
describe('SET_PROJECT_ENVIRONMENT', () => { describe('SET_PROJECT_ENVIRONMENT', () => {
it('sets the project path', () => {
mutations[types.SET_PROJECT_PATH](state, mockProjectPath);
expect(state.projectPath).toEqual(mockProjectPath);
});
it('sets the environment', () => { it('sets the environment', () => {
mutations[types.SET_PROJECT_ENVIRONMENT](state, mockEnvName); mutations[types.SET_PROJECT_ENVIRONMENT](state, mockEnvName);
expect(state.environments.current).toEqual(mockEnvName); expect(state.environments.current).toEqual(mockEnvName);
...@@ -126,16 +119,6 @@ describe('Logs Store Mutations', () => { ...@@ -126,16 +119,6 @@ describe('Logs Store Mutations', () => {
}); });
}); });
describe('ENABLE_ADVANCED_QUERYING', () => {
it('set advanced querying toggle', () => {
state.enableAdvancedQuerying = !mockEnableAdvancedQuerying;
mutations[types.ENABLE_ADVANCED_QUERYING](state, mockEnableAdvancedQuerying);
expect(state.enableAdvancedQuerying).toEqual(mockEnableAdvancedQuerying);
});
});
describe('SET_TIME_WINDOW', () => { describe('SET_TIME_WINDOW', () => {
it('sets a time window Key', () => { it('sets a time window Key', () => {
const mockKey = 'fourHours'; const mockKey = 'fourHours';
......
...@@ -44,7 +44,6 @@ describe EnvironmentsHelper do ...@@ -44,7 +44,6 @@ describe EnvironmentsHelper do
it 'returns parameters for forming the pod logs API URL' do it 'returns parameters for forming the pod logs API URL' do
expect(subject).to include( expect(subject).to include(
"project-full-path": project.full_path,
"environment-id": environment.id "environment-id": environment.id
) )
end end
......
...@@ -141,7 +141,6 @@ describe Clusters::Platforms::Kubernetes do ...@@ -141,7 +141,6 @@ describe Clusters::Platforms::Kubernetes do
let(:pod_name) { 'pod-1' } let(:pod_name) { 'pod-1' }
let(:namespace) { 'app' } let(:namespace) { 'app' }
let(:container) { 'some-container' } let(:container) { 'some-container' }
let(:enable_advanced_querying) { false }
let(:expected_logs) do let(:expected_logs) do
[ [
{ message: "Log 1", timestamp: "2019-12-13T14:04:22.123456Z" }, { message: "Log 1", timestamp: "2019-12-13T14:04:22.123456Z" },
...@@ -158,7 +157,6 @@ describe Clusters::Platforms::Kubernetes do ...@@ -158,7 +157,6 @@ describe Clusters::Platforms::Kubernetes do
expect(subject[:status]).to eq(:success) expect(subject[:status]).to eq(:success)
expect(subject[:pod_name]).to eq(pod_name) expect(subject[:pod_name]).to eq(pod_name)
expect(subject[:container_name]).to eq(container) expect(subject[:container_name]).to eq(container)
expect(subject[:enable_advanced_querying]).to eq(enable_advanced_querying)
end end
end end
...@@ -177,7 +175,6 @@ describe Clusters::Platforms::Kubernetes do ...@@ -177,7 +175,6 @@ describe Clusters::Platforms::Kubernetes do
context 'when ElasticSearch is enabled' do context 'when ElasticSearch is enabled' do
let(:cluster) { create(:cluster, :project, platform_kubernetes: service) } let(:cluster) { create(:cluster, :project, platform_kubernetes: service) }
let!(:elastic_stack) { create(:clusters_applications_elastic_stack, cluster: cluster) } let!(:elastic_stack) { create(:clusters_applications_elastic_stack, cluster: cluster) }
let(:enable_advanced_querying) { true }
before do before do
expect_any_instance_of(::Clusters::Applications::ElasticStack).to receive(:elasticsearch_client).at_least(:once).and_return(Elasticsearch::Transport::Client.new) expect_any_instance_of(::Clusters::Applications::ElasticStack).to receive(:elasticsearch_client).at_least(:once).and_return(Elasticsearch::Transport::Client.new)
......
...@@ -14,7 +14,6 @@ describe PodLogsService do ...@@ -14,7 +14,6 @@ describe PodLogsService do
let(:pods) { [pod_name] } let(:pods) { [pod_name] }
let(:container_name) { 'container-1' } let(:container_name) { 'container-1' }
let(:search) { nil } let(:search) { nil }
let(:enable_advanced_querying) { false }
let(:logs) { ['Log 1', 'Log 2', 'Log 3'] } let(:logs) { ['Log 1', 'Log 2', 'Log 3'] }
let(:result) { subject.execute } let(:result) { subject.execute }
let(:start_time) { nil } let(:start_time) { nil }
...@@ -41,7 +40,6 @@ describe PodLogsService do ...@@ -41,7 +40,6 @@ describe PodLogsService do
expect(result[:pods]).to eq(pods) expect(result[:pods]).to eq(pods)
expect(result[:pod_name]).to eq(response_pod_name) expect(result[:pod_name]).to eq(response_pod_name)
expect(result[:container_name]).to eq(container_name) expect(result[:container_name]).to eq(container_name)
expect(result[:enable_advanced_querying]).to eq(enable_advanced_querying)
end end
end end
...@@ -67,8 +65,7 @@ describe PodLogsService do ...@@ -67,8 +65,7 @@ describe PodLogsService do
status: :error, status: :error,
error: message, error: message,
pod_name: response_pod_name, pod_name: response_pod_name,
container_name: container_name, container_name: container_name
enable_advanced_querying: enable_advanced_querying
}) })
end end
end end
...@@ -81,8 +78,7 @@ describe PodLogsService do ...@@ -81,8 +78,7 @@ describe PodLogsService do
status: :success, status: :success,
logs: ["Log 1", "Log 2", "Log 3"], logs: ["Log 1", "Log 2", "Log 3"],
pod_name: response_pod_name, pod_name: response_pod_name,
container_name: container_name, container_name: container_name
enable_advanced_querying: enable_advanced_querying
}) })
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