Use looping constructs in EC2 TOE
This section provides information to help you create looping constructs in the EC2 TOE. Looping constructs define a repeated sequence of instructions. You can use the following types of looping constructs in EC2 TOE:
-
for
constructs – Iterate over a bounded sequence of integers. -
forEach
constructs-
forEach
loop with input list – Iterates over a finite collection of strings. -
forEach
loop with delimited list – Iterates over a finite collection of strings joined by a delimiter.
-
Note
Looping constructs support only string data types.
Looping construct topics
Reference iteration variables
To refer to the index and value of the current iteration variable, the reference expression {{ loop.* }}
must be used within the input body of a step that contains a looping construct. This expression
cannot be used to refer to the iteration variables of the looping construct of another step.
The reference expression consists of the following members:
{{ loop.index }}
– The ordinal position of the current iteration, which is indexed at0
.{{ loop.value }}
– The value associated with the current iteration variable.
Loop names
All looping constructs have an optional name field for identification. If a loop
name is provided, it can be used to refer to iteration variables in the input body
of the step. To refer to the iteration indices and values of a named loop, use
{{ <loop_name>.* }}
with {{ loop.* }}
in the input
body of the step. This expression cannot be used to refer to the named looping
construct of another step.
The reference expression consists of the following members:
{{ <loop_name>.index }}
– The ordinal position of the current iteration of the named loop, which is indexed at0
.{{ <loop_name>.value }}
– The value associated with the current iteration variable of the named loop.
Resolve reference expressions
The EC2 TOE resolves reference expressions as follows:
{{ <loop_name>.* }}
– EC2 TOE resolves this expression using the following logic:If the loop of the currently running step matches the
<loop_name>
value, then the reference expression resolves to the looping construct of the currently running step.<loop_name>
resolves to the named looping construct if it appears within the currently running step.
{{ loop.* }}
– EC2 TOE resolves the expression using the looping construct defined in the currently running step.
If reference expressions are used within a step that does not contain a loop, then EC2 TOE does not resolve the expressions and they appear in the step with no replacement.
Note
Reference expressions must be enclosed in double quotes to be correctly interpreted by the YAML compiler.
Types of looping constructs
This section provides information and examples about looping construct types that can be used in the EC2 TOE.
Looping construct types
for
loop
The for
loop iterates on a range of integers specified within a boundary outlined by the
start and end of the variables. The iterating values are in the set [start, end]
and
includes boundary values.
EC2 TOE verifies the start
, end
, and updateBy
values to ensure that the
combination does not result in an infinite loop.
for
loop schema
- name: "StepName" action: "ActionModule" loop: name: "string" for: start: int end: int updateBy: int inputs: ...
Field | Description | Type | Required | Default |
---|---|---|---|---|
|
Unique name of the loop. It must be unique compared to other loop names in the same phase. |
String |
No |
"" |
|
Starting value of iteration. Does not accept chaining expressions. |
Integer |
Yes |
n/a |
|
Ending value of iteration. Does not accept chaining expressions. | Integer | Yes | n/a |
|
Difference by which an iterating value is updated through addition. It must be a negative or positive non-zero value. Does not accept chaining expressions. | Integer | Yes | n/a |
for
loop input example
- name: "CalculateFileUploadLatencies" action: "ExecutePowerShell" loop: for: start: 100000 end: 1000000 updateBy: 100000 inputs: commands: - | $f = new-object System.IO.FileStream c:\temp\test{{ loop.index }}.txt, Create, ReadWrite $f.SetLength({{ loop.value }}MB) $f.Close() - c:\users\administrator\downloads\latencyTest.exe --file c:\temp\test{{ loop.index }}.txt - Amazon s3 cp c:\users\administrator\downloads\latencyMetrics.json s3://bucket/latencyMetrics.json - | Remove-Item -Path c:\temp\test{{ loop.index }}.txt Remove-Item -Path c:\users\administrator\downloads\latencyMetrics.json
forEach
loop with input list
The forEach
loop iterates on an explicit list of values, which can be strings and
chained expressions.
forEach
loop with input list schema
- name: "StepName" action: "ActionModule" loop: name: "string" forEach: - "string" inputs: ...
Field | Description | Type | Required | Default |
---|---|---|---|---|
|
Unique name of the loop. It must be unique compared to other loop names in the same phase. |
String |
No |
"" |
List of strings of |
List of strings for iteration. Accepts chained expressions as strings in the list. Chained expressions must be enclosed by double quotes for the YAML compiler to correctly interpret them. |
List of strings |
Yes |
n/a |
forEach
loop with input list example 1
- name: "ExecuteCustomScripts" action: "ExecuteBash" loop: name: BatchExecLoop forEach: - /tmp/script1.sh - /tmp/script2.sh - /tmp/script3.sh inputs: commands: - echo "Count {{ BatchExecLoop.index }}" - sh "{{ loop.value }}" - | retVal=$? if [ $retVal -ne 0 ]; then echo "Failed" else echo "Passed" fi
forEach
loop with input list example 2
- name: "RunMSIWithDifferentArgs" action: "ExecuteBinary" loop: name: MultiArgLoop forEach: - "ARG1=C:\Users ARG2=1" - "ARG1=C:\Users" - "ARG1=C:\Users ARG3=C:\Users\Administrator\Documents\f1.txt" inputs: commands: path: "c:\users\administrator\downloads\runner.exe" args: - "{{ MultiArgLoop.value }}"
forEach
loop with input list example 3
- name: "DownloadAllBinaries" action: "S3Download" loop: name: MultiArgLoop forEach: - "bin1.exe" - "bin10.exe" - "bin5.exe" inputs: - source: "s3://bucket/{{ loop.value }}" destination: "c:\temp\{{ loop.value }}"
forEach
loop with delimited list
The loop iterates over a string containing values separated by a delimiter. To iterate over the string’s constituents, EC2 TOE uses the delimiter to split the string into an array suitable for iteration.
forEach
loop with delimited list schema
- name: "StepName" action: "ActionModule" loop: name: "string" forEach: list: "string" delimiter: ".,;:\n\t -_" inputs: ...
Field | Description | Type | Required | Default |
---|---|---|---|---|
|
Unique name given to the loop. It should be unique when compared to other loop names in the same phase. |
String |
No |
"" |
|
A string that is composed of constituent strings joined by a common delimiter character. Also accepts chained expressions. In case of chained expressions, ensure that those are enclosed by double quotes for correct interpretation by the YAML compiler. | String |
Yes |
n/a |
|
Character used to separate out strings within a block. Default is
the comma character. Only one delimiter character is allowed from
the given list:
Chaining expressions cannot be used. |
String | No | Comma: "," |
Note
The value of list
is treated as an immutable string. If the source of
list
is changed during runtime, it will not be reflected during
the run.
forEach
loop with delimited list example 1
This example uses the following chaining expression pattern to refer
to another step's output:
<phase_name>.<step_name>.[inputs | outputs].<var_name>
.
- name: "RunMSIs" action: "ExecuteBinary" loop: forEach: list: "{{ build.GetAllMSIPathsForInstallation.outputs.stdout }}" delimiter: "\n" inputs: commands: path: "{{ loop.value }}"
forEach
loop with delimited list example 2
- name: "UploadMetricFiles" action: "S3Upload" loop: forEach: list: "/tmp/m1.txt,/tmp/m2.txt,/tmp/m3.txt,..." inputs: commands: - source: "{{ loop.value }}" destination: "s3://bucket/key/{{ loop.value }}"
Step fields
Loops are part of a step. Any field related to the running of a step is not applied to individual iterations. Step fields apply only at the step level, as follows:
-
timeoutSeconds – All iterations of the loop must be run within the time period specified by this field. If the loop run times out, then EC2 TOE runs the retry policy of the step and resets the timeout parameter for each new attempt. If the loop run exceeds the timeout value after reaching the maximum number of retries, the failure message of the step states that the loop run had timed out.
-
onFailure – Failure handling is applied to the step as follows:
-
If onFailure is set to
Abort
, EC2 TOE exits the loop and retries the step according to the retry policy. After the maximum number of retry attempts, EC2 TOE marks the current step as failed, and stops running the process.EC2 TOE sets the status code for the parent phase and document to
Failed
.Note
No further steps run after the failed step.
-
If onFailure is set to
Continue
, EC2 TOE exits the loop and retries the step according to the retry policy. After the maximum number of retry attempts, EC2 TOE marks the current step as failed, and continues on to run the next step.EC2 TOE sets the status code for the parent phase and document to
Failed
. -
If onFailure is set to
Ignore
, EC2 TOE exits the loop and retries the step according to the retry policy. After the maximum number of retry attempts, EC2 TOE marks the current step asIgnoredFailure
, and continues on to run the next step.EC2 TOE sets the status code for the parent phase and document to
SuccessWithIgnoredFailure
.Note
This is still considered a successful run, but includes information to let you know that one or more steps failed and were ignored.
-
maxAttempts – For every retry, the entire step and all iterations are run from the beginning.
status – The overall status of the running of a step.
status
does not represent the status of individual iterations. The status of a step with loops is determined as follows:If a single iteration fails to run, the status of a step points to a failure.
If all iterations succeed, the status of a step points to a success.
startTime – The overall start time of the running of a step. Does not represent the start time of individual iterations.
endTime – The overall end time of the running of a step. Does not represent the end time of individual iterations.
failureMessage – Includes the iteration indices that failed in case of non-timeout errors. In case of timeout errors, the message states that the loop run has failed. Individual error messages for each iteration are not provided to minimize the size of failure messages.
Step and iteration outputs
Every iteration contains an output. At the end of a loop run, EC2 TOE consolidates all
successful iteration outputs in detailedOutput.json
. The consolidated
outputs are a collation of values that belong to the corresponding output keys as
defined in the output schema of the action module. The following example shows how the
outputs are consolidated:
Output of ExecuteBash
for Iteration 1
{ "stdout":"Hello" }
Output of ExecuteBash
for Iteration 2
{ "stdout":"World" }
Output of ExecuteBash
for Step
{ "stdout":"Hello\nWorld" }
For example, ExecuteBash
, ExecutePowerShell
, and
ExecuteBinary
are action modules which return STDOUT
as
the action module output. STDOUT
messages are joined with the new line
character to produce the overall output of the step in
detailedOutput.json
.
EC2 TOE will not consolidate the outputs of unsuccessful iterations.