[KQL] Do not generate nested AST/Elasticsearch queries for same-level AND/OR clauses (#93506)

* [KQL] Do not generate nested AST for same-level AND/OR clauses

* Update tests

* Update snapshots
This commit is contained in:
Lukas Olson 2021-03-05 15:52:49 -07:00 committed by GitHub
parent fd1d796564
commit c9b0b1577a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 816 additions and 696 deletions

View file

@ -215,35 +215,35 @@ describe('Filter Utils', () => {
type: 'foo',
},
{
astPath: 'arguments.1.arguments.0',
astPath: 'arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.0',
astPath: 'arguments.2',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.3',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.title',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.4.arguments.0',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.1',
astPath: 'arguments.4.arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
@ -290,35 +290,35 @@ describe('Filter Utils', () => {
type: null,
},
{
astPath: 'arguments.1.arguments.0',
astPath: 'arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.0',
astPath: 'arguments.2',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.3',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.title',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.4.arguments.0',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.1',
astPath: 'arguments.4.arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
@ -345,14 +345,14 @@ describe('Filter Utils', () => {
type: 'foo',
},
{
astPath: 'arguments.1.arguments.0',
astPath: 'arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.0',
astPath: 'arguments.2',
error:
"This key 'foo.bytes' does NOT match the filter proposition SavedObjectType.attributes.key",
isSavedObjectAttr: false,
@ -360,21 +360,21 @@ describe('Filter Utils', () => {
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.3',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.title',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.4.arguments.0',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.1',
astPath: 'arguments.4.arguments.1',
error:
"This key 'foo.description' does NOT match the filter proposition SavedObjectType.attributes.key",
isSavedObjectAttr: false,
@ -402,35 +402,35 @@ describe('Filter Utils', () => {
type: 'bar',
},
{
astPath: 'arguments.1.arguments.0',
astPath: 'arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.0',
astPath: 'arguments.2',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.3',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.title',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.4.arguments.0',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.1',
astPath: 'arguments.4.arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
@ -457,21 +457,21 @@ describe('Filter Utils', () => {
type: 'foo',
},
{
astPath: 'arguments.1.arguments.0',
astPath: 'arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.0',
astPath: 'arguments.2',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.bytes',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.3',
error:
"This key 'foo.attributes.header' does NOT exist in foo saved object index patterns",
isSavedObjectAttr: false,
@ -479,14 +479,14 @@ describe('Filter Utils', () => {
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.0',
astPath: 'arguments.4.arguments.0',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',
type: 'foo',
},
{
astPath: 'arguments.1.arguments.1.arguments.1.arguments.1.arguments.1',
astPath: 'arguments.4.arguments.1',
error: null,
isSavedObjectAttr: false,
key: 'foo.attributes.description',

View file

@ -69,6 +69,26 @@ describe('kuery AST API', () => {
expect(actual).toEqual(expected);
});
test('should not nest same-level "and"', () => {
const expected = nodeTypes.function.buildNode('and', [
nodeTypes.function.buildNode('is', null, 'foo'),
nodeTypes.function.buildNode('is', null, 'bar'),
nodeTypes.function.buildNode('is', null, 'baz'),
]);
const actual = fromKueryExpression('foo and bar and baz');
expect(actual).toEqual(expected);
});
test('should not nest same-level "or"', () => {
const expected = nodeTypes.function.buildNode('or', [
nodeTypes.function.buildNode('is', null, 'foo'),
nodeTypes.function.buildNode('is', null, 'bar'),
nodeTypes.function.buildNode('is', null, 'baz'),
]);
const actual = fromKueryExpression('foo or bar or baz');
expect(actual).toEqual(expected);
});
test('should support negation of queries with a "not" prefix', () => {
const expected = nodeTypes.function.buildNode(
'not',
@ -84,13 +104,11 @@ describe('kuery AST API', () => {
test('"and" should have a higher precedence than "or"', () => {
const expected = nodeTypes.function.buildNode('or', [
nodeTypes.function.buildNode('is', null, 'foo'),
nodeTypes.function.buildNode('or', [
nodeTypes.function.buildNode('and', [
nodeTypes.function.buildNode('is', null, 'bar'),
nodeTypes.function.buildNode('is', null, 'baz'),
]),
nodeTypes.function.buildNode('is', null, 'qux'),
nodeTypes.function.buildNode('and', [
nodeTypes.function.buildNode('is', null, 'bar'),
nodeTypes.function.buildNode('is', null, 'baz'),
]),
nodeTypes.function.buildNode('is', null, 'qux'),
]);
const actual = fromKueryExpression('foo or bar and baz or qux');
expect(actual).toEqual(expected);

View file

@ -27,18 +27,20 @@ start
OrQuery
= &{ return errorOnLuceneSyntax; } LuceneQuery
/ left:AndQuery Or right:OrQuery {
const cursor = [left, right].find(node => node.type === 'cursor');
/ head:AndQuery tail:(Or query:AndQuery { return query; })+ {
const nodes = [head, ...tail];
const cursor = nodes.find(node => node.type === 'cursor');
if (cursor) return cursor;
return buildFunctionNode('or', [left, right]);
return buildFunctionNode('or', nodes);
}
/ AndQuery
AndQuery
= left:NotQuery And right:AndQuery {
const cursor = [left, right].find(node => node.type === 'cursor');
= head:NotQuery tail:(And query:NotQuery { return query; })+ {
const nodes = [head, ...tail];
const cursor = nodes.find(node => node.type === 'cursor');
if (cursor) return cursor;
return buildFunctionNode('and', [left, right]);
return buildFunctionNode('and', nodes);
}
/ NotQuery
@ -139,28 +141,30 @@ ListOfValues
/ Value
OrListOfValues
= partialLeft:AndListOfValues Or partialRight:OrListOfValues {
const cursor = [partialLeft, partialRight].find(node => node.type === 'cursor');
= head:AndListOfValues tail:(Or partial:AndListOfValues { return partial; })+ {
const nodes = [head, ...tail];
const cursor = nodes.find(node => node.type === 'cursor');
if (cursor) {
return {
...cursor,
suggestionTypes: ['value']
};
}
return (field) => buildFunctionNode('or', [partialLeft(field), partialRight(field)]);
return (field) => buildFunctionNode('or', nodes.map(partial => partial(field)));
}
/ AndListOfValues
AndListOfValues
= partialLeft:NotListOfValues And partialRight:AndListOfValues {
const cursor = [partialLeft, partialRight].find(node => node.type === 'cursor');
= head:NotListOfValues tail:(And partial:NotListOfValues { return partial; })+ {
const nodes = [head, ...tail];
const cursor = nodes.find(node => node.type === 'cursor');
if (cursor) {
return {
...cursor,
suggestionTypes: ['value']
};
}
return (field) => buildFunctionNode('and', [partialLeft(field), partialRight(field)]);
return (field) => buildFunctionNode('and', nodes.map(partial => partial(field)));
}
/ NotListOfValues

View file

@ -981,132 +981,132 @@ describe('get_filter', () => {
['my custom index'],
[]
);
expect(esQuery).toEqual({
bool: {
must: [],
filter: [
{
bool: {
filter: [
{
bool: {
filter: [
{
bool: {
should: [{ match: { 'event.module': 'suricata' } }],
minimum_should_match: 1,
},
},
{
bool: {
should: [{ match: { 'event.kind': 'alert' } }],
minimum_should_match: 1,
},
},
],
},
},
{
bool: {
should: [
{
bool: {
should: [{ match: { 'suricata.eve.alert.signature_id': 2610182 } }],
minimum_should_match: 1,
},
},
{
bool: {
should: [
{
bool: {
should: [
{ match: { 'suricata.eve.alert.signature_id': 2610183 } },
],
minimum_should_match: 1,
expect(esQuery).toMatchInlineSnapshot(`
Object {
"bool": Object {
"filter": Array [
Object {
"bool": Object {
"filter": Array [
Object {
"bool": Object {
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"event.module": "suricata",
},
},
},
{
bool: {
should: [
{
bool: {
should: [
{ match: { 'suricata.eve.alert.signature_id': 2610184 } },
],
minimum_should_match: 1,
},
},
{
bool: {
should: [
{
bool: {
should: [
{
match: {
'suricata.eve.alert.signature_id': 2610185,
},
},
],
minimum_should_match: 1,
},
},
{
bool: {
should: [
{
bool: {
should: [
{
match: {
'suricata.eve.alert.signature_id': 2610186,
},
},
],
minimum_should_match: 1,
},
},
{
bool: {
should: [
{
match: {
'suricata.eve.alert.signature_id': 2610187,
},
},
],
minimum_should_match: 1,
},
},
],
minimum_should_match: 1,
},
},
],
minimum_should_match: 1,
},
},
],
minimum_should_match: 1,
},
},
],
minimum_should_match: 1,
],
},
},
},
],
minimum_should_match: 1,
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"event.kind": "alert",
},
},
],
},
},
],
},
},
},
],
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"suricata.eve.alert.signature_id": 2610182,
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"suricata.eve.alert.signature_id": 2610183,
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"suricata.eve.alert.signature_id": 2610184,
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"suricata.eve.alert.signature_id": 2610185,
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"suricata.eve.alert.signature_id": 2610186,
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"suricata.eve.alert.signature_id": 2610187,
},
},
],
},
},
],
},
},
],
},
},
},
],
should: [],
must_not: [],
},
});
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
}
`);
});
});

View file

@ -451,8 +451,8 @@ describe('Combined Queries', () => {
kqlQuery: { query: 'host.name: "host-1"', language: 'kuery' },
kqlMode: 'search',
})!;
expect(filterQuery).toEqual(
'{"bool":{"must":[],"filter":[{"bool":{"should":[{"bool":{"should":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 3"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 4"}}],"minimum_should_match":1}}]}}]}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 2"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 5"}}],"minimum_should_match":1}}]}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}],"minimum_should_match":1}}],"should":[],"must_not":[]}}'
expect(filterQuery).toMatchInlineSnapshot(
`"{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 1\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 3\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 4\\"}}],\\"minimum_should_match\\":1}}]}},{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 2\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 5\\"}}],\\"minimum_should_match\\":1}}]}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"host.name\\":\\"host-1\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}],\\"should\\":[],\\"must_not\\":[]}}"`
);
});
@ -469,8 +469,8 @@ describe('Combined Queries', () => {
kqlQuery: { query: 'host.name: "host-1"', language: 'kuery' },
kqlMode: 'filter',
})!;
expect(filterQuery).toEqual(
'{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 3"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 4"}}],"minimum_should_match":1}}]}}]}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 2"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 5"}}],"minimum_should_match":1}}]}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}'
expect(filterQuery).toMatchInlineSnapshot(
`"{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 1\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 3\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 4\\"}}],\\"minimum_should_match\\":1}}]}},{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 2\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"name\\":\\"Provider 5\\"}}],\\"minimum_should_match\\":1}}]}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"host.name\\":\\"host-1\\"}}],\\"minimum_should_match\\":1}}]}}],\\"should\\":[],\\"must_not\\":[]}}"`
);
});

View file

@ -365,27 +365,20 @@ describe('status check alert', () => {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"url.port": 5601,
},
},
],
"match": Object {
"url.port": 5601,
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"url.port": 443,
},
},
],
"match": Object {
"url.port": 443,
},
},
],
@ -396,14 +389,39 @@ describe('status check alert', () => {
},
Object {
"bool": Object {
"filter": Array [
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"observer.geo.name": "harrisburg",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"monitor.type": "http",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"observer.geo.name": "harrisburg",
"tags": "unsecured",
},
},
],
@ -411,67 +429,23 @@ describe('status check alert', () => {
},
Object {
"bool": Object {
"filter": Array [
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"monitor.type": "http",
},
},
],
"match": Object {
"tags": "containers",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"tags": "unsecured",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"tags": "containers",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"tags": "org:google",
},
},
],
},
},
],
},
},
],
"match_phrase": Object {
"tags": "org:google",
},
},
],
@ -761,7 +735,7 @@ describe('status check alert', () => {
expect(mockAvailability.mock.calls[0]).toMatchInlineSnapshot(`
Array [
Object {
"filters": "{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":12349}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":5601}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":443}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"observer.geo.name\\":\\"harrisburg\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"monitor.type\\":\\"http\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"unsecured\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"containers\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"tags\\":\\"org:google\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}]}}]}}]}}",
"filters": "{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":12349}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":5601}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":443}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"observer.geo.name\\":\\"harrisburg\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"monitor.type\\":\\"http\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"unsecured\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"containers\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"tags\\":\\"org:google\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}]}}",
"range": 35,
"rangeUnit": "d",
"threshold": "99.34",
@ -1071,46 +1045,32 @@ describe('status check alert', () => {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"observer.geo.name": "apj",
},
},
],
"match": Object {
"observer.geo.name": "apj",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"observer.geo.name": "sydney",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"observer.geo.name": "us-west",
},
},
],
},
},
],
"match": Object {
"observer.geo.name": "sydney",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"observer.geo.name": "us-west",
},
},
],