Commit f5bc1c39 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'dbodicherla-add-prefix-for-templating-variables' into 'master'

Add prefix to template vars in url

See merge request gitlab-org/gitlab!31690
parents 30cc0b78 d92ca12c
...@@ -216,3 +216,14 @@ export const VARIABLE_TYPES = { ...@@ -216,3 +216,14 @@ export const VARIABLE_TYPES = {
custom: 'custom', custom: 'custom',
text: 'text', text: 'text',
}; };
/**
* The names of templating variables defined in the dashboard yml
* file are prefixed with a constant so that it doesn't collide with
* other URL params that the monitoring dashboard relies on for
* features like panel fullscreen etc.
*
* The prefix is added before it is appended to the URL and removed
* before passing the data to the backend.
*/
export const VARIABLE_PREFIX = 'var-';
import { flatMap } from 'lodash';
import { removePrefixFromLabels } from './utils';
import { NOT_IN_DB_PREFIX } from '../constants'; import { NOT_IN_DB_PREFIX } from '../constants';
const metricsIdsInPanel = panel => const metricsIdsInPanel = panel =>
...@@ -110,16 +112,19 @@ export const filteredEnvironments = state => ...@@ -110,16 +112,19 @@ export const filteredEnvironments = state =>
); );
/** /**
* Maps an variables object to an array * Maps an variables object to an array along with stripping
* the variable prefix.
*
* @param {Object} variables - Custom variables provided by the user * @param {Object} variables - Custom variables provided by the user
* @returns {Array} The custom variables array to be send to the API * @returns {Array} The custom variables array to be send to the API
* in the format of [variable1, variable1_value] * in the format of [variable1, variable1_value]
*/ */
export const getCustomVariablesArray = state => export const getCustomVariablesArray = state =>
Object.entries(state.promVariables) flatMap(state.promVariables, (val, key) => [
.flat() encodeURIComponent(removePrefixFromLabels(key)),
.map(encodeURIComponent); encodeURIComponent(val),
]);
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {}; export default () => {};
...@@ -2,7 +2,7 @@ import { slugify } from '~/lib/utils/text_utility'; ...@@ -2,7 +2,7 @@ import { slugify } from '~/lib/utils/text_utility';
import createGqClient, { fetchPolicies } from '~/lib/graphql'; import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format'; import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { NOT_IN_DB_PREFIX } from '../constants'; import { NOT_IN_DB_PREFIX, VARIABLE_PREFIX } from '../constants';
export const gqClient = createGqClient( export const gqClient = createGqClient(
{}, {},
...@@ -229,3 +229,22 @@ export const normalizeQueryResult = timeSeries => { ...@@ -229,3 +229,22 @@ export const normalizeQueryResult = timeSeries => {
return normalizedResult; return normalizedResult;
}; };
/**
* Variable labels are used as names for the dropdowns and also
* as URL params. Prefixing the name reduces the risk of
* collision with other URL params
*
* @param {String} label label for the template variable
* @returns {String}
*/
export const addPrefixToLabels = label => `${VARIABLE_PREFIX}${label}`;
/**
* Before the templating variables are passed to the backend the
* prefix needs to be removed.
*
* @param {String} label label to remove prefix from
* @returns {String}
*/
export const removePrefixFromLabels = label => label.replace(VARIABLE_PREFIX, '');
import { isString } from 'lodash'; import { isString } from 'lodash';
import { addPrefixToLabels } from './utils';
import { VARIABLE_TYPES } from '../constants'; import { VARIABLE_TYPES } from '../constants';
/** /**
...@@ -149,7 +150,7 @@ export const parseTemplatingVariables = ({ variables = {} } = {}) => ...@@ -149,7 +150,7 @@ export const parseTemplatingVariables = ({ variables = {} } = {}) =>
if (parsedVar) { if (parsedVar) {
acc[key] = { acc[key] = {
...parsedVar, ...parsedVar,
label: parsedVar.label || key, label: addPrefixToLabels(parsedVar.label || key),
}; };
} }
return acc; return acc;
......
import { omit } from 'lodash'; import { pickBy } from 'lodash';
import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_utility'; import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_utility';
import { import {
timeRangeParamNames, timeRangeParamNames,
timeRangeFromParams, timeRangeFromParams,
timeRangeToParams, timeRangeToParams,
} from '~/lib/utils/datetime_range'; } from '~/lib/utils/datetime_range';
import { VARIABLE_PREFIX } from './constants';
/** /**
* List of non time range url parameters * List of non time range url parameters
...@@ -122,19 +123,16 @@ export const timeRangeFromUrl = (search = window.location.search) => { ...@@ -122,19 +123,16 @@ export const timeRangeFromUrl = (search = window.location.search) => {
}; };
/** /**
* Returns an array with user defined variables from the URL * User-defined variables from the URL are extracted. The variables
* begin with a constant prefix so that it doesn't collide with
* other URL params.
* *
* @returns {Array} The custom variables defined by the
* user in the URL
* @param {String} New URL * @param {String} New URL
* @returns {Object} The custom variables defined by the user in the URL
*/ */
export const promCustomVariablesFromUrl = (search = window.location.search) => { export const promCustomVariablesFromUrl = (search = window.location.search) =>
const params = queryToObject(search); pickBy(queryToObject(search), (val, key) => key.startsWith(VARIABLE_PREFIX));
const paramsToRemove = timeRangeParamNames.concat(dashboardParams);
return omit(params, paramsToRemove);
};
/** /**
* Returns a URL with no time range based on the current URL. * Returns a URL with no time range based on the current URL.
......
---
title: Add prefix to template variables in URL in the monitoring dashboard
merge_request: 31690
author:
type: changed
...@@ -15,8 +15,8 @@ describe('Metrics dashboard/variables section component', () => { ...@@ -15,8 +15,8 @@ describe('Metrics dashboard/variables section component', () => {
let store; let store;
let wrapper; let wrapper;
const sampleVariables = { const sampleVariables = {
label1: 'pod', 'var-label1': 'pod',
label2: 'main', 'var-label2': 'main',
}; };
const createShallowWrapper = () => { const createShallowWrapper = () => {
......
...@@ -642,7 +642,7 @@ const generateMockTemplatingData = data => { ...@@ -642,7 +642,7 @@ const generateMockTemplatingData = data => {
const responseForSimpleTextVariable = { const responseForSimpleTextVariable = {
simpleText: { simpleText: {
label: 'simpleText', label: 'var-simpleText',
type: 'text', type: 'text',
value: 'Simple text', value: 'Simple text',
}, },
...@@ -650,7 +650,7 @@ const responseForSimpleTextVariable = { ...@@ -650,7 +650,7 @@ const responseForSimpleTextVariable = {
const responseForAdvTextVariable = { const responseForAdvTextVariable = {
advText: { advText: {
label: 'Variable 4', label: 'var-Variable 4',
type: 'text', type: 'text',
value: 'default', value: 'default',
}, },
...@@ -658,7 +658,7 @@ const responseForAdvTextVariable = { ...@@ -658,7 +658,7 @@ const responseForAdvTextVariable = {
const responseForSimpleCustomVariable = { const responseForSimpleCustomVariable = {
simpleCustom: { simpleCustom: {
label: 'simpleCustom', label: 'var-simpleCustom',
options: [ options: [
{ {
default: false, default: false,
...@@ -682,7 +682,7 @@ const responseForSimpleCustomVariable = { ...@@ -682,7 +682,7 @@ const responseForSimpleCustomVariable = {
const responseForAdvancedCustomVariableWithoutOptions = { const responseForAdvancedCustomVariableWithoutOptions = {
advCustomWithoutOpts: { advCustomWithoutOpts: {
label: 'advCustomWithoutOpts', label: 'var-advCustomWithoutOpts',
options: [], options: [],
type: 'custom', type: 'custom',
}, },
...@@ -690,7 +690,7 @@ const responseForAdvancedCustomVariableWithoutOptions = { ...@@ -690,7 +690,7 @@ const responseForAdvancedCustomVariableWithoutOptions = {
const responseForAdvancedCustomVariableWithoutLabel = { const responseForAdvancedCustomVariableWithoutLabel = {
advCustomWithoutLabel: { advCustomWithoutLabel: {
label: 'advCustomWithoutLabel', label: 'var-advCustomWithoutLabel',
options: [ options: [
{ {
default: false, default: false,
...@@ -710,7 +710,7 @@ const responseForAdvancedCustomVariableWithoutLabel = { ...@@ -710,7 +710,7 @@ const responseForAdvancedCustomVariableWithoutLabel = {
const responseForAdvancedCustomVariable = { const responseForAdvancedCustomVariable = {
...responseForSimpleCustomVariable, ...responseForSimpleCustomVariable,
advCustomNormal: { advCustomNormal: {
label: 'Advanced Var', label: 'var-Advanced Var',
options: [ options: [
{ {
default: false, default: false,
......
...@@ -327,7 +327,8 @@ describe('Monitoring store Getters', () => { ...@@ -327,7 +327,8 @@ describe('Monitoring store Getters', () => {
describe('getCustomVariablesArray', () => { describe('getCustomVariablesArray', () => {
let state; let state;
const sampleVariables = { const sampleVariables = {
label1: 'pod', 'var-label1': 'pod',
'var-label2': 'env',
}; };
beforeEach(() => { beforeEach(() => {
...@@ -340,7 +341,7 @@ describe('Monitoring store Getters', () => { ...@@ -340,7 +341,7 @@ describe('Monitoring store Getters', () => {
mutations[types.SET_PROM_QUERY_VARIABLES](state, sampleVariables); mutations[types.SET_PROM_QUERY_VARIABLES](state, sampleVariables);
const variablesArray = getters.getCustomVariablesArray(state); const variablesArray = getters.getCustomVariablesArray(state);
expect(variablesArray).toEqual(['label1', 'pod']); expect(variablesArray).toEqual(['label1', 'pod', 'label2', 'env']);
}); });
it('transforms the promVariables object to an empty array when no keys are present', () => { it('transforms the promVariables object to an empty array when no keys are present', () => {
......
...@@ -192,9 +192,10 @@ describe('monitoring/utils', () => { ...@@ -192,9 +192,10 @@ describe('monitoring/utils', () => {
direction: 'left', direction: 'left',
anchor: 'top', anchor: 'top',
pod: 'POD', pod: 'POD',
'var-pod': 'POD',
}); });
expect(promCustomVariablesFromUrl()).toEqual(expect.objectContaining({ pod: 'POD' })); expect(promCustomVariablesFromUrl()).toEqual(expect.objectContaining({ 'var-pod': 'POD' }));
}); });
it('returns an empty object when no custom variables are present', () => { it('returns an empty object when no custom variables are present', () => {
......
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