Fix template variable replacement within regexes
Template variables used within regexes would not replace when the query contained a '/' before the regex in the query (see test). This commit rewrites the logic for replacing template variables within regexes.pull/3995/head
parent
c1f51530c9
commit
85f222b62e
|
@ -5,6 +5,7 @@
|
|||
1. [#3976](https://github.com/influxdata/chronograf/pull/3976): Ensure text template variables reflect query parameters
|
||||
1. [#3976](https://github.com/influxdata/chronograf/pull/3976): Enable using a new, blank text template variable in a query
|
||||
1. [#3976](https://github.com/influxdata/chronograf/pull/3976): Ensure cells with broken queries display “No Data”
|
||||
1. [#3978](https://github.com/influxdata/chronograf/pull/3978): Fix use of template variables within InfluxQL regexes
|
||||
|
||||
## v1.6.0 [2018-06-18]
|
||||
|
||||
|
|
|
@ -110,26 +110,51 @@ const renderTemplate = (query: string, template: Template): string => {
|
|||
}
|
||||
}
|
||||
|
||||
const REGEX_COMPARATORS = ['=~', '!~']
|
||||
const REGEX_DELIMITER = '/'
|
||||
|
||||
const replaceAllRegex = (
|
||||
query: string,
|
||||
search: string,
|
||||
replacement: string
|
||||
) => {
|
||||
// check for presence of anything between two forward slashes /[your stuff here]/
|
||||
const matches = query.match(/\/([^\/]*)\//gm)
|
||||
let result = query
|
||||
let i = 0
|
||||
|
||||
if (!matches) {
|
||||
return query
|
||||
}
|
||||
while (i < result.length - 1) {
|
||||
const chars = result[i] + result[i + 1]
|
||||
const isStartOfRegex = REGEX_COMPARATORS.includes(chars)
|
||||
|
||||
return matches.reduce((acc, m) => {
|
||||
if (m.includes(search)) {
|
||||
const replaced = m.replace(search, replacement)
|
||||
return acc.split(m).join(replaced)
|
||||
if (!isStartOfRegex) {
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
|
||||
return acc
|
||||
}, query)
|
||||
const regexStart = findNext(result, REGEX_DELIMITER, i)
|
||||
const regexEnd = findNext(result, REGEX_DELIMITER, regexStart + 1)
|
||||
const regexContent = result.slice(regexStart + 1, regexEnd)
|
||||
const replacedRegexContent = regexContent.replace(search, replacement)
|
||||
|
||||
result =
|
||||
result.slice(0, regexStart + 1) +
|
||||
replacedRegexContent +
|
||||
result.slice(regexEnd)
|
||||
|
||||
i = findNext(result, REGEX_DELIMITER, regexStart + 1)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const findNext = (s: string, t: string, startIndex: number) => {
|
||||
const tail = s.slice(startIndex)
|
||||
const i = tail.indexOf(t)
|
||||
|
||||
if (i === -1) {
|
||||
throw new Error(`Expected token '${t}' in '${tail}'`)
|
||||
}
|
||||
|
||||
return startIndex + i
|
||||
}
|
||||
|
||||
const replaceAll = (query: string, search: string, replacement: string) => {
|
||||
|
|
|
@ -221,6 +221,38 @@ describe('templates.utils.replace', () => {
|
|||
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
|
||||
it('replaces a query with a single / properly', () => {
|
||||
const templates = [
|
||||
{
|
||||
tempVar: ':Cluster_Id:',
|
||||
values: [
|
||||
{
|
||||
value: 'e87a44cb9df65eb0d6fa50730842d926',
|
||||
type: TemplateValueType.TagValue,
|
||||
selected: true,
|
||||
localSelected: true,
|
||||
},
|
||||
],
|
||||
id: 'e4731672-e3d6-4633-b2ed-146ea51cbb7f',
|
||||
type: TemplateType.TagValues,
|
||||
label: '',
|
||||
query: {
|
||||
influxql:
|
||||
'SHOW TAG VALUES ON :database: FROM :measurement: WITH KEY=:tagKey:',
|
||||
db: 'telegraf',
|
||||
measurement: 'cpu',
|
||||
tagKey: 'cluster_id',
|
||||
fieldKey: '',
|
||||
},
|
||||
},
|
||||
]
|
||||
const query = `SELECT last("max") from (SELECT max("total")/1073741824 FROM "telegraf".."mem" WHERE "cluster_id" = :Cluster_Id: AND (host =~ /.*data.*/ OR host =~ /tot-.*-(3|4)/) GROUP BY time(1s), host)`
|
||||
const expected = `SELECT last("max") from (SELECT max("total")/1073741824 FROM "telegraf".."mem" WHERE "cluster_id" = 'e87a44cb9df65eb0d6fa50730842d926' AND (host =~ /.*data.*/ OR host =~ /tot-.*-(3|4)/) GROUP BY time(1s), host)`
|
||||
const actual = templateReplace(query, templates)
|
||||
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with no templates', () => {
|
||||
|
|
Loading…
Reference in New Issue