Commit 518cb413 authored by Adrien Kohlbecker's avatar Adrien Kohlbecker Committed by Natalia Tepluhina

Remove Elastic Stack cluster app feature flag

Enable the app by default
parent 6b832922
......@@ -129,9 +129,6 @@ export default {
crossplaneInstalled() {
return this.applications.crossplane.status === APPLICATION_STATUS.INSTALLED;
},
enableClusterApplicationElasticStack() {
return gon.features && gon.features.enableClusterApplicationElasticStack;
},
ingressModSecurityDescription() {
const escapedUrl = _.escape(this.ingressModSecurityHelpPath);
......@@ -655,7 +652,6 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
</div>
</application-row>
<application-row
v-if="enableClusterApplicationElasticStack"
id="elastic_stack"
:logo-url="elasticStackLogo"
:title="applications.elastic_stack.title"
......
......@@ -12,9 +12,6 @@ class Clusters::ClustersController < Clusters::BaseController
before_action :authorize_update_cluster!, only: [:update]
before_action :authorize_admin_cluster!, only: [:destroy, :clear_cache]
before_action :update_applications_status, only: [:cluster_status]
before_action only: [:show] do
push_frontend_feature_flag(:enable_cluster_application_elastic_stack)
end
helper_method :token_in_session
......
......@@ -58,7 +58,7 @@ module Clusters
end
def instantiate_application
raise_invalid_application_error if invalid_application?
raise_invalid_application_error if unknown_application?
builder || raise(InvalidApplicationError, "invalid application: #{application_name}")
end
......@@ -67,10 +67,6 @@ module Clusters
raise(InvalidApplicationError, "invalid application: #{application_name}")
end
def invalid_application?
unknown_application? || (application_name == Applications::ElasticStack.application_name && !Feature.enabled?(:enable_cluster_application_elastic_stack))
end
def unknown_application?
Clusters::Cluster::APPLICATIONS.keys.exclude?(application_name)
end
......
---
title: Add new Elastic Stack cluster application for pod log aggregation
merge_request: 23058
author:
type: added
......@@ -435,18 +435,7 @@ and you will have access to more advanced querying capabilities.
Log data is automatically deleted after 15 days using [Curator](https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/about.html).
This is a preliminary release of Elastic Stack as a GitLab-managed application. By default,
the ability to install it is disabled.
To allow installation of Elastic Stack as a GitLab-managed application, ask a GitLab
administrator to run following command within a Rails console:
```ruby
Feature.enable(:enable_cluster_application_elastic_stack)
```
Once the feature flag is set, to enable log shipping, install Elastic Stack into the cluster with the
**Install** button.
To enable log shipping, install Elastic Stack into the cluster with the **Install** button.
NOTE: **Note:**
The [`stable/elastic-stack`](https://github.com/helm/charts/tree/master/stable/elastic-stack)
......
......@@ -46,21 +46,20 @@ export default {
showLoader() {
return this.logs.isLoading || !this.logs.isComplete;
},
featureElasticEnabled() {
return gon.features && gon.features.enableClusterApplicationElasticStack;
},
advancedFeaturesEnabled() {
const environment = this.environments.options.find(
({ name }) => name === this.environments.current,
);
return this.featureElasticEnabled && environment && environment.enable_advanced_logs_querying;
return environment && environment.enable_advanced_logs_querying;
},
disableAdvancedControls() {
return this.environments.isLoading || !this.advancedFeaturesEnabled;
},
shouldShowElasticStackCallout() {
return (
!this.isElasticStackCalloutDismissed &&
!this.environments.isLoading &&
!this.logs.isLoading &&
!this.advancedFeaturesEnabled
!this.disableAdvancedControls
);
},
},
......@@ -119,8 +118,7 @@ export default {
:label="s__('Environments|Environment')"
label-size="sm"
label-for="environments-dropdown"
class="px-1"
:class="featureElasticEnabled ? 'col-3' : 'col-6'"
class="col-3 px-1"
>
<gl-dropdown
id="environments-dropdown"
......@@ -143,8 +141,7 @@ export default {
:label="s__('Environments|Pod logs from')"
label-size="sm"
label-for="pods-dropdown"
class="px-1"
:class="featureElasticEnabled ? 'col-3' : 'col-6'"
class="col-3 px-1"
>
<gl-dropdown
id="pods-dropdown"
......@@ -162,52 +159,47 @@ export default {
</gl-dropdown-item>
</gl-dropdown>
</gl-form-group>
<template v-if="featureElasticEnabled">
<gl-form-group
id="dates-fg"
:label="s__('Environments|Show last')"
label-size="sm"
label-for="time-window-dropdown"
class="col-3 px-1"
<gl-form-group
id="dates-fg"
:label="s__('Environments|Show last')"
label-size="sm"
label-for="time-window-dropdown"
class="col-3 px-1"
>
<gl-dropdown
id="time-window-dropdown"
ref="time-window-dropdown"
:disabled="disableAdvancedControls"
:text="timeWindow.options[timeWindow.current].label"
class="d-flex gl-h-32"
toggle-class="dropdown-menu-toggle"
>
<gl-dropdown
id="time-window-dropdown"
ref="time-window-dropdown"
:disabled="environments.isLoading || !advancedFeaturesEnabled"
:text="timeWindow.options[timeWindow.current].label"
class="d-flex gl-h-32"
toggle-class="dropdown-menu-toggle"
<gl-dropdown-item
v-for="(option, key) in timeWindow.options"
:key="key"
@click="setTimeWindow(key)"
>
<gl-dropdown-item
v-for="(option, key) in timeWindow.options"
:key="key"
@click="setTimeWindow(key)"
>
{{ option.label }}
</gl-dropdown-item>
</gl-dropdown>
</gl-form-group>
<gl-form-group
id="search-fg"
:label="s__('Environments|Search')"
label-size="sm"
label-for="search"
class="col-3 px-1"
>
<gl-search-box-by-click
v-model.trim="searchQuery"
:disabled="environments.isLoading || !advancedFeaturesEnabled"
:placeholder="s__('Environments|Search')"
class="js-logs-search"
type="search"
autofocus
@submit="
(environments.isLoading || !advancedFeaturesEnabled) && setSearch(searchQuery)
"
/>
</gl-form-group>
</template>
{{ option.label }}
</gl-dropdown-item>
</gl-dropdown>
</gl-form-group>
<gl-form-group
id="search-fg"
:label="s__('Environments|Search')"
label-size="sm"
label-for="search"
class="col-3 px-1"
>
<gl-search-box-by-click
v-model.trim="searchQuery"
:disabled="disableAdvancedControls"
:placeholder="s__('Environments|Search')"
class="js-logs-search"
type="search"
autofocus
@submit="disableAdvancedControls && setSearch(searchQuery)"
/>
</gl-form-group>
</div>
<log-control-buttons
......
......@@ -4,9 +4,6 @@ module Projects
class LogsController < Projects::ApplicationController
before_action :authorize_read_pod_logs!
before_action :environment
before_action do
push_frontend_feature_flag(:enable_cluster_application_elastic_stack)
end
def index
if environment.nil?
......
......@@ -92,7 +92,7 @@ module EE
end
def elastic_stack_available?
::Feature.enabled?(:enable_cluster_application_elastic_stack) && !!cluster.application_elastic_stack
!!cluster.application_elastic_stack
end
private
......
......@@ -114,15 +114,13 @@ describe('EnvironmentLogs', () => {
expect(findPodsDropdown().is(GlDropdown)).toBe(true);
expect(findLogControlButtons().exists()).toBe(true);
expect(findSearchBar().exists()).toBe(false); // behind ff
expect(findTimeWindowDropdown().exists()).toBe(false); // behind ff
expect(findSearchBar().exists()).toBe(true);
expect(findSearchBar().is(GlSearchBoxByClick)).toBe(true);
expect(findTimeWindowDropdown().exists()).toBe(true);
expect(findTimeWindowDropdown().is(GlDropdown)).toBe(true);
// log trace
expect(findLogTrace().isEmpty()).toBe(false);
// layout
expect(wrapper.find('#environments-dropdown-fg').attributes('class')).toMatch('col-6');
expect(wrapper.find('#pods-dropdown-fg').attributes('class')).toMatch('col-6');
});
it('mounted inits data', () => {
......@@ -156,15 +154,24 @@ describe('EnvironmentLogs', () => {
});
it('displays a disabled environments dropdown', () => {
expect(findEnvironmentsDropdown().attributes('disabled')).toEqual('true');
expect(findEnvironmentsDropdown().attributes('disabled')).toBe('true');
expect(findEnvironmentsDropdown().findAll(GlDropdownItem).length).toBe(0);
});
it('displays a disabled pods dropdown', () => {
expect(findPodsDropdown().attributes('disabled')).toEqual('true');
expect(findPodsDropdown().attributes('disabled')).toBe('true');
expect(findPodsDropdown().findAll(GlDropdownItem).length).toBe(0);
});
it('displays a disabled search bar', () => {
expect(findSearchBar().exists()).toBe(true);
expect(findSearchBar().attributes('disabled')).toBe('true');
});
it('displays a disabled time window dropdown', () => {
expect(findTimeWindowDropdown().attributes('disabled')).toBe('true');
});
it('does not update buttons state', () => {
expect(updateControlBtnsMock).not.toHaveBeenCalled();
});
......@@ -179,22 +186,7 @@ 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', () => {
describe('legacy environment', () => {
beforeEach(() => {
state.pods.options = [];
......@@ -209,15 +201,13 @@ describe('EnvironmentLogs', () => {
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');
it('displays a disabled search bar and time window dropdown', () => {
expect(findSearchBar().exists()).toBe(true);
expect(findSearchBar().attributes('disabled')).toBe('true');
expect(findTimeWindowDropdown().attributes('disabled')).toBe('true');
});
});
......@@ -227,9 +217,6 @@ describe('EnvironmentLogs', () => {
actionMocks.showPodLogs.mockImplementation(mockShowPodLogs);
actionMocks.fetchEnvironments.mockImplementation(mockFetchEnvs);
gon.features = gon.features || {};
gon.features.enableClusterApplicationElasticStack = true;
initWrapper();
});
......@@ -242,6 +229,14 @@ describe('EnvironmentLogs', () => {
actionMocks.fetchEnvironments.mockReset();
});
it('displays an enabled search bar', () => {
expect(findSearchBar().attributes('disabled')).toBeFalsy();
});
it('displays an enabled time window dropdown', () => {
expect(findTimeWindowDropdown().attributes('disabled')).toBeFalsy();
});
it('populates environments dropdown', () => {
const items = findEnvironmentsDropdown().findAll(GlDropdownItem);
expect(findEnvironmentsDropdown().props('text')).toBe(mockEnvName);
......@@ -312,103 +307,4 @@ describe('EnvironmentLogs', () => {
});
});
});
describe('when feature flag enable_cluster_application_elastic_stack is enabled', () => {
let originalGon;
beforeEach(() => {
originalGon = window.gon;
window.gon = { features: { enableClusterApplicationElasticStack: true } };
});
afterEach(() => {
window.gon = originalGon;
});
it('displays UI elements', () => {
initWrapper();
// elements
expect(findSearchBar().exists()).toBe(true);
expect(findSearchBar().is(GlSearchBoxByClick)).toBe(true);
expect(findTimeWindowDropdown().exists()).toBe(true);
expect(findTimeWindowDropdown().is(GlDropdown)).toBe(true);
// layout
expect(wrapper.find('#environments-dropdown-fg').attributes('class')).toMatch('col-3');
expect(wrapper.find('#pods-dropdown-fg').attributes('class')).toMatch('col-3');
expect(wrapper.find('#dates-fg').attributes('class')).toMatch('col-3');
expect(wrapper.find('#search-fg').attributes('class')).toMatch('col-3');
});
describe('loading state', () => {
beforeEach(() => {
state.pods.options = [];
state.logs = {
lines: [],
isLoading: true,
};
state.environments = {
options: [],
isLoading: true,
};
initWrapper();
});
it('displays a disabled search bar', () => {
expect(findSearchBar().exists()).toEqual(true);
expect(findSearchBar().attributes('disabled')).toEqual('true');
});
it('displays a disabled time window dropdown', () => {
expect(findTimeWindowDropdown().attributes('disabled')).toEqual('true');
});
});
describe('when advanced querying is disabled', () => {
beforeEach(() => {
state.pods.options = [];
state.logs = {
lines: [],
isLoading: false,
};
state.environments = {
options: [],
isLoading: false,
};
state.enableAdvancedQuerying = false;
initWrapper();
});
it('search bar and time window dropdown are disabled', () => {
expect(findSearchBar().attributes('disabled')).toEqual('true');
expect(findTimeWindowDropdown().attributes('disabled')).toEqual('true');
});
});
describe('state with data', () => {
beforeEach(() => {
actionMocks.setInitData.mockImplementation(mockSetInitData);
actionMocks.showPodLogs.mockImplementation(mockShowPodLogs);
actionMocks.fetchEnvironments.mockImplementation(mockFetchEnvs);
initWrapper();
});
it('displays an enabled search bar', () => {
expect(findSearchBar().attributes('disabled')).toBeFalsy();
});
it('displays an enabled time window dropdown', () => {
expect(findTimeWindowDropdown().attributes('disabled')).toBeFalsy();
});
});
});
});
......@@ -179,7 +179,6 @@ describe Clusters::Platforms::Kubernetes 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(::Gitlab::Elasticsearch::Logs).to receive(:pod_logs).and_return(expected_logs)
stub_feature_flags(enable_cluster_application_elastic_stack: true)
end
include_examples 'successful log request'
......
......@@ -14,9 +14,6 @@ describe('Applications', () => {
beforeEach(() => {
Applications = Vue.extend(applications);
gon.features = gon.features || {};
gon.features.enableClusterApplicationElasticStack = true;
});
afterEach(() => {
......
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