Branching and Looping
• | Branching |
• | Looping |
Branching is done using the customary if keyword. This keyword marks the beginning of a block (like sub). It must be followed by an expression that must resolve to a value. If the value is false or null, then the expressions in the block are skipped; otherwise they are executed sequentially.
@server = rs_cm.get(href: "/api/servers/123")
if @server.state == "operational"
@server.terminate()
end
Cloud Workflow Language also supports the else keyword with the usual meaning:
@server = rs_cm.get(href: "/api/servers/123")
if @server.state == "operational"
@server.terminate()
else
if @server.state == "terminated"
@server.launch()
end
end
Finally, Cloud Workflow Language also supports the elsif keyword which can be used to write the example above more succinctly:
@server = rs_cm.get(href: "/api/servers/123")
if @server.state == "operational"
@server.terminate()
elsif @server.state == "terminated"
@server.launch()
end
This notation is especially useful to chain multiple tests without having to keep indenting the code.
There are three different kinds of loops:
• | While Loops allow repeating a block until a given condition is met. |
• | Foreach Loops allow iterating over a resource collection, a range, or an array of values. |
• | Map Loops are also an iterator, but they return one or more collection(s) built from the elements of the initial collection. |
The while keyword marks the beginning of a block. It must be followed by an expression that resolves to a value. The sub-expressions are executed until the value resolves to false or null:
# Assumes $app_servers_count, $app_server_definition and $server_name have previously been defined
$count = 0
while $count < $app_servers_count do
@server = rs_cm.server.create({ "name": $server_name + "_" + $count } + $app_server_definition)
@server.launch()
$count = $count + 1
end
This example will loop $app_servers_count times and in each iteration will create a server using a given set of arguments and launch it. The + operator applied to hashes returns a hash built from merging the left hand side of the operator into the right hand side. The same operator following a string concatenates the string with the right hand side value (a string or an integer). So the loop body in the example above will override the name used to create the server using a common prefix and the index as suffix.
Foreach loops allow iterating over either a resource collection, a range, or an array of values. The syntax is:
@servers = rs_cm.get(href: "/api/deployments/123").servers()
$recipes = ["cassandra::default", "cassandra::configure", "cassandra::restart"]
foreach $recipe in $recipes do
@servers.run_executable(recipe_name: $recipe)
end
@deployment = rs_cm.get(href: "/api/deployments/123")
foreach $name in ["clone-1".."clone-3"] do
@deployment.clone(deployment: { name: $name })
end
As mentioned above, foreach also allows iterating through collections as in:
@servers = rs_cm.get(href: "/api/deployments/123").servers()
foreach @server in @servers do
call audit_server(@server.name)
end
Note:A cloud workflow always acts on resource collections. The elements returned by foreach are thus collections themselves (albeit made of a single resource).
The map iterator constructs a new collection by iterating over an existing collection and applying a transformation to each element. The full form of the map iterator is fairly flexible and can iterate over a collection, a range, or an array of values, and it can construct one or multiple collections or arrays of values. The example below shows it iterating over the @servers collection and producing a $states array of values and @instances collection.
The map iterator follows the same syntax as the foreach operator, but adds a return keyword used to specify which variable(s) or reference(s) from the inner block should be used to build the resulting arrays(s)/collection(s).
@servers = rs_cm.get(href: "/api/deployments/123").servers()
$states, @instances = map @server in @servers return $state, @instance do
$state = @server.state
if $state == "stopped"
@instance = @server.launch()
else
@instance = @server.current_instance()
end
end
The above code creates two collections: the resource collection @instances and an the array $states. The @instances resource collection gets built by appending the content of @instance at the end of each iteration. Similarly, $states gets built by appending the value of $state at the end of each iteration. If a reference or a variable specified after return does not get defined in the execution of an iteration, then nothing is appended to the corresponding resulting collection.