diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /app/assets/javascripts/clusters | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/assets/javascripts/clusters')
9 files changed, 342 insertions, 19 deletions
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index 1b11ec355bb..3699a3b8b2b 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -14,6 +14,7 @@ import { INGRESS_DOMAIN_SUFFIX, CROSSPLANE, KNATIVE, + FLUENTD, } from './constants'; import ClustersService from './services/clusters_service'; import ClustersStore from './stores/clusters_store'; @@ -49,6 +50,7 @@ export default class Clusters { installElasticStackPath, installCrossplanePath, installPrometheusPath, + installFluentdPath, managePrometheusPath, clusterEnvironmentsPath, hasRbac, @@ -102,6 +104,7 @@ export default class Clusters { updateKnativeEndpoint: updateKnativePath, installElasticStackEndpoint: installElasticStackPath, clusterEnvironmentsEndpoint: clusterEnvironmentsPath, + installFluentdEndpoint: installFluentdPath, }); this.installApplication = this.installApplication.bind(this); @@ -265,6 +268,7 @@ export default class Clusters { eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data)); eventHub.$on('setIngressModSecurityMode', data => this.setIngressModSecurityMode(data)); eventHub.$on('resetIngressModSecurityChanges', id => this.resetIngressModSecurityChanges(id)); + eventHub.$on('setFluentdSettings', data => this.setFluentdSettings(data)); // Add event listener to all the banner close buttons this.addBannerCloseHandler(this.unreachableContainer, 'unreachable'); this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure'); @@ -281,6 +285,7 @@ export default class Clusters { eventHub.$off('setIngressModSecurityEnabled'); eventHub.$off('setIngressModSecurityMode'); eventHub.$off('resetIngressModSecurityChanges'); + eventHub.$off('setFluentdSettings'); } initPolling(method, successCallback, errorCallback) { @@ -320,7 +325,7 @@ export default class Clusters { handleClusterStatusSuccess(data) { const prevStatus = this.store.state.status; - const prevApplicationMap = Object.assign({}, this.store.state.applications); + const prevApplicationMap = { ...this.store.state.applications }; this.store.updateStateFromServer(data.data); @@ -506,6 +511,12 @@ export default class Clusters { }); } + setFluentdSettings(settings = {}) { + Object.entries(settings).forEach(([key, value]) => { + this.store.updateAppProperty(FLUENTD, key, value); + }); + } + toggleIngressDomainHelpText({ externalIp }, { externalIp: newExternalIp }) { if (externalIp !== newExternalIp) { this.ingressDomainHelpText.classList.toggle('hide', !newExternalIp); diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 723030c5b8b..f11502a7dde 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -1,5 +1,5 @@ <script> -import { escape as esc } from 'lodash'; +import { escape } from 'lodash'; import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg'; import { GlLoadingIcon } from '@gitlab/ui'; import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png'; @@ -14,6 +14,7 @@ import knativeLogo from 'images/cluster_app_logos/knative.png'; import meltanoLogo from 'images/cluster_app_logos/meltano.png'; import prometheusLogo from 'images/cluster_app_logos/prometheus.png'; import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png'; +import fluentdLogo from 'images/cluster_app_logos/fluentd.png'; import { s__, sprintf } from '../../locale'; import applicationRow from './application_row.vue'; import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; @@ -22,6 +23,7 @@ import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../con import eventHub from '~/clusters/event_hub'; import CrossplaneProviderStack from './crossplane_provider_stack.vue'; import IngressModsecuritySettings from './ingress_modsecurity_settings.vue'; +import FluentdOutputSettings from './fluentd_output_settings.vue'; export default { components: { @@ -31,6 +33,7 @@ export default { KnativeDomainEditor, CrossplaneProviderStack, IngressModsecuritySettings, + FluentdOutputSettings, }, props: { type: { @@ -102,6 +105,7 @@ export default { meltanoLogo, prometheusLogo, elasticStackLogo, + fluentdLogo, }), computed: { isProjectCluster() { @@ -134,7 +138,7 @@ export default { }, ingressDescription() { return sprintf( - esc( + escape( s__( `ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}.`, ), @@ -142,14 +146,14 @@ export default { { pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb" target="_blank" rel="noopener noreferrer"> - ${esc(s__('ClusterIntegration|pricing'))}</a>`, + ${escape(s__('ClusterIntegration|pricing'))}</a>`, }, false, ); }, certManagerDescription() { return sprintf( - esc( + escape( s__( `ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates @@ -159,14 +163,14 @@ export default { { letsEncrypt: `<a href="https://letsencrypt.org/" target="_blank" rel="noopener noreferrer"> - ${esc(s__("ClusterIntegration|Let's Encrypt"))}</a>`, + ${escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`, }, false, ); }, crossplaneDescription() { return sprintf( - esc( + escape( s__( `ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{kubectl} or %{gitlabIntegrationLink}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`, @@ -175,7 +179,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity { gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane" target="_blank" rel="noopener noreferrer"> - ${esc(s__('ClusterIntegration|Gitlab Integration'))}</a>`, + ${escape(s__('ClusterIntegration|Gitlab Integration'))}</a>`, kubectl: `<code>kubectl</code>`, }, false, @@ -184,7 +188,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity prometheusDescription() { return sprintf( - esc( + escape( s__( `ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications.`, @@ -193,7 +197,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity { gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html" target="_blank" rel="noopener noreferrer"> - ${esc(s__('ClusterIntegration|GitLab Integration'))}</a>`, + ${escape(s__('ClusterIntegration|GitLab Integration'))}</a>`, }, false, ); @@ -219,11 +223,11 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity installedVia() { if (this.cloudRun) { return sprintf( - esc(s__(`ClusterIntegration|installed via %{installed_via}`)), + escape(s__(`ClusterIntegration|installed via %{installed_via}`)), { installed_via: `<a href="${ this.cloudRunHelpPath - }" target="_blank" rel="noopener noreferrer">${esc( + }" target="_blank" rel="noopener noreferrer">${escape( s__('ClusterIntegration|Cloud Run'), )}</a>`, }, @@ -658,7 +662,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity :uninstall-successful="applications.elastic_stack.uninstallSuccessful" :uninstall-failed="applications.elastic_stack.uninstallFailed" :disabled="!helmInstalled" - title-link="https://github.com/helm/charts/tree/master/stable/elastic-stack" + title-link="https://gitlab.com/gitlab-org/charts/elastic-stack" > <div slot="description"> <p> @@ -670,6 +674,51 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity </p> </div> </application-row> + + <application-row + id="fluentd" + :logo-url="fluentdLogo" + :title="applications.fluentd.title" + :status="applications.fluentd.status" + :status-reason="applications.fluentd.statusReason" + :request-status="applications.fluentd.requestStatus" + :request-reason="applications.fluentd.requestReason" + :installed="applications.fluentd.installed" + :install-failed="applications.fluentd.installFailed" + :install-application-request-params="{ + host: applications.fluentd.host, + port: applications.fluentd.port, + protocol: applications.fluentd.protocol, + waf_log_enabled: applications.fluentd.wafLogEnabled, + cilium_log_enabled: applications.fluentd.ciliumLogEnabled, + }" + :uninstallable="applications.fluentd.uninstallable" + :uninstall-successful="applications.fluentd.uninstallSuccessful" + :uninstall-failed="applications.fluentd.uninstallFailed" + :disabled="!helmInstalled" + :updateable="false" + title-link="https://github.com/helm/charts/tree/master/stable/fluentd" + > + <div slot="description"> + <p> + {{ + s__( + `ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed.`, + ) + }} + </p> + + <fluentd-output-settings + :port="applications.fluentd.port" + :protocol="applications.fluentd.protocol" + :host="applications.fluentd.host" + :waf-log-enabled="applications.fluentd.wafLogEnabled" + :cilium-log-enabled="applications.fluentd.ciliumLogEnabled" + :status="applications.fluentd.status" + :update-failed="applications.fluentd.updateFailed" + /> + </div> + </application-row> </div> </section> </template> diff --git a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue new file mode 100644 index 00000000000..1884b501a20 --- /dev/null +++ b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue @@ -0,0 +1,241 @@ +<script> +import { __ } from '~/locale'; +import { APPLICATION_STATUS, FLUENTD } from '~/clusters/constants'; +import { + GlAlert, + GlDeprecatedButton, + GlDropdown, + GlDropdownItem, + GlFormCheckbox, +} from '@gitlab/ui'; +import eventHub from '~/clusters/event_hub'; +import { mapValues } from 'lodash'; + +const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS; + +export default { + components: { + GlAlert, + GlDeprecatedButton, + GlDropdown, + GlDropdownItem, + GlFormCheckbox, + }, + props: { + protocols: { + type: Array, + required: false, + default: () => ['TCP', 'UDP'], + }, + status: { + type: String, + required: false, + default: '', + }, + updateFailed: { + type: Boolean, + required: false, + }, + protocol: { + type: String, + required: false, + default: () => __('Protocol'), + }, + port: { + type: Number, + required: false, + default: 514, + }, + host: { + type: String, + required: false, + default: '', + }, + wafLogEnabled: { + type: Boolean, + required: false, + }, + ciliumLogEnabled: { + type: Boolean, + required: false, + }, + }, + data: () => ({ + currentServerSideSettings: { + host: null, + port: null, + protocol: null, + wafLogEnabled: null, + ciliumLogEnabled: null, + }, + }), + computed: { + isSaving() { + return [UPDATING].includes(this.status); + }, + saveButtonDisabled() { + return [UNINSTALLING, UPDATING, INSTALLING].includes(this.status); + }, + saveButtonLabel() { + return this.isSaving ? __('Saving') : __('Save changes'); + }, + /** + * Returns true either when: + * - The application is getting updated. + * - The user has changed some of the settings for an application which is + * neither getting installed nor updated. + */ + showButtons() { + return this.isSaving || (this.changedByUser && [INSTALLED, UPDATED].includes(this.status)); + }, + protocolName() { + if (this.protocol) { + return this.protocol.toUpperCase(); + } + return __('Protocol'); + }, + changedByUser() { + return Object.entries(this.currentServerSideSettings).some(([key, value]) => { + return value !== null && value !== this[key]; + }); + }, + }, + watch: { + status() { + this.resetCurrentServerSideSettings(); + }, + }, + methods: { + updateApplication() { + eventHub.$emit('updateApplication', { + id: FLUENTD, + params: { + port: this.port, + protocol: this.protocol, + host: this.host, + waf_log_enabled: this.wafLogEnabled, + cilium_log_enabled: this.ciliumLogEnabled, + }, + }); + }, + resetCurrentServerSideSettings() { + this.currentServerSideSettings = mapValues(this.currentServerSideSettings, () => { + return null; + }); + }, + resetStatus() { + const newSettings = mapValues(this.currentServerSideSettings, (value, key) => { + return value === null ? this[key] : value; + }); + eventHub.$emit('setFluentdSettings', { + ...newSettings, + isEditingSettings: false, + }); + }, + updateCurrentServerSideSettings(settings) { + Object.keys(settings).forEach(key => { + if (this.currentServerSideSettings[key] === null) { + this.currentServerSideSettings[key] = this[key]; + } + }); + }, + setFluentdSettings(settings) { + this.updateCurrentServerSideSettings(settings); + eventHub.$emit('setFluentdSettings', { + ...settings, + isEditingSettings: true, + }); + }, + selectProtocol(protocol) { + this.setFluentdSettings({ protocol }); + }, + hostChanged(host) { + this.setFluentdSettings({ host }); + }, + portChanged(port) { + this.setFluentdSettings({ port: Number(port) }); + }, + wafLogChanged(wafLogEnabled) { + this.setFluentdSettings({ wafLogEnabled }); + }, + ciliumLogChanged(ciliumLogEnabled) { + this.setFluentdSettings({ ciliumLogEnabled }); + }, + }, +}; +</script> + +<template> + <div> + <gl-alert v-if="updateFailed" class="mb-3" variant="danger" :dismissible="false"> + {{ + s__( + 'ClusterIntegration|Something went wrong while trying to save your settings. Please try again.', + ) + }} + </gl-alert> + <div class="form-horizontal"> + <div class="form-group"> + <label for="fluentd-host"> + <strong>{{ s__('ClusterIntegration|SIEM Hostname') }}</strong> + </label> + <input + id="fluentd-host" + :value="host" + type="text" + class="form-control" + @input="hostChanged($event.target.value)" + /> + </div> + <div class="form-group"> + <label for="fluentd-port"> + <strong>{{ s__('ClusterIntegration|SIEM Port') }}</strong> + </label> + <input + id="fluentd-port" + :value="port" + type="number" + class="form-control" + @input="portChanged($event.target.value)" + /> + </div> + <div class="form-group"> + <label for="fluentd-protocol"> + <strong>{{ s__('ClusterIntegration|SIEM Protocol') }}</strong> + </label> + <gl-dropdown :text="protocolName" class="w-100"> + <gl-dropdown-item + v-for="(value, index) in protocols" + :key="index" + @click="selectProtocol(value.toLowerCase())" + > + {{ value }} + </gl-dropdown-item> + </gl-dropdown> + </div> + <div class="form-group flex flex-wrap"> + <gl-form-checkbox :checked="wafLogEnabled" @input="wafLogChanged"> + <strong>{{ s__('ClusterIntegration|Send ModSecurity Logs') }}</strong> + </gl-form-checkbox> + <gl-form-checkbox :checked="ciliumLogEnabled" @input="ciliumLogChanged"> + <strong>{{ s__('ClusterIntegration|Send Cilium Logs') }}</strong> + </gl-form-checkbox> + </div> + <div v-if="showButtons" class="mt-3"> + <gl-deprecated-button + ref="saveBtn" + class="mr-1" + variant="success" + :loading="isSaving" + :disabled="saveButtonDisabled" + @click="updateApplication" + > + {{ saveButtonLabel }} + </gl-deprecated-button> + <gl-deprecated-button ref="cancelBtn" :disabled="saveButtonDisabled" @click="resetStatus"> + {{ __('Cancel') }} + </gl-deprecated-button> + </div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue index 95eb427a49c..c2f963f0b34 100644 --- a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue +++ b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue @@ -1,5 +1,5 @@ <script> -import { escape as esc } from 'lodash'; +import { escape } from 'lodash'; import { s__, __ } from '../../locale'; import { APPLICATION_STATUS, INGRESS, LOGGING_MODE, BLOCKING_MODE } from '~/clusters/constants'; import { @@ -87,7 +87,7 @@ export default { ); }, ingressModSecurityDescription() { - return esc(this.ingressModSecurityHelpPath); + return escape(this.ingressModSecurityHelpPath); }, saving() { return [UPDATING].includes(this.ingress.status); diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue index b35adae3352..271f9f74838 100644 --- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue +++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue @@ -1,5 +1,5 @@ <script> -import { escape as esc } from 'lodash'; +import { escape } from 'lodash'; import SplitButton from '~/vue_shared/components/split_button.vue'; import { GlModal, GlDeprecatedButton, GlFormInput } from '@gitlab/ui'; import { s__, sprintf } from '~/locale'; @@ -82,7 +82,7 @@ export default { ) : s__('ClusterIntegration|To remove your integration, type %{clusterName} to confirm:'), { - clusterName: `<code>${esc(this.clusterName)}</code>`, + clusterName: `<code>${escape(this.clusterName)}</code>`, }, false, ); diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js index 6c3046fc56b..60e179c54eb 100644 --- a/app/assets/javascripts/clusters/constants.js +++ b/app/assets/javascripts/clusters/constants.js @@ -53,6 +53,7 @@ export const CERT_MANAGER = 'cert_manager'; export const CROSSPLANE = 'crossplane'; export const PROMETHEUS = 'prometheus'; export const ELASTIC_STACK = 'elastic_stack'; +export const FLUENTD = 'fluentd'; export const APPLICATIONS = [ HELM, @@ -63,6 +64,7 @@ export const APPLICATIONS = [ CERT_MANAGER, PROMETHEUS, ELASTIC_STACK, + FLUENTD, ]; export const INGRESS_DOMAIN_SUFFIX = '.nip.io'; diff --git a/app/assets/javascripts/clusters/event_hub.js b/app/assets/javascripts/clusters/event_hub.js index 0948c2e5352..e31806ad199 100644 --- a/app/assets/javascripts/clusters/event_hub.js +++ b/app/assets/javascripts/clusters/event_hub.js @@ -1,3 +1,3 @@ -import Vue from 'vue'; +import createEventHub from '~/helpers/event_hub_factory'; -export default new Vue(); +export default createEventHub(); diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js index 333fb293a15..2a6c6965dab 100644 --- a/app/assets/javascripts/clusters/services/clusters_service.js +++ b/app/assets/javascripts/clusters/services/clusters_service.js @@ -13,6 +13,7 @@ export default class ClusterService { jupyter: this.options.installJupyterEndpoint, knative: this.options.installKnativeEndpoint, elastic_stack: this.options.installElasticStackEndpoint, + fluentd: this.options.installFluentdEndpoint, }; this.appUpdateEndpointMap = { knative: this.options.updateKnativeEndpoint, diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index b09fd6800b6..9d354e66661 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -13,6 +13,7 @@ import { UPDATE_EVENT, UNINSTALL_EVENT, ELASTIC_STACK, + FLUENTD, } from '../constants'; import transitionApplicationState from '../services/application_state_machine'; @@ -103,6 +104,16 @@ export default class ClusterStore { ...applicationInitialState, title: s__('ClusterIntegration|Elastic Stack'), }, + fluentd: { + ...applicationInitialState, + title: s__('ClusterIntegration|Fluentd'), + host: null, + port: null, + protocol: null, + wafLogEnabled: null, + ciliumLogEnabled: null, + isEditingSettings: false, + }, }, environments: [], fetchingEnvironments: false, @@ -253,6 +264,14 @@ export default class ClusterStore { } else if (appId === ELASTIC_STACK) { this.state.applications.elastic_stack.version = version; this.state.applications.elastic_stack.updateAvailable = updateAvailable; + } else if (appId === FLUENTD) { + if (!this.state.applications.fluentd.isEditingSettings) { + this.state.applications.fluentd.port = serverAppEntry.port; + this.state.applications.fluentd.host = serverAppEntry.host; + this.state.applications.fluentd.protocol = serverAppEntry.protocol; + this.state.applications.fluentd.wafLogEnabled = serverAppEntry.waf_log_enabled; + this.state.applications.fluentd.ciliumLogEnabled = serverAppEntry.cilium_log_enabled; + } } }); } |