Commit 54c095cc authored by Jose Vargas's avatar Jose Vargas

Filter out custom variables from Url

This filters out any custom variables that the
user might send via the URL params to the
monitor dashboard.
parent 0c4df6a7
......@@ -38,6 +38,7 @@ import {
timeRangeFromUrl,
panelToUrl,
expandedPanelPayloadFromUrl,
customVariablesFromUrl,
} from '../utils';
import { metricStates } from '../constants';
import { defaultTimeRange, timeRanges } from '~/vue_shared/constants';
......@@ -211,6 +212,7 @@ export default {
hasValidDates: true,
timeRanges,
isRearrangingPanels: false,
customVariables: customVariablesFromUrl(),
};
},
computed: {
......@@ -282,12 +284,14 @@ export default {
this.setGettingStartedEmptyState();
} else {
this.setTimeRange(this.selectedTimeRange);
this.setVariables(this.customVariables);
this.fetchData();
}
},
methods: {
...mapActions('monitoringDashboard', [
'setTimeRange',
'setVariables',
'fetchData',
'fetchDashboardData',
'setGettingStartedEmptyState',
......
......@@ -80,6 +80,10 @@ export const setTimeRange = ({ commit }, timeRange) => {
commit(types.SET_TIME_RANGE, timeRange);
};
export const setVariables = ({ commit }, variables) => {
commit(types.SET_QUERY_VARIABLES, variables);
};
export const filterEnvironments = ({ commit, dispatch }, searchTerm) => {
commit(types.SET_ENVIRONMENTS_FILTER, searchTerm);
dispatch('fetchEnvironmentsData');
......@@ -218,12 +222,16 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
*
* @param {metric} metric
*/
export const fetchPrometheusMetric = ({ commit }, { metric, defaultQueryParams }) => {
export const fetchPrometheusMetric = ({ commit, state }, { metric, defaultQueryParams }) => {
const queryParams = { ...defaultQueryParams };
if (metric.step) {
queryParams.step = metric.step;
}
if (state.variables.length > 0) {
queryParams.variables = state.variables;
}
commit(types.REQUEST_METRIC_RESULT, { metricId: metric.metricId });
return getPrometheusMetricResult(metric.prometheusEndpointPath, queryParams)
......
// Dashboard "skeleton", groups, panels and metrics
// Dashboard "skeleton", groups, panels, metrics, query variables
export const REQUEST_METRICS_DASHBOARD = 'REQUEST_METRICS_DASHBOARD';
export const RECEIVE_METRICS_DASHBOARD_SUCCESS = 'RECEIVE_METRICS_DASHBOARD_SUCCESS';
export const RECEIVE_METRICS_DASHBOARD_FAILURE = 'RECEIVE_METRICS_DASHBOARD_FAILURE';
export const SET_QUERY_VARIABLES = 'SET_QUERY_VARIABLES';
// Annotations
export const RECEIVE_ANNOTATIONS_SUCCESS = 'RECEIVE_ANNOTATIONS_SUCCESS';
......
......@@ -169,4 +169,19 @@ export default {
state.expandedPanel.group = group;
state.expandedPanel.panel = panel;
},
[types.SET_QUERY_VARIABLES](state, variables) {
let variablesArr = [];
const variablesKeys = Object.keys(variables);
if (variablesKeys.length > 0) {
variablesArr = variablesKeys.reduce((acc, key) => {
acc.push(key);
acc.push(`${key}_${variables[key]}`);
return acc;
}, []);
}
state.variables = variablesArr;
},
};
......@@ -33,6 +33,7 @@ export default () => ({
panel: null,
},
allDashboards: [],
variables: [],
// Other project data
annotations: [],
......
import { pickBy } from 'lodash';
import { omit, pickBy } from 'lodash';
import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_utility';
import {
timeRangeParamNames,
......@@ -6,6 +6,11 @@ import {
timeRangeToParams,
} from '~/lib/utils/datetime_range';
/**
* List of non time range url parameters
*/
export const dashboardParams = ['dashboard', 'group', 'title', 'y_label'];
/**
* This method is used to validate if the graph data format for a chart component
* that needs a time series as a response from a prometheus query (queryRange) is
......@@ -114,6 +119,20 @@ export const timeRangeFromUrl = (search = window.location.search) => {
return timeRangeFromParams(params);
};
/**
* Returns an array with user defined variables from the URL
*
* @returns {Array} The custom variables defined by the
* user in the URL
*/
export const customVariablesFromUrl = (search = window.location.search) => {
const params = queryToObject(search);
const paramsToRemove = timeRangeParamNames.concat(dashboardParams);
return omit(params, paramsToRemove);
};
/**
* Returns a URL with no time range based on the current URL.
*
......
---
title: Filter out custom variables from URL and interpolate them in queries
merge_request: 30560
author:
type: added
......@@ -102,7 +102,7 @@ describe('Dashboard', () => {
});
describe('request information to the server', () => {
it('calls to set time range and fetch data', () => {
it('calls to set time range, variables and fetch data', () => {
createShallowWrapper({ hasMetrics: true });
return wrapper.vm.$nextTick().then(() => {
......@@ -111,6 +111,11 @@ describe('Dashboard', () => {
expect.any(Object),
);
expect(store.dispatch).toHaveBeenCalledWith(
'monitoringDashboard/setVariables',
expect.any(Object),
);
expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined);
});
});
......
......@@ -25,6 +25,7 @@ import {
clearExpandedPanel,
setGettingStartedEmptyState,
duplicateSystemDashboard,
setVariables,
} from '~/monitoring/stores/actions';
import {
gqClient,
......@@ -392,6 +393,29 @@ describe('Monitoring store actions', () => {
);
});
});
describe('setVariables', () => {
let mockedState;
beforeEach(() => {
mockedState = storeState();
});
it('should commit SET_QUERY_VARIABLES mutation', done => {
testAction(
setVariables,
{ pod: 'POD' },
mockedState,
[
{
type: types.SET_QUERY_VARIABLES,
payload: { pod: 'POD' },
},
],
[],
done,
);
});
});
describe('fetchDashboard', () => {
let dispatch;
let state;
......
......@@ -364,4 +364,18 @@ describe('Monitoring mutations', () => {
expect(stateCopy.expandedPanel.panel).toEqual(null);
});
});
describe('SET_QUERY_VARIABLES', () => {
it('stores an empty variables array when no custom variables are given', () => {
mutations[types.SET_QUERY_VARIABLES](stateCopy, {});
expect(stateCopy.variables).toEqual([]);
});
it('stores variables in the key key_value format in the array', () => {
mutations[types.SET_QUERY_VARIABLES](stateCopy, { pod: 'POD' });
expect(stateCopy.variables).toEqual(['pod', 'pod_POD']);
});
});
});
......@@ -169,6 +169,29 @@ describe('monitoring/utils', () => {
});
});
describe('customVariablesFromUrl', () => {
const { customVariablesFromUrl } = monitoringUtils;
it('returns an object with only the custom variables', () => {
queryToObject.mockReturnValueOnce({
dashboard: '.gitlab/dashboards/custom_dashboard.yml',
pod: 'POD',
});
expect(customVariablesFromUrl()).toEqual(expect.objectContaining({ pod: 'POD' }));
});
it('returns an empty object when no custom variables are present', () => {
const params = {
dashboard: '.gitlab/dashboards/custom_dashboard.yml',
param1: 'value1',
param2: 'value2',
};
expect(customVariablesFromUrl(params, mockPath)).toStrictEqual({});
});
});
describe('removeTimeRangeParams', () => {
const { removeTimeRangeParams } = monitoringUtils;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment