Branching and Looping

This section describes:

Branching
Looping

Branching

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.

Looping

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.

While Loops

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

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).

Map Loops

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.