Thomas Vachuska

Adding sequential construct to STC to serially chain sequences based on env properties.

Change-Id: I1df66d2a704309f5450eeca08a6e9b89c02e8346
1 +<!--
2 + ~ Copyright 2015 Open Networking Laboratory
3 + ~
4 + ~ Licensed under the Apache License, Version 2.0 (the "License");
5 + ~ you may not use this file except in compliance with the License.
6 + ~ You may obtain a copy of the License at
7 + ~
8 + ~ http://www.apache.org/licenses/LICENSE-2.0
9 + ~
10 + ~ Unless required by applicable law or agreed to in writing, software
11 + ~ distributed under the License is distributed on an "AS IS" BASIS,
12 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + ~ See the License for the specific language governing permissions and
14 + ~ limitations under the License.
15 + -->
16 +<scenario name="example" description="sequential scenario example">
17 + <group name="Wrapup">
18 + <!-- 'starts' is a comma-separated list of patterns that name steps starting the current iteration of the sequence -->
19 + <!-- 'ends' is a comma-separated list of patterns that name steps ending the previous iteration of the sequence -->
20 + <!-- In this example each Final-Check-Logs-(N) will become dependent on Fetch-Logs-(N-1), for N > 1 -->
21 + <sequential var="${OC#}" starts="Final-Check-Logs-${#}" ends="Fetch-Logs-${#-1}">
22 + <step name="Final-Check-Logs-${#}" exec="onos-check-logs ${OC#}"/>
23 + <step name="Fetch-Logs-${#}" exec="onos-fetch-logs ${OC#}"
24 + cwd="${WORKSPACE}/tmp/stc" requires="~^"/>
25 + </sequential>
26 + </group>
27 +</scenario>
...@@ -48,6 +48,7 @@ public class Compiler { ...@@ -48,6 +48,7 @@ public class Compiler {
48 private static final String GROUP = "group"; 48 private static final String GROUP = "group";
49 private static final String STEP = "step"; 49 private static final String STEP = "step";
50 private static final String PARALLEL = "parallel"; 50 private static final String PARALLEL = "parallel";
51 + private static final String SEQUENTIAL = "sequential";
51 private static final String DEPENDENCY = "dependency"; 52 private static final String DEPENDENCY = "dependency";
52 53
53 private static final String LOG_DIR = "[@logDir]"; 54 private static final String LOG_DIR = "[@logDir]";
...@@ -59,12 +60,16 @@ public class Compiler { ...@@ -59,12 +60,16 @@ public class Compiler {
59 private static final String IF = "[@if]"; 60 private static final String IF = "[@if]";
60 private static final String UNLESS = "[@unless]"; 61 private static final String UNLESS = "[@unless]";
61 private static final String VAR = "[@var]"; 62 private static final String VAR = "[@var]";
63 + private static final String STARTS = "[@starts]";
64 + private static final String ENDS = "[@ends]";
62 private static final String FILE = "[@file]"; 65 private static final String FILE = "[@file]";
63 private static final String NAMESPACE = "[@namespace]"; 66 private static final String NAMESPACE = "[@namespace]";
64 67
65 static final String PROP_START = "${"; 68 static final String PROP_START = "${";
66 static final String PROP_END = "}"; 69 static final String PROP_END = "}";
70 +
67 private static final String HASH = "#"; 71 private static final String HASH = "#";
72 + private static final String HASH_PREV = "#-1";
68 73
69 private final Scenario scenario; 74 private final Scenario scenario;
70 75
...@@ -72,7 +77,7 @@ public class Compiler { ...@@ -72,7 +77,7 @@ public class Compiler {
72 private final Map<String, Step> inactiveSteps = Maps.newHashMap(); 77 private final Map<String, Step> inactiveSteps = Maps.newHashMap();
73 private final Map<String, String> requirements = Maps.newHashMap(); 78 private final Map<String, String> requirements = Maps.newHashMap();
74 private final Set<Dependency> dependencies = Sets.newHashSet(); 79 private final Set<Dependency> dependencies = Sets.newHashSet();
75 - private final List<Integer> parallels = Lists.newArrayList(); 80 + private final List<Integer> clonables = Lists.newArrayList();
76 81
77 private ProcessFlow processFlow; 82 private ProcessFlow processFlow;
78 private File logDir; 83 private File logDir;
...@@ -175,6 +180,10 @@ public class Compiler { ...@@ -175,6 +180,10 @@ public class Compiler {
175 cfg.configurationsAt(PARALLEL) 180 cfg.configurationsAt(PARALLEL)
176 .forEach(c -> processParallelGroup(c, namespace, parentGroup)); 181 .forEach(c -> processParallelGroup(c, namespace, parentGroup));
177 182
183 + // Scan all sequential groups
184 + cfg.configurationsAt(SEQUENTIAL)
185 + .forEach(c -> processSequentialGroup(c, namespace, parentGroup));
186 +
178 // Scan all dependencies 187 // Scan all dependencies
179 cfg.configurationsAt(DEPENDENCY) 188 cfg.configurationsAt(DEPENDENCY)
180 .forEach(c -> processDependency(c, namespace)); 189 .forEach(c -> processDependency(c, namespace));
...@@ -309,14 +318,62 @@ public class Compiler { ...@@ -309,14 +318,62 @@ public class Compiler {
309 318
310 int i = 1; 319 int i = 1;
311 while (condition(var, i).length() > 0) { 320 while (condition(var, i).length() > 0) {
312 - parallels.add(0, i); 321 + clonables.add(0, i);
322 + compile(cfg, namespace, parentGroup);
323 + clonables.remove(0);
324 + i++;
325 + }
326 + }
327 +
328 + /**
329 + * Processes a sequential clone group directive.
330 + *
331 + * @param cfg hierarchical definition
332 + * @param namespace optional namespace
333 + * @param parentGroup optional parent group
334 + */
335 + private void processSequentialGroup(HierarchicalConfiguration cfg,
336 + String namespace, Group parentGroup) {
337 + String var = cfg.getString(VAR);
338 + String starts = cfg.getString(STARTS);
339 + String ends = cfg.getString(ENDS);
340 + print("sequential var=%s", var);
341 +
342 + int i = 1;
343 + while (condition(var, i).length() > 0) {
344 + clonables.add(0, i);
313 compile(cfg, namespace, parentGroup); 345 compile(cfg, namespace, parentGroup);
314 - parallels.remove(0); 346 + if (i > 1) {
347 + processSequentialRequirements(starts, ends, namespace);
348 + }
349 + clonables.remove(0);
315 i++; 350 i++;
316 } 351 }
317 } 352 }
318 353
319 /** 354 /**
355 + * Hooks starts of this sequence tier to the previous tier.
356 + *
357 + * @param starts comma-separated list of start steps
358 + * @param ends comma-separated list of end steps
359 + * @param namespace optional namespace
360 + */
361 + private void processSequentialRequirements(String starts, String ends,
362 + String namespace) {
363 + for (String s : split(starts)) {
364 + String start = expand(prefix(s, namespace));
365 + String reqs = requirements.get(s);
366 + for (String n : split(ends)) {
367 + boolean isSoft = n.startsWith("~");
368 + String name = n.replaceFirst("^~", "");
369 + name = (isSoft ? "~" : "") + expand(prefix(name, namespace));
370 + reqs = reqs == null ? name : (reqs + "," + name);
371 + }
372 + requirements.put(start, reqs);
373 + }
374 + }
375 +
376 + /**
320 * Returns the elaborated repetition construct conditional. 377 * Returns the elaborated repetition construct conditional.
321 * 378 *
322 * @param var repetition var property 379 * @param var repetition var property
...@@ -413,9 +470,11 @@ public class Compiler { ...@@ -413,9 +470,11 @@ public class Compiler {
413 String prop = pString.substring(start + PROP_START.length(), end); 470 String prop = pString.substring(start + PROP_START.length(), end);
414 String value; 471 String value;
415 if (prop.equals(HASH)) { 472 if (prop.equals(HASH)) {
416 - value = parallels.get(0).toString(); 473 + value = Integer.toString(clonables.get(0));
474 + } else if (prop.equals(HASH_PREV)) {
475 + value = Integer.toString(clonables.get(0) - 1);
417 } else if (prop.endsWith(HASH)) { 476 } else if (prop.endsWith(HASH)) {
418 - pString = pString.replaceFirst("#}", parallels.get(0).toString() + "}"); 477 + pString = pString.replaceFirst("#}", clonables.get(0) + "}");
419 last = start; 478 last = start;
420 continue; 479 continue;
421 } else { 480 } else {
......
...@@ -69,8 +69,8 @@ public class CompilerTest { ...@@ -69,8 +69,8 @@ public class CompilerTest {
69 ProcessFlow flow = compiler.processFlow(); 69 ProcessFlow flow = compiler.processFlow();
70 70
71 assertSame("incorrect scenario", scenario, compiler.scenario()); 71 assertSame("incorrect scenario", scenario, compiler.scenario());
72 - assertEquals("incorrect step count", 24, flow.getVertexes().size()); 72 + assertEquals("incorrect step count", 33, flow.getVertexes().size());
73 - assertEquals("incorrect dependency count", 16, flow.getEdges().size()); 73 + assertEquals("incorrect dependency count", 26, flow.getEdges().size());
74 assertEquals("incorrect logDir", 74 assertEquals("incorrect logDir",
75 new File(TEST_DIR.getAbsolutePath(), "foo"), compiler.logDir()); 75 new File(TEST_DIR.getAbsolutePath(), "foo"), compiler.logDir());
76 76
......
...@@ -44,4 +44,11 @@ ...@@ -44,4 +44,11 @@
44 <step name="ding-${#}" exec="asdads" requires="ping-${#},pong-${#}"/> 44 <step name="ding-${#}" exec="asdads" requires="ping-${#},pong-${#}"/>
45 <dependency name="maybe" requires="ding-${#}"/> 45 <dependency name="maybe" requires="ding-${#}"/>
46 </parallel> 46 </parallel>
47 +
48 + <sequential var="${TOC#}" requires="alpha" starts="fifi-${#},gigi-${#}" ends="gaga-${#-1}">
49 + <step name="fifi-${#}" exec="asdads ${TOC#}"/>
50 + <step name="gigi-${#}" exec="asdads"/>
51 + <step name="gaga-${#}" exec="asdads" requires="fifi-${#},gigi-${#}"/>
52 + <dependency name="maybe" requires="gaga-${#}"/>
53 + </sequential>
47 </scenario> 54 </scenario>
...\ No newline at end of file ...\ No newline at end of file
......