Repository: meshery/meshery
Pull request #14728: Prometheus components axios fetch migrated to rtk query 
Author: login: Pratik-050
Labels: name: component/ui
description: User Interface
Created: 2025-05-15T15:26:00Z | Merged: 2025-05-19T09:09:03Z

**Notes for Reviewers**

- This PR migrates the pending data-fetch components in meshery to rtk
- Pending components
https://docs.google.com/spreadsheets/d/1RlUcr-iLtCFCsV1VZvWD0jBijPJAx-Rk-1GLLsL9sSI/edit?pli=1&gid=0#gid=0

**[Signed commits](https://github.com/meshery/meshery/blob/master/CONTRIBUTING.md#signing-off-on-commits-developer-certificate-of-origin)**
- [x] Yes, I signed my commits.




Diff:
diff --git a/ui/components/telemetry/prometheus/PrometheusComponent.js b/ui/components/telemetry/prometheus/PrometheusComponent.js
index 021f4fc70de6..fe1d986e0e61 100644
--- a/ui/components/telemetry/prometheus/PrometheusComponent.js
+++ b/ui/components/telemetry/prometheus/PrometheusComponent.js
@@ -2,7 +2,11 @@ import React, { useState, useEffect } from 'react';
 import PropTypes from 'prop-types';
 import { NoSsr } from '@layer5/sistent';
 import { Typography, styled, Box } from '@layer5/sistent';
-import dataFetch from '../../../lib/data-fetch';
+import {
+  useConfigureConnectionMutation,
+  useUpdateConnectionMutation,
+} from '@/rtk-query/connection';
+import { useGetPrometheusConfigQuery } from '@/rtk-query/telemetry';
 import PrometheusSelectionComponent from './PrometheusSelectionComponent';
 import GrafanaDisplaySelection from '../grafana/GrafanaDisplaySelection';
 import GrafanaCustomCharts from '../grafana/GrafanaCustomCharts';
@@ -71,35 +75,32 @@ const PrometheusComponent = (props) => {
     return getK8sClusterIdsFromCtxId(selectedK8sContexts, k8sConfig);
   };
 
-  const submitPrometheusConfigure = (url) => {
-    const params = new URLSearchParams({ prometheusURL: url });
+  const [configurePrometheus] = useConfigureConnectionMutation();
+
+  const submitPrometheusConfigure = async (url) => {
     updateProgress({ showProgress: true });
-    dataFetch(
-      `/api/telemetry/metrics/config`,
-      {
-        method: 'POST',
-        credentials: 'include',
-        headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
-        body: params,
-      },
-      (result) => {
-        updateProgress({ showProgress: false });
-        if (result) {
-          props.notify({
-            message: 'Prometheus was configured!',
-            event_type: EVENT_TYPES.SUCCESS,
-          });
-          setPrometheusConfigSuccess(true);
-          dispatch(
-            updatePrometheusConfig({
-              prometheusURL: url,
-              selectedPrometheusBoardsConfigs: [],
-            }),
-          );
-        }
-      },
-      handleError,
-    );
+    try {
+      await configurePrometheus({
+        connectionKind: CONNECTION_KINDS.PROMETHEUS,
+        body: { prometheusURL: url },
+      }).unwrap();
+
+      props.notify({
+        message: 'Prometheus was configured!',
+        event_type: EVENT_TYPES.SUCCESS,
+      });
+      setPrometheusConfigSuccess(true);
+      dispatch(
+        updatePrometheusConfig({
+          prometheusURL: url,
+          selectedPrometheusBoardsConfigs: [],
+        }),
+      );
+    } catch (err) {
+      handleError(err?.data?.error || 'Error communicating with Prometheus');
+    } finally {
+      updateProgress({ showProgress: false });
+    }
   };
 
   const isValidGrafanaURL = (url) =>
@@ -115,6 +116,9 @@ const PrometheusComponent = (props) => {
       }
 
       setPrometheusURL(newURL);
+      setConnectionID(data?.id);
+      setConnectionName(data?.name);
+
       dispatch(
         updatePrometheusConfig({
           prometheusURL: newURL,
@@ -139,36 +143,37 @@ const PrometheusComponent = (props) => {
     props.notify({ message, event_type: EVENT_TYPES.ERROR });
   };
 
-  const handlePrometheusChipDelete = (e) => {
+  const [updateConnection] = useUpdateConnectionMutation();
+
+  const handlePrometheusChipDelete = async (e) => {
     e.preventDefault();
     if (!connectionID) return;
 
     updateProgress({ showProgress: true });
-    dataFetch(
-      `/api/integrations/connections/${CONNECTION_KINDS.PROMETHEUS}/status`,
-      {
-        method: 'PUT',
-        credentials: 'include',
-        body: JSON.stringify({ [connectionID]: CONNECTION_STATES.DISCOVERED }),
-      },
-      () => {
-        updateProgress({ showProgress: false });
-        setPrometheusConfigSuccess(false);
-        setPrometheusURL('');
-        setSelectedPrometheusBoardsConfigs([]);
-        dispatch(
-          updatePrometheusConfig({
-            prometheusURL: '',
-            selectedPrometheusBoardsConfigs: [],
-          }),
-        );
-        props.notify({
-          message: `Connection "${connectionID}" transitioned to discovered state`,
-          event_type: EVENT_TYPES.SUCCESS,
-        });
-      },
-      (err) => handleError(err.message),
-    );
+    try {
+      await updateConnection({
+        connectionKind: CONNECTION_KINDS.PROMETHEUS,
+        connectionPayload: { [connectionID]: CONNECTION_STATES.DISCOVERED },
+      }).unwrap();
+
+      setPrometheusConfigSuccess(false);
+      setPrometheusURL('');
+      setSelectedPrometheusBoardsConfigs([]);
+      dispatch(
+        updatePrometheusConfig({
+          prometheusURL: '',
+          selectedPrometheusBoardsConfigs: [],
+        }),
+      );
+      props.notify({
+        message: `Connection "${connectionID}" transitioned to discovered state`,
+        event_type: EVENT_TYPES.SUCCESS,
+      });
+    } catch (err) {
+      handleError(err?.data?.error || 'Failed to update Prometheus connection');
+    } finally {
+      updateProgress({ showProgress: false });
+    }
   };
 
   const handlePrometheusClick = () => {
@@ -200,50 +205,50 @@ const PrometheusComponent = (props) => {
     );
   };
 
+  const { data: prometheusConfig, isSuccess: isPrometheusConfigLoaded } =
+    useGetPrometheusConfigQuery(undefined, { skip: !props.isMeshConfigured });
+
   useEffect(() => {
-    if (initialPrometheus.prometheusURL !== prometheusURL) {
-      setPrometheusConfigSuccess(initialPrometheus.prometheusURL !== '');
-      setPrometheusURL(initialPrometheus.prometheusURL);
-      setSelectedPrometheusBoardsConfigs(initialPrometheus.selectedPrometheusBoardsConfigs || []);
-      setConnectionID(initialPrometheus.connectionID);
-      setConnectionName(initialPrometheus.connectionName);
+    if (!isPrometheusConfigLoaded) return;
+
+    updateProgress({ showProgress: false });
+
+    if (prometheusConfig?.prometheusURL) {
+      setPrometheusURL(prometheusConfig.prometheusURL);
+      setPrometheusConfigSuccess(true);
+      setSelectedPrometheusBoardsConfigs(prometheusConfig.selectedPrometheusBoardsConfigs || []);
     }
-  }, [initialPrometheus]);
 
-  useEffect(() => {
-    if (!props.isMeshConfigured) return;
+    const selector = {
+      type: 'ALL_MESH',
+      k8sClusterIDs: getK8sClusterIds(),
+    };
 
-    dataFetch(
-      `/api/telemetry/metrics/config`,
-      {
-        method: 'GET',
-        credentials: 'include',
-        headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
-      },
-      (result) => {
-        updateProgress({ showProgress: false });
-        if (result?.prometheusURL) {
-          const selector = {
-            type: 'ALL_MESH',
-            k8sClusterIDs: getK8sClusterIds(),
-          };
-          fetchAvailableAddons(selector).subscribe({
-            next: (res) => {
-              res?.addonsState?.forEach((addon) => {
-                if (addon.name === 'prometheus' && prometheusURL === '') {
-                  const newURL = `http://${addon.endpoint}`;
-                  setPrometheusURL(newURL);
-                  submitPrometheusConfigure(newURL);
-                }
-              });
-            },
-            error: (err) => console.error('Error registering Prometheus:', err),
-          });
-        }
+    fetchAvailableAddons(selector).subscribe({
+      next: (res) => {
+        res?.addonsState?.forEach((addon) => {
+          if (
+            addon.name === 'prometheus' &&
+            prometheusURL === '' &&
+            prometheusConfig?.prometheusURL === ''
+          ) {
+            const newURL = `http://${addon.endpoint}`;
+            setPrometheusURL(newURL);
+            submitPrometheusConfigure(newURL);
+          }
+        });
       },
-      handleError,
-    );
-  }, []);
+      error: (err) => console.error('Error registering Prometheus:', err),
+    });
+  }, [
+    isPrometheusConfigLoaded,
+    prometheusConfig,
+    props.isMeshConfigured,
+    prometheusURL,
+    submitPrometheusConfigure,
+    selectedK8sContexts,
+    k8sConfig,
+  ]);
 
   if (prometheusConfigSuccess) {
     const displaySelec = selectedPrometheusBoardsConfigs.length > 0 && (
diff --git a/ui/components/telemetry/prometheus/PrometheusConfigComponent.js b/ui/components/telemetry/prometheus/PrometheusConfigComponent.js
index c44c24417895..8607b50f0e52 100644
--- a/ui/components/telemetry/prometheus/PrometheusConfigComponent.js
+++ b/ui/components/telemetry/prometheus/PrometheusConfigComponent.js
@@ -1,13 +1,12 @@
-import React, { useState } from 'react';
+import React from 'react';
 import PropTypes from 'prop-types';
 import { NoSsr } from '@layer5/sistent';
 import { Grid, Button, styled } from '@layer5/sistent';
 import ReactSelectWrapper from '../../ReactSelectWrapper';
 import CAN from '@/utils/can';
 import { keys } from '@/utils/permission_constants';
-import { useEffect } from 'react';
 import { CONNECTION_KINDS, CONNECTION_STATES } from '@/utils/Enum';
-import dataFetch from 'lib/data-fetch';
+import { useGetConnectionsQuery } from '@/rtk-query/connection';
 
 const StyledRoot = styled('div')(({ theme }) => ({
   padding: theme.spacing(5),
@@ -27,22 +26,14 @@ const ButtonContainer = styled('div')(({ theme }) => ({
 
 // change this to display all connected prometheuses connecion and based on the selection updat tht erduc prom object
 const PrometheusConfigComponent = ({ urlError, handleChange, handlePrometheusConfigure }) => {
-  const [availablePrometheusConnection, setAvailablePrometheusConnection] = useState([]);
+  const { data } = useGetConnectionsQuery({
+    page: 0,
+    pagesize: 1,
+    status: JSON.stringify([CONNECTION_STATES.CONNECTED]),
+    kind: JSON.stringify([CONNECTION_KINDS.PROMETHEUS]),
+  });
 
-  useEffect(() => {
-    dataFetch(
-      `/api/integrations/connections?page=0&pagesize=1&status=${encodeURIComponent(
-        JSON.stringify([CONNECTION_STATES.CONNECTED]),
-      )}&kind=${encodeURIComponent(JSON.stringify([CONNECTION_KINDS.PROMETHEUS]))}`,
-      {
-        credentials: 'include',
-        method: 'GET',
-      },
-      (result) => {
-        setAvailablePrometheusConnection(result?.connections);
-      },
-    );
-  }, []);
+  const availablePrometheusConnection = data?.connections || [];
 
   return (
     <NoSsr>
diff --git a/ui/components/telemetry/prometheus/PrometheusSelectionComponent.js b/ui/components/telemetry/prometheus/PrometheusSelectionComponent.js
index 0499aa133da5..abf63620c74a 100644
--- a/ui/components/telemetry/prometheus/PrometheusSelectionComponent.js
+++ b/ui/components/telemetry/prometheus/PrometheusSelectionComponent.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import { TextField, Grid, Button, Chip, MenuItem, styled, NoSsr, Alert } from '@layer5/sistent';
 import { Controlled as CodeMirror } from 'react-codemirror2';
 import { trueRandom } from '../../../lib/trueRandom';
-import dataFetch from '../../../lib/data-fetch';
+import { usePostBoardImportMutation, useLazyQueryTemplateVarsQuery } from '@/rtk-query/telemetry';
 import CodeIcon from '@mui/icons-material/Code';
 import { updateProgress } from '@/store/slices/mesheryUi';
 
@@ -122,104 +122,97 @@ const PrometheusSelectionComponent = (props) => {
     });
   };
 
-  const boardChange = (newVal) => {
-    updateProgress({ showProgress: true });
+  const [postBoardImport] = usePostBoardImportMutation();
+  const [triggerTemplateQuery] = useLazyQueryTemplateVarsQuery();
 
-    dataFetch(
-      `/api/telemetry/metrics/board_import/${connectionID}`,
-      {
-        method: 'POST',
-        credentials: 'include',
-        headers: { 'Content-Type': 'application/json' },
+  const boardChange = async (newVal) => {
+    updateProgress({ showProgress: true });
+    try {
+      const result = await postBoardImport({
+        connectionID,
         body: newVal,
-      },
-      (result) => {
-        updateProgress({ showProgress: false });
-        const filteredPanels =
-          result.panels?.filter((panel) =>
-            panel.targets?.some((t) => t.datasource?.type?.toLowerCase() === 'prometheus'),
-          ) || [];
-
-        if (filteredPanels.length === 0) {
-          return handleError('No panels found with target datasource as prometheus.');
-        }
+      }).unwrap();
 
-        setGrafanaBoardObject(result);
-        setPanels(filteredPanels);
-        setSelectedPanels(filteredPanels.map((p) => p.id));
-        setTemplateVars(result.template_vars || []);
-        setTemplateVarOptions([]);
-        setSelectedTemplateVars([]);
+      const filteredPanels =
+        result.panels?.filter((panel) =>
+          panel.targets?.some((t) => t.datasource?.type?.toLowerCase() === 'prometheus'),
+        ) || [];
 
-        if (result.template_vars?.length > 0) {
-          queryTemplateVars(0, result.template_vars, [], []);
-        }
-      },
-      handleError,
-    );
+      if (filteredPanels.length === 0) {
+        return handleError('No panels found with target datasource as prometheus.');
+      }
+
+      setGrafanaBoardObject(result);
+      setPanels(filteredPanels);
+      setSelectedPanels(filteredPanels.map((p) => p.id));
+      setTemplateVars(result.template_vars || []);
+      setTemplateVarOptions([]);
+      setSelectedTemplateVars([]);
+
+      if (result.template_vars?.length > 0) {
+        queryTemplateVars(0, result.template_vars, [], []);
+      }
+    } catch (error) {
+      handleError(error);
+    } finally {
+      updateProgress({ showProgress: false });
+    }
   };
 
-  const queryTemplateVars = (ind, vars, options, selectedVars) => {
+  const queryTemplateVars = async (ind, vars, options, selectedVars) => {
     if (!vars?.[ind]) return;
 
-    let queryURL = `/api/telemetry/metrics/query/${connectionID}?query=${encodeURIComponent(vars[ind].query)}`;
+    let queryStr = `query=${encodeURIComponent(vars[ind].query)}`;
     for (let i = ind; i > 0; i--) {
-      queryURL += `&${vars[i - 1].name}=${selectedVars[i - 1]}`;
+      queryStr += `&${vars[i - 1].name}=${selectedVars[i - 1]}`;
     }
 
     if (vars[ind].query.startsWith('label_values') && vars[ind].query.includes(',')) {
-      // series query needs a start and end time or else it will take way longer to return. . .
-      // but at this point this component does not have the time range selection bcoz the time range selection comes after this component makes its selections
-      // hence for now just limiting the time period to the last 24hrs
       const ed = new Date();
       const sd = new Date();
       sd.setDate(sd.getDate() - 1);
-      queryURL += `&start=${Math.floor(sd.getTime() / 1000)}&end=${Math.floor(ed.getTime() / 1000)}`; // accounts for the last 24hrs
+      queryStr += `&start=${Math.floor(sd.getTime() / 1000)}&end=${Math.floor(ed.getTime() / 1000)}`;
     }
 
     updateProgress({ showProgress: true });
-
-    dataFetch(
-      queryURL,
-      { credentials: 'include' },
-      (result) => {
-        updateProgress({ showProgress: false });
-        let tmpVarOpts = [];
-
-        if (Array.isArray(result?.data)) {
-          if (
-            vars[ind].query.startsWith('label_values') &&
-            vars[ind].query.includes(',') &&
-            typeof result.data[0] === 'object'
-          ) {
-            const q = vars[ind].query.replace('label_values(', '').slice(0, -1);
-            const qInd = q.split(',').pop().trim();
-            result.data.forEach((d) => {
-              const v = d[qInd];
-              if (v && !tmpVarOpts.includes(v)) tmpVarOpts.push(v);
-            });
-          } else {
-            tmpVarOpts = result.data;
-          }
-        } else if (result?.data?.result) {
-          tmpVarOpts = result.data.result.map(({ metric }) => Object.values(metric)?.[0]);
+    try {
+      const result = await triggerTemplateQuery({ connectionID, query: queryStr }).unwrap();
+      let tmpVarOpts = [];
+
+      if (Array.isArray(result?.data)) {
+        if (
+          vars[ind].query.startsWith('label_values') &&
+          vars[ind].query.includes(',') &&
+          typeof result.data[0] === 'object'
+        ) {
+          const q = vars[ind].query.replace('label_values(', '').slice(0, -1);
+          const qInd = q.split(',').pop().trim();
+          result.data.forEach((d) => {
+            const v = d[qInd];
+            if (v && !tmpVarOpts.includes(v)) tmpVarOpts.push(v);
+          });
+        } else {
+          tmpVarOpts = result.data;
         }
+      } else if (result?.data?.result) {
+        tmpVarOpts = result.data.result.map(({ metric }) => Object.values(metric)?.[0]);
+      }
 
-        setTemplateVarOptions((prev) => {
-          const newOptions = [...prev];
-          newOptions[ind] = tmpVarOpts;
-          return newOptions;
-        });
-      },
-      (error) => {
-        setTemplateVarOptions((prev) => {
-          const newOptions = [...prev];
-          newOptions[ind] = [vars[ind].Value];
-          return newOptions;
-        });
-        handleError(error);
-      },
-    );
+      setTemplateVarOptions((prev) => {
+        const newOptions = [...prev];
+        newOptions[ind] = tmpVarOpts;
+        return newOptions;
+      });
+    } catch (error) {
+      setTemplateVarOptions((prev) => {
+        const newOptions = [...prev];
+        newOptions[ind] = [vars[ind].Value];
+        return newOptions;
+      });
+      handleError(error);
+    } finally {
+      updateProgress({ showProgress: false });
+    }
   };
 
   const handleTemplateVarChange = (ind) => (e) => {
diff --git a/ui/rtk-query/connection.js b/ui/rtk-query/connection.js
index acf5caf65bec..8481ee8f2553 100644
--- a/ui/rtk-query/connection.js
+++ b/ui/rtk-query/connection.js
@@ -130,6 +130,7 @@ export const {
   useVerifyAndRegisterConnectionMutation,
   useConnectToConnectionMutation,
   useGetConnectionsQuery,
+  useLazyGetConnectionsQuery,
   useGetConnectionStatusQuery,
   useLazyGetConnectionDetailsQuery,
   useVerifyConnectionURLMutation,
diff --git a/ui/rtk-query/telemetry.js b/ui/rtk-query/telemetry.js
index 57d1f76ecaeb..f812f3c508d4 100644
--- a/ui/rtk-query/telemetry.js
+++ b/ui/rtk-query/telemetry.js
@@ -54,6 +54,29 @@ const telemetryApi = api.injectEndpoints({
       }),
       invalidatesTags: () => [{ type: TAGS.GRAFANA }],
     }),
+    getPrometheusConfig: builder.query({
+      query: () => ({
+        url: 'telemetry/metrics/config',
+        method: 'GET',
+        credentials: 'include',
+      }),
+    }),
+    postBoardImport: builder.mutation({
+      query: ({ connectionID, body }) => ({
+        url: `/telemetry/metrics/board_import/${connectionID}`,
+        method: 'POST',
+        body,
+        credentials: 'include',
+        headers: { 'Content-Type': 'application/json' },
+      }),
+    }),
+    queryTemplateVars: builder.query({
+      query: ({ connectionID, query }) => ({
+        url: `/telemetry/metrics/query/${connectionID}?${query}`,
+        method: 'GET',
+        credentials: 'include',
+      }),
+    }),
   }),
 });
 
@@ -64,4 +87,7 @@ export const {
   useGetStaticPrometheusBoardConfigQuery,
   useUpdateGrafanaBoardsMutation,
   useConfigureGrafanaMutation,
+  useGetPrometheusConfigQuery,
+  usePostBoardImportMutation,
+  useLazyQueryTemplateVarsQuery,
 } = telemetryApi;


Reviews:
user: login: gemini-code-assist[bot]
body: Hello @Pratik-050, I'm Gemini Code Assist[^1]! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

## Summary of Changes
As Gemini, I've reviewed this pull request. The primary goal of this PR is to continue the migration of data fetching logic within the Meshery UI from the custom `dataFetch` utility to RTK Query. Specifically, this PR focuses on the components related to Prometheus telemetry, replacing the existing `axios`-based calls with dedicated RTK Query hooks for fetching configuration, configuring connections, updating connection status, importing Grafana boards, and querying template variables.

### Highlights
* **RTK Query Migration**: Migrated data fetching logic in Prometheus-related components (`PrometheusComponent`, `PrometheusConfigComponent`, `PrometheusSelectionComponent`) from a custom `dataFetch` utility to RTK Query hooks.
* **New RTK Query Endpoints**: Added new endpoints to the `connectionsApi` RTK Query slice to handle Prometheus configuration (GET), board import (POST), and template variable queries (GET).
* **Component Refactoring**: Updated component logic to utilize the state management and request handling provided by RTK Query hooks, including handling loading states, success responses, and errors more consistently.

### Changelog
<details>
<summary>Click here to see the changelog</summary>

* **ui/components/telemetry/prometheus/PrometheusComponent.js**
  * Removed `dataFetch` import (line 5).
  * Imported `useConfigureConnectionMutation`, `useUpdateConnectionMutation`, and `useGetPrometheusConfigQuery` from `@/rtk-query/connection` (lines 5-9).
  * Replaced `dataFetch` call for `submitPrometheusConfigure` with `useConfigureConnectionMutation` (lines 78-103).
  * Replaced `dataFetch` call for `handlePrometheusChipDelete` with `useUpdateConnectionMutation` (lines 143-173).
  * Replaced `dataFetch` call for fetching initial Prometheus config in `useEffect` with `useGetPrometheusConfigQuery` (lines 205-240).
  * Adjusted `useEffect` logic to react to `isPrometheusConfigLoaded` and `prometheusConfig` from the RTK Query hook (lines 208-240).
* **ui/components/telemetry/prometheus/PrometheusConfigComponent.js**
  * Removed `useState` for `availablePrometheusConnection` (line 1).
  * Removed `dataFetch` import (line 10).
  * Imported `useLazyGetConnectionsQuery` from `@/rtk-query/connection` (line 9).
  * Replaced `dataFetch` call in `useEffect` with `useLazyGetConnectionsQuery` trigger (lines 31-38).
  * Accessed connection data from the RTK Query hook result (`data?.connections`) (line 40).
* **ui/components/telemetry/prometheus/PrometheusSelectionComponent.js**
  * Removed `dataFetch` import (line 6).
  * Imported `usePostBoardImportMutation` and `useLazyQueryTemplateVarsQuery` from `@/rtk-query/connection` (line 6).
  * Replaced `dataFetch` call for `boardChange` with `usePostBoardImportMutation` (lines 125-160).
  * Replaced `dataFetch` call for `queryTemplateVars` with `useLazyQueryTemplateVarsQuery` trigger (lines 162-216).
* **ui/rtk-query/connection.js**
  * Added `getPrometheusConfig` query endpoint (lines 125-131).
  * Added `postBoardImport` mutation endpoint (lines 132-140).
  * Added `queryTemplateVars` query endpoint (lines 141-147).
  * Exported `useLazyGetConnectionsQuery` hook (line 156).
  * Exported `useGetPrometheusConfigQuery`, `usePostBoardImportMutation`, and `useLazyQueryTemplateVarsQuery` hooks (lines 167-169).

</details>


<details>

<summary><b>Using Gemini Code Assist</b></summary>
<br>

The full guide for Gemini Code Assist can be found on our [documentation page](https://developers.google.com/gemini-code-assist/docs/review-github-code), here are some quick tips.

<b>Invoking Gemini</b>

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either `/gemini <command>` or `@gemini-code-assist <command>`. Below is a summary of the supported commands.

Feature | Command | Description
--- | --- | ---
Code Review | `/gemini review` | Performs a code review for the current pull request in its current state.
Pull Request Summary | `/gemini summary` | Provides a summary of the current pull request in its current state.
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments.
Help | `/gemini help` | Displays a list of available commands.

<b>Customization</b>

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a `.gemini/` folder in the base of the repository. Detailed instructions can be found [here](https://developers.google.com/gemini-code-assist/docs/customize-gemini-behavior-github).

<b>Limitations & Feedback</b>

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with :thumbsup: and :thumbsdown: on @gemini-code-assist comments to provide feedback.

</details>

<b>You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the [Gemini Code Assist IDE Extension](https://cloud.google.com/products/gemini/code-assist).</b>


[^1]: Review the [Privacy Notices](https://policies.google.com/privacy), [Generative AI Prohibited Use Policy](https://policies.google.com/terms/generative-ai/use-policy), [Terms of Service](https://policies.google.com/terms), and learn how to configure Gemini Code Assist in GitHub [here](https://developers.google.com/gemini-code-assist/docs/review-github-code). Gemini can make mistakes, so double check it and [use code with caution](https://support.google.com/legal/answer/13505487).

---

> Old fetch calls retire,
> New hooks take their place now,
> State is managed well.


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T15:26:29Z
user: login: gemini-code-assist[bot]
body: ## Code Review
This pull request successfully migrates Prometheus components from using a custom `dataFetch` utility to RTK Query for API interactions. This is a significant improvement, leveraging RTK Query's features for better state management, caching, and code organization. The implementation uses `async/await` and `try...catch` blocks effectively.

I've found one high-severity issue related to `useEffect` dependencies that needs addressing and two medium-severity suggestions for more specific error handling. Addressing these will further enhance the robustness of the changes.

Minor note: The PR title has a typo "Promethues" (should be "Prometheus").

### Summary of Findings
* **Incomplete `useEffect` Dependencies**: A `useEffect` hook in `PrometheusComponent.js` is missing several dependencies (`prometheusURL` state, props like `selectedK8sContexts`, `k8sConfig`, and functions called within the effect or their underlying prop dependencies). This is a high-severity issue that could lead to stale closures and incorrect behavior.
* **Error Handling Specificity**: In `PrometheusSelectionComponent.js`, the `catch` blocks for RTK Query mutations/queries pass the raw error object to `handleError`. It's recommended to extract more specific error messages (e.g., from `error.data.message`) for better diagnostics. This is a medium-severity issue.
* **Successful RTK Query Migration**: The core goal of migrating data fetching to RTK Query has been achieved, improving code structure and maintainability.

### Merge Readiness
The pull request makes good progress in modernizing data fetching with RTK Query. However, there is a high-severity issue regarding `useEffect` dependencies in `PrometheusComponent.js` that must be addressed before merging to prevent potential bugs. Additionally, a medium-severity suggestion for improving error message specificity in `PrometheusSelectionComponent.js` should be considered.

I am unable to approve pull requests directly. Once these changes are made, further review by other team members would be appropriate before merging.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T15:28:29Z
user: login: amitamrutiya
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T15:59:10Z
user: login: Pratik-050
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T05:21:08Z
user: login: Pratik-050
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T05:21:37Z

Review comments:
diff_hunk: @@ -200,50 +202,42 @@ const PrometheusComponent = (props) => {
     );
   };
 
+  const { data: prometheusConfig, isSuccess: isPrometheusConfigLoaded } =
+    useGetPrometheusConfigQuery(undefined, { skip: !props.isMeshConfigured });
+
   useEffect(() => {
-    if (initialPrometheus.prometheusURL !== prometheusURL) {
-      setPrometheusConfigSuccess(initialPrometheus.prometheusURL !== '');
-      setPrometheusURL(initialPrometheus.prometheusURL);
-      setSelectedPrometheusBoardsConfigs(initialPrometheus.selectedPrometheusBoardsConfigs || []);
-      setConnectionID(initialPrometheus.connectionID);
-      setConnectionName(initialPrometheus.connectionName);
+    if (!isPrometheusConfigLoaded) return;
+
+    updateProgress({ showProgress: false });
+
+    if (prometheusConfig?.prometheusURL) {
+      setPrometheusURL(prometheusConfig.prometheusURL);
+      setPrometheusConfigSuccess(true);
+      setSelectedPrometheusBoardsConfigs(prometheusConfig.selectedPrometheusBoardsConfigs || []);
     }
-  }, [initialPrometheus]);
 
-  useEffect(() => {
-    if (!props.isMeshConfigured) return;
+    const selector = {
+      type: 'ALL_MESH',
+      k8sClusterIDs: getK8sClusterIds(),
+    };
 
-    dataFetch(
-      `/api/telemetry/metrics/config`,
-      {
-        method: 'GET',
-        credentials: 'include',
-        headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
-      },
-      (result) => {
-        updateProgress({ showProgress: false });
-        if (result?.prometheusURL) {
-          const selector = {
-            type: 'ALL_MESH',
-            k8sClusterIDs: getK8sClusterIds(),
-          };
-          fetchAvailableAddons(selector).subscribe({
-            next: (res) => {
-              res?.addonsState?.forEach((addon) => {
-                if (addon.name === 'prometheus' && prometheusURL === '') {
-                  const newURL = `http://${addon.endpoint}`;
-                  setPrometheusURL(newURL);
-                  submitPrometheusConfigure(newURL);
-                }
-              });
-            },
-            error: (err) => console.error('Error registering Prometheus:', err),
-          });
-        }
+    fetchAvailableAddons(selector).subscribe({
+      next: (res) => {
+        res?.addonsState?.forEach((addon) => {
+          if (
+            addon.name === 'prometheus' &&
+            prometheusURL === '' &&
+            prometheusConfig?.prometheusURL === ''
+          ) {
+            const newURL = `http://${addon.endpoint}`;
+            setPrometheusURL(newURL);
+            submitPrometheusConfigure(newURL);
+          }
+        });
       },
-      handleError,
-    );
-  }, []);
+      error: (err) => console.error('Error registering Prometheus:', err),
+    });
+  }, [isPrometheusConfigLoaded, prometheusConfig, props.isMeshConfigured]);
path: ui/components/telemetry/prometheus/PrometheusComponent.js
user: login: gemini-code-assist[bot]
body: ![high](https://img.shields.io/badge/priority-high-orange)

The dependency array for this `useEffect` hook appears to be incomplete. The hook's logic depends on:

1.  `prometheusURL` (state variable, read on line 229).
2.  Values from `props` used by `getK8sClusterIds()` (called on line 221), specifically `props.selectedK8sContexts` and `props.k8sConfig`.
3.  Functions called within the effect: `fetchAvailableAddons` (from props) and `submitPrometheusConfigure` (defined in this component). These functions, or their own unstable dependencies from `props` (like `props.notify`, `props.updateProgress`, `props.handleError` for `submitPrometheusConfigure`), should be included.

Missing dependencies can lead to stale closures and bugs where the effect doesn't re-run when it should. 

Could you please review and update the dependency array to include all values and functions from the component scope that the effect depends on? For functions defined in the component like `submitPrometheusConfigure`, consider memoizing them with `useCallback` before adding to the dependency array.

```suggestion
  }, [isPrometheusConfigLoaded, prometheusConfig, props.isMeshConfigured, prometheusURL, props.selectedK8sContexts, props.k8sConfig, fetchAvailableAddons, submitPrometheusConfigure]);
```
created_at: 2025-05-15T15:28:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,104 +122,97 @@ const PrometheusSelectionComponent = (props) => {
     });
   };
 
-  const boardChange = (newVal) => {
-    updateProgress({ showProgress: true });
+  const [postBoardImport] = usePostBoardImportMutation();
+  const [triggerTemplateQuery] = useLazyQueryTemplateVarsQuery();
 
-    dataFetch(
-      `/api/telemetry/metrics/board_import/${connectionID}`,
-      {
-        method: 'POST',
-        credentials: 'include',
-        headers: { 'Content-Type': 'application/json' },
+  const boardChange = async (newVal) => {
+    updateProgress({ showProgress: true });
+    try {
+      const result = await postBoardImport({
+        connectionID,
         body: newVal,
-      },
-      (result) => {
-        updateProgress({ showProgress: false });
-        const filteredPanels =
-          result.panels?.filter((panel) =>
-            panel.targets?.some((t) => t.datasource?.type?.toLowerCase() === 'prometheus'),
-          ) || [];
-
-        if (filteredPanels.length === 0) {
-          return handleError('No panels found with target datasource as prometheus.');
-        }
+      }).unwrap();
 
-        setGrafanaBoardObject(result);
-        setPanels(filteredPanels);
-        setSelectedPanels(filteredPanels.map((p) => p.id));
-        setTemplateVars(result.template_vars || []);
-        setTemplateVarOptions([]);
-        setSelectedTemplateVars([]);
+      const filteredPanels =
+        result.panels?.filter((panel) =>
+          panel.targets?.some((t) => t.datasource?.type?.toLowerCase() === 'prometheus'),
+        ) || [];
 
-        if (result.template_vars?.length > 0) {
-          queryTemplateVars(0, result.template_vars, [], []);
-        }
-      },
-      handleError,
-    );
+      if (filteredPanels.length === 0) {
+        return handleError('No panels found with target datasource as prometheus.');
+      }
+
+      setGrafanaBoardObject(result);
+      setPanels(filteredPanels);
+      setSelectedPanels(filteredPanels.map((p) => p.id));
+      setTemplateVars(result.template_vars || []);
+      setTemplateVarOptions([]);
+      setSelectedTemplateVars([]);
+
+      if (result.template_vars?.length > 0) {
+        queryTemplateVars(0, result.template_vars, [], []);
+      }
+    } catch (error) {
+      handleError(error);
path: ui/components/telemetry/prometheus/PrometheusSelectionComponent.js
user: login: gemini-code-assist[bot]
body: ![medium](https://img.shields.io/badge/priority-medium-yellow)

In the `catch` block for `boardChange`, `handleError(error)` is called. While this passes the error along, it might be more informative to extract a specific message from the `error` object if it's an RTK Query error. 

For instance, RTK Query errors often have a `data` property with more details (e.g., `error.data?.message` or `error.data?.error`). Passing a more specific string message to `handleError` could improve debugging and user feedback.

Consider checking the structure of the `error` object and passing a more refined message.

```suggestion
      handleError(error?.data?.message || error?.data?.error || error?.message || 'Failed to import board.');
```
created_at: 2025-05-15T15:28:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,104 +122,97 @@
     });
   };
 
-  const boardChange = (newVal) => {
-    updateProgress({ showProgress: true });
+  const [postBoardImport] = usePostBoardImportMutation();
+  const [triggerTemplateQuery] = useLazyQueryTemplateVarsQuery();
 
-    dataFetch(
-      `/api/telemetry/metrics/board_import/${connectionID}`,
-      {
-        method: 'POST',
-        credentials: 'include',
-        headers: { 'Content-Type': 'application/json' },
+  const boardChange = async (newVal) => {
+    updateProgress({ showProgress: true });
+    try {
+      const result = await postBoardImport({
+        connectionID,
         body: newVal,
-      },
-      (result) => {
-        updateProgress({ showProgress: false });
-        const filteredPanels =
-          result.panels?.filter((panel) =>
-            panel.targets?.some((t) => t.datasource?.type?.toLowerCase() === 'prometheus'),
-          ) || [];
-
-        if (filteredPanels.length === 0) {
-          return handleError('No panels found with target datasource as prometheus.');
-        }
+      }).unwrap();
 
-        setGrafanaBoardObject(result);
-        setPanels(filteredPanels);
-        setSelectedPanels(filteredPanels.map((p) => p.id));
-        setTemplateVars(result.template_vars || []);
-        setTemplateVarOptions([]);
-        setSelectedTemplateVars([]);
+      const filteredPanels =
+        result.panels?.filter((panel) =>
+          panel.targets?.some((t) => t.datasource?.type?.toLowerCase() === 'prometheus'),
+        ) || [];
 
-        if (result.template_vars?.length > 0) {
-          queryTemplateVars(0, result.template_vars, [], []);
-        }
-      },
-      handleError,
-    );
+      if (filteredPanels.length === 0) {
+        return handleError('No panels found with target datasource as prometheus.');
+      }
+
+      setGrafanaBoardObject(result);
+      setPanels(filteredPanels);
+      setSelectedPanels(filteredPanels.map((p) => p.id));
+      setTemplateVars(result.template_vars || []);
+      setTemplateVarOptions([]);
+      setSelectedTemplateVars([]);
+
+      if (result.template_vars?.length > 0) {
+        queryTemplateVars(0, result.template_vars, [], []);
+      }
+    } catch (error) {
+      handleError(error);
+    } finally {
+      updateProgress({ showProgress: false });
+    }
   };
 
-  const queryTemplateVars = (ind, vars, options, selectedVars) => {
+  const queryTemplateVars = async (ind, vars, options, selectedVars) => {
     if (!vars?.[ind]) return;
 
-    let queryURL = `/api/telemetry/metrics/query/${connectionID}?query=${encodeURIComponent(vars[ind].query)}`;
+    let queryStr = `query=${encodeURIComponent(vars[ind].query)}`;
     for (let i = ind; i > 0; i--) {
-      queryURL += `&${vars[i - 1].name}=${selectedVars[i - 1]}`;
+      queryStr += `&${vars[i - 1].name}=${selectedVars[i - 1]}`;
     }
 
     if (vars[ind].query.startsWith('label_values') && vars[ind].query.includes(',')) {
-      // series query needs a start and end time or else it will take way longer to return. . .
-      // but at this point this component does not have the time range selection bcoz the time range selection comes after this component makes its selections
-      // hence for now just limiting the time period to the last 24hrs
       const ed = new Date();
       const sd = new Date();
       sd.setDate(sd.getDate() - 1);
-      queryURL += `&start=${Math.floor(sd.getTime() / 1000)}&end=${Math.floor(ed.getTime() / 1000)}`; // accounts for the last 24hrs
+      queryStr += `&start=${Math.floor(sd.getTime() / 1000)}&end=${Math.floor(ed.getTime() / 1000)}`;
     }
 
     updateProgress({ showProgress: true });
-
-    dataFetch(
-      queryURL,
-      { credentials: 'include' },
-      (result) => {
-        updateProgress({ showProgress: false });
-        let tmpVarOpts = [];
-
-        if (Array.isArray(result?.data)) {
-          if (
-            vars[ind].query.startsWith('label_values') &&
-            vars[ind].query.includes(',') &&
-            typeof result.data[0] === 'object'
-          ) {
-            const q = vars[ind].query.replace('label_values(', '').slice(0, -1);
-            const qInd = q.split(',').pop().trim();
-            result.data.forEach((d) => {
-              const v = d[qInd];
-              if (v && !tmpVarOpts.includes(v)) tmpVarOpts.push(v);
-            });
-          } else {
-            tmpVarOpts = result.data;
-          }
-        } else if (result?.data?.result) {
-          tmpVarOpts = result.data.result.map(({ metric }) => Object.values(metric)?.[0]);
+    try {
+      const result = await triggerTemplateQuery({ connectionID, query: queryStr }).unwrap();
+      let tmpVarOpts = [];
+
+      if (Array.isArray(result?.data)) {
+        if (
+          vars[ind].query.startsWith('label_values') &&
+          vars[ind].query.includes(',') &&
+          typeof result.data[0] === 'object'
+        ) {
+          const q = vars[ind].query.replace('label_values(', '').slice(0, -1);
+          const qInd = q.split(',').pop().trim();
+          result.data.forEach((d) => {
+            const v = d[qInd];
+            if (v && !tmpVarOpts.includes(v)) tmpVarOpts.push(v);
+          });
+        } else {
+          tmpVarOpts = result.data;
         }
+      } else if (result?.data?.result) {
+        tmpVarOpts = result.data.result.map(({ metric }) => Object.values(metric)?.[0]);
+      }
 
-        setTemplateVarOptions((prev) => {
-          const newOptions = [...prev];
-          newOptions[ind] = tmpVarOpts;
-          return newOptions;
-        });
-      },
-      (error) => {
-        setTemplateVarOptions((prev) => {
-          const newOptions = [...prev];
-          newOptions[ind] = [vars[ind].Value];
-          return newOptions;
-        });
-        handleError(error);
-      },
-    );
+      setTemplateVarOptions((prev) => {
+        const newOptions = [...prev];
+        newOptions[ind] = tmpVarOpts;
+        return newOptions;
+      });
+    } catch (error) {
+      setTemplateVarOptions((prev) => {
+        const newOptions = [...prev];
+        newOptions[ind] = [vars[ind].Value];
+        return newOptions;
+      });
+      handleError(error);
path: ui/components/telemetry/prometheus/PrometheusSelectionComponent.js
user: login: gemini-code-assist[bot]
body: ![medium](https://img.shields.io/badge/priority-medium-yellow)

Similar to the `boardChange` function, the `catch` block here calls `handleError(error)`. It would be beneficial to extract a more specific error message from the RTK Query `error` object before passing it to `handleError`.

This can provide better context for the error.

```suggestion
      handleError(error?.data?.message || error?.data?.error || error?.message || 'Failed to query template variables.');
```
created_at: 2025-05-15T15:28:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,23 +26,19 @@ const ButtonContainer = styled('div')(({ theme }) => ({
 
 // change this to display all connected prometheuses connecion and based on the selection updat tht erduc prom object
 const PrometheusConfigComponent = ({ urlError, handleChange, handlePrometheusConfigure }) => {
-  const [availablePrometheusConnection, setAvailablePrometheusConnection] = useState([]);
+  const [triggerFetchConnections, { data }] = useLazyGetConnectionsQuery();
 
   useEffect(() => {
-    dataFetch(
-      `/api/integrations/connections?page=0&pagesize=1&status=${encodeURIComponent(
-        JSON.stringify([CONNECTION_STATES.CONNECTED]),
-      )}&kind=${encodeURIComponent(JSON.stringify([CONNECTION_KINDS.PROMETHEUS]))}`,
-      {
-        credentials: 'include',
-        method: 'GET',
-      },
-      (result) => {
-        setAvailablePrometheusConnection(result?.connections);
-      },
-    );
+    triggerFetchConnections({
+      page: 0,
+      pagesize: 1,
+      status: JSON.stringify([CONNECTION_STATES.CONNECTED]),
+      kind: JSON.stringify([CONNECTION_KINDS.PROMETHEUS]),
+    });
   }, []);
path: ui/components/telemetry/prometheus/PrometheusConfigComponent.js
user: login: amitamrutiya
body: no need of this useEffect, you can directly made an API call
created_at: 2025-05-18T15:58:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -140,4 +164,7 @@ export const {
   useGetConnectionByKindQuery,
   useCancelConnectionRegisterMutation,
   useAddKubernetesConfigMutation,
+  useGetPrometheusConfigQuery,
+  usePostBoardImportMutation,
+  useLazyQueryTemplateVarsQuery,
path: ui/rtk-query/connection.js
user: login: amitamrutiya
body: add this into telementry rtk file
created_at: 2025-05-18T15:58:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,23 +26,19 @@ const ButtonContainer = styled('div')(({ theme }) => ({
 
 // change this to display all connected prometheuses connecion and based on the selection updat tht erduc prom object
 const PrometheusConfigComponent = ({ urlError, handleChange, handlePrometheusConfigure }) => {
-  const [availablePrometheusConnection, setAvailablePrometheusConnection] = useState([]);
+  const [triggerFetchConnections, { data }] = useLazyGetConnectionsQuery();
 
   useEffect(() => {
-    dataFetch(
-      `/api/integrations/connections?page=0&pagesize=1&status=${encodeURIComponent(
-        JSON.stringify([CONNECTION_STATES.CONNECTED]),
-      )}&kind=${encodeURIComponent(JSON.stringify([CONNECTION_KINDS.PROMETHEUS]))}`,
-      {
-        credentials: 'include',
-        method: 'GET',
-      },
-      (result) => {
-        setAvailablePrometheusConnection(result?.connections);
-      },
-    );
+    triggerFetchConnections({
+      page: 0,
+      pagesize: 1,
+      status: JSON.stringify([CONNECTION_STATES.CONNECTED]),
+      kind: JSON.stringify([CONNECTION_KINDS.PROMETHEUS]),
+    });
   }, []);
path: ui/components/telemetry/prometheus/PrometheusConfigComponent.js
user: login: Pratik-050
body: Removed the useEffect.
created_at: 2025-05-19T05:21:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -140,4 +164,7 @@ export const {
   useGetConnectionByKindQuery,
   useCancelConnectionRegisterMutation,
   useAddKubernetesConfigMutation,
+  useGetPrometheusConfigQuery,
+  usePostBoardImportMutation,
+  useLazyQueryTemplateVarsQuery,
path: ui/rtk-query/connection.js
user: login: Pratik-050
body: Moved the logic to telemetry.js 
created_at: 2025-05-19T05:21:37Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-15T15:29:17Z
body: <!-- meshmap-snapshot: do not delete/edit this line -->
[<img src="https://raw.githubusercontent.com/layer5labs/meshery-extensions-packages/master/action-assets/2025@5/dea82811-74ba-474f-b9e4-426e7401707eNn18ERs=.png">](https://raw.githubusercontent.com/layer5labs/meshery-extensions-packages/master/action-assets/2025@5/dea82811-74ba-474f-b9e4-426e7401707eNn18ERs=.png) _[View in catalog](https://cloud.layer5.io/catalog/content/design/24e9dbda-18ab-4454-adef-6ac0ef3cf5c6), [Edit in playground](https://playground.meshery.io/extension/meshmap?mode=design&design=24e9dbda-18ab-4454-adef-6ac0ef3cf5c6) or learn how to [interpret Meshery Designs](https://cloud.layer5.io/academy/learning-paths/mastering-meshery/introduction-to-meshery?chapter=interpreting-meshery-designs)_
author_association: CONTRIBUTOR
user: login: leecalcote
created_at: 2025-05-15T19:21:00Z
body: @Pratik-050 thoughts on the feedback?
author_association: MEMBER
user: login: leecalcote
created_at: 2025-05-15T19:21:12Z
body: eslint check is failing...
author_association: MEMBER
user: login: Pratik-050
created_at: 2025-05-16T05:03:02Z
body: Yes @leecalcote some unused variables are there and also there's a problem in the dependency list of the useEffect I'll update the PR accordingly. Thanks!

author_association: CONTRIBUTOR
user: login: Pratik-050
created_at: 2025-05-19T05:59:29Z
body: Hello @amitamrutiya I've made the requested changes. Please have a look. Thanks!
P.S: I've force pushed as the head was diverging but the merge from upstream master was normal.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-19T09:31:09Z
body:         
  **Commit SHA:** `87c74c6c44101e8dc3fc57e249aef2be374f7d62`  

  ### END-TO-END TESTS

- Testing started at: May 19th 2025, 9:25:04 am

**📦 Test Result Summary**

- ✅ 70 passed
- ❌ 0 failed
- ⚠️ 3 flaked
- ⏩ 0 skipped

⌛ _Duration: 5 minutes and 41 seconds_

**Overall Result**: 👍 All tests passed.



<details>
    <summary>[Show/Hide] Test Result Details</summary>
    <div markdown="1">

| Test | Browser | Test Case | Tags | Result |
| :---: | :---: | :--- | :---: | :---: |
| 1 | chromium-meshery-provider | Transition to disconnected state and then back to connected state | unstable | ⚠️ |
| 2 | chromium-meshery-provider | Transition to ignored state and then back to connected state | unstable | ⚠️ |
| 3 | chromium-meshery-provider | Transition to not found state and then back to connected state | unstable | ⚠️ |
| 4 | chromium-meshery-provider | Delete Kubernetes cluster connections | unstable | ⚠️ |
| 5 | chromium-meshery-provider | Ping Istio Adapter | unstable | ⚠️ |
| 6 | chromium-local-provider | Add a cluster connection by uploading kubeconfig file | unstable | ⚠️ |
| 7 | chromium-local-provider | Transition to disconnected state and then back to connected state | unstable | ⚠️ |
| 8 | chromium-local-provider | Transition to ignored state and then back to connected state | unstable | ⚠️ |
| 9 | chromium-local-provider | Transition to not found state and then back to connected state | unstable | ⚠️ |
| 10 | chromium-local-provider | Delete Kubernetes cluster connections | unstable | ⚠️ |

</div>
</details>


<!-- To see the full report, please visit our CI/CD pipeline with reporter. -->
  
author_association: CONTRIBUTOR