From 9269d175bdffd5628ba9fbb3253a52ac01306df7 Mon Sep 17 00:00:00 2001 From: Anna Vovchenko <avovchenko@gitlab.com> Date: Thu, 30 Nov 2023 10:11:34 +0000 Subject: [PATCH] Fix Kubernetes cluster health badge Currently, we only calculate cluster health once. With the addition of the watch_api, we need a way to update it when new data is received. Changelog: fixed --- .../components/kubernetes_overview.vue | 15 ++++++++++++--- .../components/kubernetes_pods.vue | 7 ++++--- .../components/kubernetes_status_bar.vue | 2 +- .../components/kubernetes_summary.vue | 4 +--- .../components/kubernetes_tabs.vue | 2 +- locale/gitlab.pot | 2 +- .../environments/kubernetes_overview_spec.js | 19 +++++++++++++++++-- .../environments/kubernetes_pods_spec.js | 10 ++++++++-- .../environments/kubernetes_summary_spec.js | 4 ++-- .../environments/kubernetes_tabs_spec.js | 7 ++++--- 10 files changed, 51 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/environments/components/kubernetes_overview.vue b/app/assets/javascripts/environments/components/kubernetes_overview.vue index 36cce29d6247f..d5a7b43c95319 100644 --- a/app/assets/javascripts/environments/components/kubernetes_overview.vue +++ b/app/assets/javascripts/environments/components/kubernetes_overview.vue @@ -43,7 +43,7 @@ export default { return { isVisible: false, error: '', - hasFailedState: false, + failedState: {}, podsLoading: false, workloadTypesLoading: false, }; @@ -78,6 +78,9 @@ export default { return this.hasFailedState ? 'error' : 'success'; }, + hasFailedState() { + return Object.values(this.failedState).some((item) => item); + }, }, methods: { toggleCollapse() { @@ -86,6 +89,12 @@ export default { onClusterError(message) { this.error = message; }, + onUpdateFailedState(event) { + this.failedState = { + ...this.failedState, + ...event, + }; + }, }, i18n: { collapse: __('Collapse'), @@ -126,14 +135,14 @@ export default { class="gl-mb-5" @cluster-error="onClusterError" @loading="podsLoading = $event" - @failed="hasFailedState = true" /> + @update-failed-state="onUpdateFailedState" /> <kubernetes-tabs :configuration="k8sAccessConfiguration" :namespace="namespace" class="gl-mb-5" @cluster-error="onClusterError" @loading="workloadTypesLoading = $event" - @failed="hasFailedState = true" + @update-failed-state="onUpdateFailedState" /></template> </gl-collapse> </div> diff --git a/app/assets/javascripts/environments/components/kubernetes_pods.vue b/app/assets/javascripts/environments/components/kubernetes_pods.vue index 743159d62563f..2015355f7940b 100644 --- a/app/assets/javascripts/environments/components/kubernetes_pods.vue +++ b/app/assets/javascripts/environments/components/kubernetes_pods.vue @@ -82,9 +82,10 @@ export default { methods: { countPodsByPhase(phase) { const filteredPods = this.k8sPods.filter((item) => item.status.phase === phase); - if (phase === PHASE_FAILED && filteredPods.length) { - this.$emit('failed'); - } + + const hasFailedState = Boolean(phase === PHASE_FAILED && filteredPods.length); + this.$emit('update-failed-state', { pods: hasFailedState }); + return filteredPods.length; }, }, diff --git a/app/assets/javascripts/environments/components/kubernetes_status_bar.vue b/app/assets/javascripts/environments/components/kubernetes_status_bar.vue index 8ecb61711ce28..20ed67f6bd9cf 100644 --- a/app/assets/javascripts/environments/components/kubernetes_status_bar.vue +++ b/app/assets/javascripts/environments/components/kubernetes_status_bar.vue @@ -153,7 +153,7 @@ export default { }, }, i18n: { - healthLabel: s__('Environment|Environment health'), + healthLabel: s__('Environment|Environment status'), syncStatusLabel: s__('Environment|Sync status'), }, badgeContainerClasses: 'gl-display-flex gl-align-items-center gl-flex-shrink-0 gl-mr-3 gl-mb-2', diff --git a/app/assets/javascripts/environments/components/kubernetes_summary.vue b/app/assets/javascripts/environments/components/kubernetes_summary.vue index 1f4e91afe3577..2912fd8f4d88f 100644 --- a/app/assets/javascripts/environments/components/kubernetes_summary.vue +++ b/app/assets/javascripts/environments/components/kubernetes_summary.vue @@ -140,9 +140,7 @@ export default { return workloadType.items?.failed?.length > 0; }); - if (failed) { - this.$emit('failed'); - } + this.$emit('update-failed-state', { summary: failed }); }, }, i18n: { diff --git a/app/assets/javascripts/environments/components/kubernetes_tabs.vue b/app/assets/javascripts/environments/components/kubernetes_tabs.vue index 60b36596ef3f6..0d80b1fd79712 100644 --- a/app/assets/javascripts/environments/components/kubernetes_tabs.vue +++ b/app/assets/javascripts/environments/components/kubernetes_tabs.vue @@ -140,7 +140,7 @@ export default { :namespace="namespace" :configuration="configuration" @loading="$emit('loading', $event)" - @failed="$emit('failed')" + @update-failed-state="$emit('update-failed-state', $event)" @cluster-error="$emit('cluster-error', $event)" /> diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 74170c6e5016c..453b983fddba2 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -18985,7 +18985,7 @@ msgstr "" msgid "Environment|Deployments" msgstr "" -msgid "Environment|Environment health" +msgid "Environment|Environment status" msgstr "" msgid "Environment|External IP" diff --git a/spec/frontend/environments/kubernetes_overview_spec.js b/spec/frontend/environments/kubernetes_overview_spec.js index 12689df586fe0..9f4a7518c473d 100644 --- a/spec/frontend/environments/kubernetes_overview_spec.js +++ b/spec/frontend/environments/kubernetes_overview_spec.js @@ -149,14 +149,14 @@ describe('~/environments/components/kubernetes_overview.vue', () => { }); it('sets `clusterHealthStatus` as error when pods emitted a failure', async () => { - findKubernetesPods().vm.$emit('failed'); + findKubernetesPods().vm.$emit('update-failed-state', { pods: true }); await nextTick(); expect(findKubernetesStatusBar().props('clusterHealthStatus')).toBe('error'); }); it('sets `clusterHealthStatus` as error when workload types emitted a failure', async () => { - findKubernetesTabs().vm.$emit('failed'); + findKubernetesTabs().vm.$emit('update-failed-state', { summary: true }); await nextTick(); expect(findKubernetesStatusBar().props('clusterHealthStatus')).toBe('error'); @@ -165,6 +165,21 @@ describe('~/environments/components/kubernetes_overview.vue', () => { it('sets `clusterHealthStatus` as success when data is loaded and no failures where emitted', () => { expect(findKubernetesStatusBar().props('clusterHealthStatus')).toBe('success'); }); + + it('sets `clusterHealthStatus` as success after state update if there are no failures', async () => { + findKubernetesTabs().vm.$emit('update-failed-state', { summary: true }); + findKubernetesTabs().vm.$emit('update-failed-state', { pods: true }); + await nextTick(); + expect(findKubernetesStatusBar().props('clusterHealthStatus')).toBe('error'); + + findKubernetesTabs().vm.$emit('update-failed-state', { summary: false }); + await nextTick(); + expect(findKubernetesStatusBar().props('clusterHealthStatus')).toBe('error'); + + findKubernetesTabs().vm.$emit('update-failed-state', { pods: false }); + await nextTick(); + expect(findKubernetesStatusBar().props('clusterHealthStatus')).toBe('success'); + }); }); describe('on cluster error', () => { diff --git a/spec/frontend/environments/kubernetes_pods_spec.js b/spec/frontend/environments/kubernetes_pods_spec.js index 2952e0c68c219..6c3e49e4d8a00 100644 --- a/spec/frontend/environments/kubernetes_pods_spec.js +++ b/spec/frontend/environments/kubernetes_pods_spec.js @@ -90,11 +90,17 @@ describe('~/environments/components/kubernetes_pods.vue', () => { ]); }); - it('emits a failed event when there are failed pods', async () => { + it('emits a update-failed-state event for each pod', async () => { createWrapper(); await waitForPromises(); - expect(wrapper.emitted('failed')).toHaveLength(1); + expect(wrapper.emitted('update-failed-state')).toHaveLength(4); + expect(wrapper.emitted('update-failed-state')).toEqual([ + [{ pods: false }], + [{ pods: false }], + [{ pods: false }], + [{ pods: true }], + ]); }); }); diff --git a/spec/frontend/environments/kubernetes_summary_spec.js b/spec/frontend/environments/kubernetes_summary_spec.js index efabd766001d8..0d448d0b6af0d 100644 --- a/spec/frontend/environments/kubernetes_summary_spec.js +++ b/spec/frontend/environments/kubernetes_summary_spec.js @@ -107,8 +107,8 @@ describe('~/environments/components/kubernetes_summary.vue', () => { ); }); - it('emits a failed event when there are failed workload types', () => { - expect(wrapper.emitted('failed')).toHaveLength(1); + it('emits a update-failed-state event when there are failed workload types', () => { + expect(wrapper.emitted('update-failed-state')).toEqual([[{ summary: true }]]); }); it('emits an error message when gets an error from the cluster_client API', async () => { diff --git a/spec/frontend/environments/kubernetes_tabs_spec.js b/spec/frontend/environments/kubernetes_tabs_spec.js index fecd6d2a8ee1a..bf029ad6a810c 100644 --- a/spec/frontend/environments/kubernetes_tabs_spec.js +++ b/spec/frontend/environments/kubernetes_tabs_spec.js @@ -179,9 +179,10 @@ describe('~/environments/components/kubernetes_tabs.vue', () => { expect(wrapper.emitted('loading')[1]).toEqual([false]); }); - it('emits a failed event when gets it from the component', () => { - findKubernetesSummary().vm.$emit('failed'); - expect(wrapper.emitted('failed')).toHaveLength(1); + it('emits a state update event when gets it from the component', () => { + const eventData = { summary: true }; + findKubernetesSummary().vm.$emit('update-failed-state', eventData); + expect(wrapper.emitted('update-failed-state')).toEqual([[eventData]]); }); }); }); -- GitLab