diff options
Diffstat (limited to 'app/assets/javascripts/clusters/components')
4 files changed, 306 insertions, 16 deletions
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, ); |