[Logstash] [PipelineViewer] Preserve all nested pipeline statements during graph conversion (#19101)
* Ensure all true/false statements are nested in IfStatements. * Simplify nested vertex diffing. * Rename get vertices function and test it. * Update tests, add more tests. * Update prompted by review feedback. * Update tests - add required props to provided objects. * Remove unneeded function/tests. * PR Cleanup.
This commit is contained in:
parent
72f0f5918b
commit
8425016e66
|
@ -40,18 +40,34 @@ export class IfVertex extends Vertex {
|
||||||
return this.outgoingEdges.find(e => e.when === true);
|
return this.outgoingEdges.find(e => e.when === true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get trueEdges() {
|
||||||
|
return this.outgoingEdges.filter(e => e.when === true);
|
||||||
|
}
|
||||||
|
|
||||||
get falseEdge() {
|
get falseEdge() {
|
||||||
return this.outgoingEdges.find(e => e.when === false);
|
return this.outgoingEdges.find(e => e.when === false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get falseEdges() {
|
||||||
|
return this.outgoingEdges.filter(e => e.when === false);
|
||||||
|
}
|
||||||
|
|
||||||
get trueOutgoingVertex() {
|
get trueOutgoingVertex() {
|
||||||
return this.trueEdge ? this.trueEdge.to : null;
|
return this.trueEdge ? this.trueEdge.to : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get trueOutgoingVertices() {
|
||||||
|
return this.trueEdges.map(e => e.to);
|
||||||
|
}
|
||||||
|
|
||||||
get falseOutgoingVertex() {
|
get falseOutgoingVertex() {
|
||||||
return this.falseEdge ? this.falseEdge.to : null;
|
return this.falseEdge ? this.falseEdge.to : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get falseOutgoingVertices() {
|
||||||
|
return this.falseEdges.map(e => e.to);
|
||||||
|
}
|
||||||
|
|
||||||
get next() {
|
get next() {
|
||||||
const trueDescendants = this.trueOutgoingVertex ? this.trueOutgoingVertex.descendants().vertices : [];
|
const trueDescendants = this.trueOutgoingVertex ? this.trueOutgoingVertex.descendants().vertices : [];
|
||||||
const falseDescendants = this.falseOutgoingVertex ? this.falseOutgoingVertex.descendants().vertices : [];
|
const falseDescendants = this.falseOutgoingVertex ? this.falseOutgoingVertex.descendants().vertices : [];
|
||||||
|
|
|
@ -49,6 +49,8 @@ describe('IfStatement class', () => {
|
||||||
esVertex.pipelineStage = 'output';
|
esVertex.pipelineStage = 'output';
|
||||||
|
|
||||||
ifVertex.trueOutgoingVertex = esVertex;
|
ifVertex.trueOutgoingVertex = esVertex;
|
||||||
|
ifVertex.trueOutgoingVertices = [ esVertex ];
|
||||||
|
ifVertex.falseOutgoingVertices = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates a IfStatement from vertex props', () => {
|
it('creates a IfStatement from vertex props', () => {
|
||||||
|
@ -88,6 +90,9 @@ describe('IfStatement class', () => {
|
||||||
|
|
||||||
ifVertex.trueOutgoingVertex = esVertex;
|
ifVertex.trueOutgoingVertex = esVertex;
|
||||||
ifVertex.falseOutgoingVertex = terminalVertex;
|
ifVertex.falseOutgoingVertex = terminalVertex;
|
||||||
|
|
||||||
|
ifVertex.trueOutgoingVertices = [ esVertex ];
|
||||||
|
ifVertex.falseOutgoingVertices = [ terminalVertex ];
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates a IfStatement from vertex props', () => {
|
it('creates a IfStatement from vertex props', () => {
|
||||||
|
@ -126,6 +131,8 @@ describe('IfStatement class', () => {
|
||||||
esVertex.pipelineStage = 'output';
|
esVertex.pipelineStage = 'output';
|
||||||
|
|
||||||
ifVertex.trueOutgoingVertex = esVertex;
|
ifVertex.trueOutgoingVertex = esVertex;
|
||||||
|
ifVertex.trueOutgoingVertices = [ esVertex ];
|
||||||
|
ifVertex.falseOutgoingVertices = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates a IfStatement from vertex props', () => {
|
it('creates a IfStatement from vertex props', () => {
|
||||||
|
@ -171,6 +178,9 @@ describe('IfStatement class', () => {
|
||||||
|
|
||||||
ifVertex.trueOutgoingVertex = esVertex;
|
ifVertex.trueOutgoingVertex = esVertex;
|
||||||
ifVertex.falseOutgoingVertex = terminalVertex;
|
ifVertex.falseOutgoingVertex = terminalVertex;
|
||||||
|
|
||||||
|
ifVertex.trueOutgoingVertices = [ esVertex ];
|
||||||
|
ifVertex.falseOutgoingVertices = [ terminalVertex ];
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates a IfStatement from vertex props', () => {
|
it('creates a IfStatement from vertex props', () => {
|
||||||
|
|
|
@ -1579,6 +1579,185 @@ describe('Pipeline class', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Pipeline with if having two nested output statements', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
graph = new Graph();
|
||||||
|
graph.update({
|
||||||
|
vertices: [
|
||||||
|
{
|
||||||
|
id: "the_if",
|
||||||
|
explicit_id: false,
|
||||||
|
type: "if",
|
||||||
|
condition: "[is_rt] == \"RT\"",
|
||||||
|
stats: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin_type: "output",
|
||||||
|
type: "plugin",
|
||||||
|
config_name: "stdout",
|
||||||
|
id: "plugin_1",
|
||||||
|
meta: {
|
||||||
|
source: {
|
||||||
|
line: 124,
|
||||||
|
protocol: "str",
|
||||||
|
id: "pipeline",
|
||||||
|
column: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
explicit_id: false,
|
||||||
|
stats: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin_type: "output",
|
||||||
|
type: "plugin",
|
||||||
|
config_name: "elasticsearch",
|
||||||
|
id: "plugin_2",
|
||||||
|
meta: {
|
||||||
|
source: {
|
||||||
|
line: 117,
|
||||||
|
protocol: "str",
|
||||||
|
id: "pipeline",
|
||||||
|
column: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
explicit_id: true,
|
||||||
|
stats: null
|
||||||
|
},
|
||||||
|
],
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
id: "35591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc5",
|
||||||
|
from: "the_if",
|
||||||
|
to: "plugin_1",
|
||||||
|
type: "boolean",
|
||||||
|
when: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc535",
|
||||||
|
from: "the_if",
|
||||||
|
to: "plugin_2",
|
||||||
|
type: "boolean",
|
||||||
|
when: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has two child statements', () => {
|
||||||
|
const pipeline = Pipeline.fromPipelineGraph(graph);
|
||||||
|
|
||||||
|
expect(pipeline.outputStatements.length).to.be(1);
|
||||||
|
const { trueStatements } = pipeline.outputStatements[0];
|
||||||
|
expect(trueStatements.length).to.be(2);
|
||||||
|
expect(trueStatements[0].id).to.be('plugin_1');
|
||||||
|
expect(trueStatements[1].id).to.be('plugin_2');
|
||||||
|
expect(pipeline.outputStatements[0].elseStatements.length).to.be(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Pipeline with if having two nested else statements', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
graph = new Graph();
|
||||||
|
graph.update({
|
||||||
|
vertices: [
|
||||||
|
{
|
||||||
|
id: "the_if",
|
||||||
|
explicit_id: false,
|
||||||
|
type: "if",
|
||||||
|
condition: "[is_rt] == \"RT\"",
|
||||||
|
stats: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin_type: "output",
|
||||||
|
type: "plugin",
|
||||||
|
config_name: "stdout",
|
||||||
|
id: "plugin_1",
|
||||||
|
meta: {
|
||||||
|
source: {
|
||||||
|
line: 124,
|
||||||
|
protocol: "str",
|
||||||
|
id: "pipeline",
|
||||||
|
column: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
explicit_id: false,
|
||||||
|
stats: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin_type: "output",
|
||||||
|
type: "plugin",
|
||||||
|
config_name: "elasticsearch",
|
||||||
|
id: "plugin_2",
|
||||||
|
meta: {
|
||||||
|
source: {
|
||||||
|
line: 117,
|
||||||
|
protocol: "str",
|
||||||
|
id: "pipeline",
|
||||||
|
column: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
explicit_id: true,
|
||||||
|
stats: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin_type: "output",
|
||||||
|
type: "plugin",
|
||||||
|
config_name: "stdout",
|
||||||
|
id: "plugin_3",
|
||||||
|
meta: {
|
||||||
|
source: {
|
||||||
|
line: 120,
|
||||||
|
protocol: "str",
|
||||||
|
id: "pipeline",
|
||||||
|
column: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
explicit_id: false,
|
||||||
|
stats: null
|
||||||
|
},
|
||||||
|
],
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
id: "35591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc5",
|
||||||
|
from: "the_if",
|
||||||
|
to: "plugin_1",
|
||||||
|
type: "boolean",
|
||||||
|
when: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc535",
|
||||||
|
from: "the_if",
|
||||||
|
to: "plugin_2",
|
||||||
|
type: "boolean",
|
||||||
|
when: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "637281923dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc5",
|
||||||
|
from: "the_if",
|
||||||
|
to: "plugin_3",
|
||||||
|
type: "boolean",
|
||||||
|
when: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has two child else statements', () => {
|
||||||
|
const pipeline = Pipeline.fromPipelineGraph(graph);
|
||||||
|
|
||||||
|
expect(pipeline.outputStatements.length).to.be(1);
|
||||||
|
const {
|
||||||
|
trueStatements,
|
||||||
|
elseStatements
|
||||||
|
} = pipeline.outputStatements[0];
|
||||||
|
expect(trueStatements.length).to.be(1);
|
||||||
|
expect(trueStatements[0].id).to.be('plugin_3');
|
||||||
|
expect(elseStatements.length).to.be(2);
|
||||||
|
expect(elseStatements[0].id).to.be('plugin_1');
|
||||||
|
expect(elseStatements[1].id).to.be('plugin_2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Pipeline with nested ifs', () => {
|
describe('Pipeline with nested ifs', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
graph = new Graph();
|
graph = new Graph();
|
||||||
|
|
|
@ -8,6 +8,16 @@ import { Statement } from './statement';
|
||||||
import { makeStatement } from './make_statement';
|
import { makeStatement } from './make_statement';
|
||||||
import { isVertexPipelineStage } from './utils';
|
import { isVertexPipelineStage } from './utils';
|
||||||
|
|
||||||
|
function makeStatementsForOutgoingVertices(outgoingVertices, statements, next, pipelineStage) {
|
||||||
|
outgoingVertices.forEach(vertex => {
|
||||||
|
let currentVertex = vertex;
|
||||||
|
while(isVertexPipelineStage(currentVertex, pipelineStage) && (currentVertex !== next)) {
|
||||||
|
statements.push(makeStatement(currentVertex, pipelineStage));
|
||||||
|
currentVertex = currentVertex.next;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export class IfStatement extends Statement {
|
export class IfStatement extends Statement {
|
||||||
constructor(vertex, trueStatements, elseStatements) {
|
constructor(vertex, trueStatements, elseStatements) {
|
||||||
super(vertex);
|
super(vertex);
|
||||||
|
@ -22,22 +32,15 @@ export class IfStatement extends Statement {
|
||||||
static fromPipelineGraphVertex(ifVertex, pipelineStage) {
|
static fromPipelineGraphVertex(ifVertex, pipelineStage) {
|
||||||
const trueStatements = [];
|
const trueStatements = [];
|
||||||
const elseStatements = [];
|
const elseStatements = [];
|
||||||
|
const {
|
||||||
|
trueOutgoingVertices,
|
||||||
|
falseOutgoingVertices
|
||||||
|
} = ifVertex;
|
||||||
|
|
||||||
const trueVertex = ifVertex.trueOutgoingVertex;
|
|
||||||
const falseVertex = ifVertex.falseOutgoingVertex;
|
|
||||||
const next = ifVertex.next;
|
const next = ifVertex.next;
|
||||||
|
|
||||||
let currentVertex = trueVertex;
|
makeStatementsForOutgoingVertices(trueOutgoingVertices, trueStatements, next, pipelineStage);
|
||||||
while (isVertexPipelineStage(currentVertex, pipelineStage) && (currentVertex !== next)) {
|
makeStatementsForOutgoingVertices(falseOutgoingVertices, elseStatements, next, pipelineStage);
|
||||||
trueStatements.push(makeStatement(currentVertex, pipelineStage));
|
|
||||||
currentVertex = currentVertex.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentVertex = falseVertex;
|
|
||||||
while (currentVertex && isVertexPipelineStage(currentVertex, pipelineStage) && (currentVertex !== next)) {
|
|
||||||
elseStatements.push(makeStatement(currentVertex, pipelineStage));
|
|
||||||
currentVertex = currentVertex.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IfStatement(
|
return new IfStatement(
|
||||||
ifVertex,
|
ifVertex,
|
||||||
|
|
Loading…
Reference in a new issue