Control Flow

sysopswork recommends the use of control flow in exceptional cases. Ideally the script must follow the implementation life cycle detailed at Implementation Life Cycle. Control flow creates an unnecessary complexity, but sometimes there is no alternative, therefore sysopswork provides this capability.

This page assumes some familiarity with common control flow used in programming languages.

There are 3 types of control flow statements in sysopswork:

  • IF … {…} ELSE IF … {…} ELSE {…}

  • WHILE … {…}

  • FOR EACH … IN … {…}

Although the statements above show the entire control flow block within the same line, you must have the initial statement in a single line, followed by all instructions within the block at separate lines, and finally the closing } also in an independent line. Remember that sysopswork processes instructions line-by-line.

Conditional

IF compares two values and if the result is logically true, sysopswork applies the instructions within respective {…} block. You can have one or more ELSE IF blocks to go through multiple evaluations. If IF test or an ELSE IF test is true, the rest of the ELSE IF, or ELSE will not be evaluated. In case you have an ELSE block, and none of the IF or ELSE IF tests is true, then sysopswork will apply the instruction within the ELSE block.

The conditional tests are:

  • variable IS EMPTY

  • variable IS NOT EMPTY

  • variable IS “value”

  • variable IS NOT “value”

  • variable IS GT “value”

  • variable IS NOT GT “value”

  • variable IS GE “value”

  • variable IS NOT GE “value”

  • variable IS LT “value”

  • variable IS NOT LT “value”

  • variable IS LE “value”

  • variable IS NOT LE “value”

variables are the variables explained at page Variables.

GT stands for greater than
GE stands for greater than or equal
LT stands for less than
LE stands for less than or equal

“value” must be enclosed within double quotes, even if it is a number.

Conditional tests with GT, GE, LT, or LE expects both variable and “value” to be a number. The other tests expects either string or number.

Some examples of IF … {…} ELSE IF … {…} ELSE {…} test syntax:

IF variable IS EMPTY {

}

IF variable IS "value" {

}

IF variable IS NOT "value" {

}

IF variable IS GT "value" {

} ELSE IF variable IS LT "value" {

} ELSE {

}

The value EMPTY without double quotes means the variable has no value at all. 0 or false does not count as EMPTY (this might be similar to an empty string, NULL or undefined in other programming languages).

Loop

WHILE loop takes same conditional tests as IF/ELSE IF/ELSE. Below is an example:

WHILE variable IS NOT "value" {

}

It continues to apply the instructions within the block while the result of the test evaluates to true.

FOR EACH loop runs one iteration per item within a list (details about lists can be found at Variables) and the syntax is:

FOR EACH local_variable IN list {

INSTRUCTION {{local_variable_value}}

}

FOR EACH loop iterates one item of the list at a time, starting at first and it ends after iteration with the last item of the list. There is no need to inform the item index on FOR EACH statement or within the block.

IMPORTANT: Instructions and/or sequence numbers cannot be variables. For example, the following line within FOR EACH block is INVALID:

STEPS = ("PREC", "IMPC", "POSTC")
FOR EACH STEP IN STEPS {
        1.{{STEP}}: command
        #DO NOT DO THIS! IT IS AN INVALID USAGE OF FOR EACH LOOP.
}

For REST/HTTP(S) requests, instructions REST-STEP: and REST-METHOD: cannot contain variables, neither HTTP header keys. For REST/HTTP(S) results, only the parameter “VALUE” can be a variable.

QUESTION: & ANSWER: instructions must be out of control flow blocks.

OBJECT: lines are scope based, unless it is the only line within a scope. Let me explain how this works. Let’s say you have the following lines:

OBJECT: host001
PREC: command1
IF VAR IS "VAL" {
        PREC: command2
}
PREC: command3

In this case, if IF condition is true, all commands will be applied to object host001. Otherwise only commands command1 and command3.

In the next case:

OBJECT: host001
1.PREC: command1
if VAR is "VAL" {
        OBJECT: host002
}
3.PREC: command3

As OBJECT: host002 is the only line within the IF block, if the IF condition is true, then host002 is used by 3.PREC, otherwise host001 is used.

However, in this other case:

OBJECT: host001
1.PREC: command1
if VAR is "VAL" {
        OBJECT: host002
        2.PREC: command2
}
3.PREC: command3

As OBJECT: host002 is not the only line within the IF block, if the IF condition is true, the instruction 2.PREC: command2 will be applied to host002, and 3.PREC: command3 will be applied to the previous object host001.

If you want 3.PREC: command3 to be applied to object host002, then you can enter the respective object after closing the block of the IF statement, as the following example shows:

OBJECT: host001
1.PREC: command1
if VAR is "VAL" {
        OBJECT: host002
        2.PREC: command2
}
OBJECT: host002
3.PREC: command3

Although the structure of this short script could be better written, it shows the objective of forcing the same object within the scope to also be used after the scope. To achieve same objective, the ideal script would look like the following:

OBJECT: host001
1.PREC: command1
OBJECT: host002
if VAR is "VAL" {
        2.PREC: command2
}
3.PREC: command3

IMPORTANT: As demonstrated above, be careful with OBJECT: lines within blocks. If used with another instruction within the block, the respecive OBJECT: is no longer used at the end of the block.

Although loop iterations can be nested, as mentioned at the top of the page, this unecessary complexity is strongly discouraged.

Altering Loop Behavior

Similar to most programming languages, sysopswork can alter WHILE and FOR EACH behavior with the use of BREAK or CONTINUE.

Those statements must be alone within a single line.

When sysopswork finds BREAK within a loop block, it exits the block by skipping any lines after it until the closing } of the respective block.

In the case of CONTINUE, sysopswork also skips any lines after it until the closing } of the respective block, however, the loop goes through the next iteration.