Commit e8bc265c authored by Sean McGivern's avatar Sean McGivern

Merge branch '218312-change-variables-parameter-format' into 'master'

Send variables parameter as a Hash to the Prometheus proxy API

See merge request gitlab-org/gitlab!33062
parents 0a26a34f 21b97aa4
...@@ -218,13 +218,16 @@ export const fetchPrometheusMetric = ( ...@@ -218,13 +218,16 @@ export const fetchPrometheusMetric = (
{ commit, state, getters }, { commit, state, getters },
{ metric, defaultQueryParams }, { metric, defaultQueryParams },
) => { ) => {
const queryParams = { ...defaultQueryParams }; let queryParams = { ...defaultQueryParams };
if (metric.step) { if (metric.step) {
queryParams.step = metric.step; queryParams.step = metric.step;
} }
if (Object.keys(state.variables).length > 0) { if (Object.keys(state.variables).length > 0) {
queryParams.variables = getters.getCustomVariablesArray; queryParams = {
...queryParams,
...getters.getCustomVariablesParams,
};
} }
commit(types.REQUEST_METRIC_RESULT, { metricId: metric.metricId }); commit(types.REQUEST_METRIC_RESULT, { metricId: metric.metricId });
......
import { flatMap } from 'lodash';
import { NOT_IN_DB_PREFIX } from '../constants'; import { NOT_IN_DB_PREFIX } from '../constants';
import { addPrefixToCustomVariableParams } from './utils';
const metricsIdsInPanel = panel => const metricsIdsInPanel = panel =>
panel.metrics.filter(metric => metric.metricId && metric.result).map(metric => metric.metricId); panel.metrics.filter(metric => metric.metricId && metric.result).map(metric => metric.metricId);
...@@ -116,13 +116,27 @@ export const filteredEnvironments = state => ...@@ -116,13 +116,27 @@ export const filteredEnvironments = state =>
* Maps an variables object to an array along with stripping * Maps an variables object to an array along with stripping
* the variable prefix. * the variable prefix.
* *
* This method outputs an object in the below format
*
* {
* variables[key1]=value1,
* variables[key2]=value2,
* }
*
* This is done so that the backend can identify the custom
* user-defined variables coming through the URL and differentiate
* from other variables used for Prometheus API endpoint.
*
* @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 {variables[key1]=value1, variables[key2]=value2}
*/ */
export const getCustomVariablesArray = state => export const getCustomVariablesParams = state =>
flatMap(state.variables, (variable, key) => [key, variable.value]); Object.keys(state.variables).reduce((acc, variable) => {
acc[addPrefixToCustomVariableParams(variable)] = state.variables[variable]?.value;
return acc;
}, {});
// 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 () => {};
...@@ -249,3 +249,19 @@ export const normalizeQueryResult = timeSeries => { ...@@ -249,3 +249,19 @@ export const normalizeQueryResult = timeSeries => {
return normalizedResult; return normalizedResult;
}; };
/**
* Custom variables defined in the dashboard yml file are
* eventually passed over the wire to the backend Prometheus
* API proxy.
*
* This method adds a prefix to the URL param keys so that
* the backend can differential these variables from the other
* variables.
*
* This is currently only used by getters/getCustomVariablesParams
*
* @param {String} key Variable key that needs to be prefixed
* @returns {String}
*/
export const addPrefixToCustomVariableParams = key => `variables[${key}]`;
...@@ -32,8 +32,8 @@ module Prometheus ...@@ -32,8 +32,8 @@ module Prometheus
def validate_variables(_result) def validate_variables(_result)
return success unless variables return success unless variables
unless variables.is_a?(Array) && variables.size.even? unless variables.is_a?(ActionController::Parameters)
return error(_('Optional parameter "variables" must be an array of keys and values. Ex: [key1, value1, key2, value2]')) return error(_('Optional parameter "variables" must be a Hash. Ex: variables[key1]=value1'))
end end
success success
...@@ -88,12 +88,7 @@ module Prometheus ...@@ -88,12 +88,7 @@ module Prometheus
end end
def variables_hash def variables_hash
# .each_slice(2) converts ['key1', 'value1', 'key2', 'value2'] into variables.to_h
# [['key1', 'value1'], ['key2', 'value2']] which is then converted into
# a hash by to_h: {'key1' => 'value1', 'key2' => 'value2'}
# to_h will raise an ArgumentError if the number of elements in the original
# array is not even.
variables&.each_slice(2).to_h
end end
def query(result) def query(result)
......
---
title: Change format of variables parameter in Prometheus proxy API for metrics dashboard
merge_request: 33062
author:
type: fixed
...@@ -15060,7 +15060,7 @@ msgstr "" ...@@ -15060,7 +15060,7 @@ msgstr ""
msgid "Optional" msgid "Optional"
msgstr "" msgstr ""
msgid "Optional parameter \"variables\" must be an array of keys and values. Ex: [key1, value1, key2, value2]" msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr "" msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab." msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
......
...@@ -84,12 +84,12 @@ describe Projects::Environments::PrometheusApiController do ...@@ -84,12 +84,12 @@ describe Projects::Environments::PrometheusApiController do
before do before do
expected_params[:query] = %{up{pod_name="#{pod_name}"}} expected_params[:query] = %{up{pod_name="#{pod_name}"}}
expected_params[:variables] = ['pod_name', pod_name] expected_params[:variables] = { 'pod_name' => pod_name }
end end
it 'replaces variables with values' do it 'replaces variables with values' do
get :proxy, params: environment_params.merge( get :proxy, params: environment_params.merge(
query: 'up{pod_name="{{pod_name}}"}', variables: ['pod_name', pod_name] query: 'up{pod_name="{{pod_name}}"}', variables: { 'pod_name' => pod_name }
) )
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
......
...@@ -329,7 +329,7 @@ describe('Monitoring store Getters', () => { ...@@ -329,7 +329,7 @@ describe('Monitoring store Getters', () => {
}); });
}); });
describe('getCustomVariablesArray', () => { describe('getCustomVariablesParams', () => {
let state; let state;
beforeEach(() => { beforeEach(() => {
...@@ -340,25 +340,21 @@ describe('Monitoring store Getters', () => { ...@@ -340,25 +340,21 @@ describe('Monitoring store Getters', () => {
it('transforms the variables object to an array in the [variable, variable_value] format for all variable types', () => { it('transforms the variables object to an array in the [variable, variable_value] format for all variable types', () => {
mutations[types.SET_VARIABLES](state, mockTemplatingDataResponses.allVariableTypes); mutations[types.SET_VARIABLES](state, mockTemplatingDataResponses.allVariableTypes);
const variablesArray = getters.getCustomVariablesArray(state); const variablesArray = getters.getCustomVariablesParams(state);
expect(variablesArray).toEqual([ expect(variablesArray).toEqual({
'simpleText', 'variables[advCustomNormal]': 'value2',
'Simple text', 'variables[advText]': 'default',
'advText', 'variables[simpleCustom]': 'value1',
'default', 'variables[simpleText]': 'Simple text',
'simpleCustom', });
'value1',
'advCustomNormal',
'value2',
]);
}); });
it('transforms the variables object to an empty array when no keys are present', () => { it('transforms the variables object to an empty array when no keys are present', () => {
mutations[types.SET_VARIABLES](state, {}); mutations[types.SET_VARIABLES](state, {});
const variablesArray = getters.getCustomVariablesArray(state); const variablesArray = getters.getCustomVariablesParams(state);
expect(variablesArray).toEqual([]); expect(variablesArray).toEqual({});
}); });
}); });
......
...@@ -64,7 +64,7 @@ describe Prometheus::ProxyVariableSubstitutionService do ...@@ -64,7 +64,7 @@ describe Prometheus::ProxyVariableSubstitutionService do
let(:params_keys) do let(:params_keys) do
{ {
query: 'up{pod_name="{{pod_name}}"}', query: 'up{pod_name="{{pod_name}}"}',
variables: ['pod_name', pod_name] variables: { 'pod_name' => pod_name }
} }
end end
...@@ -76,7 +76,7 @@ describe Prometheus::ProxyVariableSubstitutionService do ...@@ -76,7 +76,7 @@ describe Prometheus::ProxyVariableSubstitutionService do
let(:params_keys) do let(:params_keys) do
{ {
query: 'up{pod_name="{{pod_name}}",env="{{ci_environment_slug}}"}', query: 'up{pod_name="{{pod_name}}",env="{{ci_environment_slug}}"}',
variables: ['pod_name', pod_name, 'ci_environment_slug', 'custom_value'] variables: { 'pod_name' => pod_name, 'ci_environment_slug' => 'custom_value' }
} }
end end
...@@ -95,8 +95,7 @@ describe Prometheus::ProxyVariableSubstitutionService do ...@@ -95,8 +95,7 @@ describe Prometheus::ProxyVariableSubstitutionService do
} }
end end
it_behaves_like 'error', 'Optional parameter "variables" must be an ' \ it_behaves_like 'error', 'Optional parameter "variables" must be a Hash. Ex: variables[key1]=value1'
'array of keys and values. Ex: [key1, value1, key2, value2]'
end end
context 'with nil variables' do context 'with nil variables' do
......
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