CloudSlang is a YAML (version 1.2) based language for describing a workflow. Using CloudSlang you can easily define a workflow in a structured, easy-to-understand format that can be run by the CloudSlang Orchestration Engine (Score). CloudSlang files can be run by the :doc:`CloudSlang CLI <cloudslang_cli>` or by an embedded instance of Score using the :ref:`Slang API <slang_api>`.
This reference begins with a brief introduction to CloudSlang files and their structure, then continues with a brief explanation of CloudSlang expressions and variable contexts. Finally, there are alphabetical listings of the CloudSlang keywords and functions. See the :doc:`examples <cloudslang_examples>` section for the full code examples from which many of the code snippets in this reference are taken.
CloudSlang files are written using YAML. The recommended extension for CloudSlang flow and operation file names is .sl, but .sl.yaml and .sl.yml will work as well. CloudSlang system properties file names end with the .prop.sl extension.
Since CloudSlang is YAML-based, proper indentation is crucial. For more information, see the :ref:`YAML Overview <indentation_scoping>`.
There are four types of CloudSlang files:
- flow - contains a list of steps and navigation logic that calls operations or subflows
- operation - contains an action that runs a script or method
- decision - contains decision logic without an action
- system properties - contains a list of system property keys and values
The following properties are for all types of CloudSlang files. For properties specific to flow, operation, or system properties files, see their respective sections below.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
namespace |
no | -- | string | namespace
of the file
|
namespace |
imports |
no | -- | list of
key:value pairs
|
files to import | imports |
extensions |
no | -- | -- | information to be
ignored by the compiler
|
extensions |
Variable names in CloudSlang files cannot contain localized characters. In general, CloudSlang variable names must conform to both Python's naming constraints as well as Java's naming constraints.
Inputs, outputs, results, publish values, fully qualified system properties and fully qualified executable names must be unique and are validated as case insensitive. When using any of the above, they must be referred to using the case in which they were declared.
When using the CLI or Build Tool, CloudSlang will use the encoding found in the :ref:`CLI configuration file <configure_cli>` or :ref:`Build Tool configuration file <configure_build_tool>` for input values respectively. If no encoding is found in the configuration file, the CLI or Build Tool will use UTF-8.
The general structure of CloudSlang files is outlined here. Some of the properties that appear are optional. All CloudSlang keywords, properties and concepts are explained in detail below.
Flow file
Operation file
Decision file
System properties file
Many CloudSlang keys map to either an expression or literal value.
Literal values are denoted as they are in standard YAML. Numbers are interpreted as numerical values and strings may be written unquoted, single quoted or double quoted.
Example: literal values
literal_number: 4
literal_unquoted_string: cloudslang
literal_single_quoted_string: 'cloudslang'
literal_double_quoted_string: "cloudslang"
Note
Where expressions are allowed as values (input defaults, output and result values, etc.) and a literal string value is being used, you are encouraged to use a quoted style of literal string.
Example: recommended style for literal strings
flow:
name: flow_name #expression not allowed - unquoted literal string
workflow:
- step1:
do:
print:
- text: "hello" #expression allowed - quoted literal string
Expressions are preceded by a dollar sign ($
) and enclosed in curly brackets
({}
).
Example: expressions
- expression_1: ${4 + 7}
- expression_2: ${some_input}
- expression_3: ${get('input1', 'default_input')}
Expressions that contain characters that are considered special characters in
YAML must be enclosed in quotes or use YAML block notation. If using quotes, use
the style of quotes that are not already used in the expression. For example, if
your expression contains single quotes ('
), enclose the expression using
double quotes ("
).
Example: escaping special characters
- expression1: "${var1 + ': ' + var2}"
- expression2: >
${var1 + ': ' + var2}
- expression3: |
${var1 + ': ' + var2}
To pass a map where an expression is allowed use the default property.
Example: passing a map using the default property
- map1:
default: {a: 1, b: c}
- map2:
default: {'a key': 1, b: c}
It is also possible to use two sets of quotes and an expression marker, but the approach detailed above is the recommended one.
Example: passing a map using the expression marker and quotes
- map3: "${{'a key': 1, 'b': 'c'}}"
- map4: >
${{'a key': 1, 'b': 'c'}}
Throughout the execution of a flow, its steps, operations, decisions and subflows there are different variable contexts that are accessible. Which contexts are accessible depends on the current section of the flow, operation or decision.
The table below summarizes the accessible contexts at any given location in a flow, operation or decision.
Contexts/
Location
|
Context
Passed To
Executable
|
Flow
Context
|
Operation/
Decision
Context
|
Action
Outputs
Context
|
Subflow/
Operation/
Outputs
Context
|
Step
Arguments
|
Branched
Step
Output
Values
|
Already
Bound
Values
|
---|---|---|---|---|---|---|---|---|
flow
inputs
|
Yes | Yes | ||||||
flow
outputs
|
Yes | Yes | ||||||
operation/
decision
inputs
|
Yes | Yes | ||||||
operation/
decision
outputs
|
Yes | Yes | Yes | |||||
operation/
decision
results
|
Yes | Yes | ||||||
step
arguments
|
Yes | Yes | ||||||
step
publish
|
Yes | Yes | Yes - using
branches_context
|
Yes | ||||
step
navigation
|
Yes | Yes | ||||||
action
inputs
|
Yes |
May appear in the publish section of a parallel step.
As branches of a parallel_loop complete, values that have
been output and the branch's result get placed as a dictionary into the
branches_context
list. The list is therefore in the order the
branches have completed.
A specific value can be accessed using the index representing its branch's place in the finishing order and the name of the variable or the branch_result key.
Example - retrieves the name variable from the first branch to finish
publish:
- first_name: ${branches_context[0]['name']}
More commonly, the branches_context
is used to aggregate the values
that have been published by all of the branches.
Example - aggregates name values into a list
publish:
- name_list: ${map(lambda x:str(x['name']), branches_context)}
May appear in the publish section of a parallel step.
As branches of a parallel_loop complete, branch results get
placed into the branches_context list under the
branch_result
key.
Example - aggregates branch results
publish:
- branch_results_list: ${map(lambda x:str(x['branch_result']), branches_context)}
The key break
is a property of a loop. It is mapped to a
list of results on which to break out of the loop or an empty list
([]
) to override the default breaking behavior for a list. When the
operation or subflow of the iterative
step returns a result in the break's list, the
iteration halts and the iterative step's
navigation logic is run.
If the break
property is not defined, the loop will break on results
of FAILURE
by default. This behavior may be overriden so that
iteration will continue even when a result of FAILURE
is returned by
defining alternate break behavior or mapping the break
key to an
empty list ([]
).
Example - loop that breaks on result of CUSTOM
loop:
for: value in range(1,7)
do:
custom_op:
- text: ${value}
break:
- CUSTOM
navigate:
- CUSTOM: print_end
Example - loop that continues even on result of FAILURE
loop:
for: value in range(1,7)
do:
custom_op:
- text: ${value}
break: []
The key class_name
is a property of a java_action. It is
mapped to the name of the Java class where an annotated @Action resides.
The key decision
is mapped to the properties which make up the
decision contents.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
name |
yes | -- | string | name of the
decision
|
name |
inputs |
no | -- | list | decision inputs | inputs |
outputs |
no | -- | list | decision outputs | outputs |
results |
yes | -- | list | possible decision
results
|
results |
Example - decision that compares two values
decision:
name: compare
inputs:
- x
- y
outputs:
- sum: ${x+y}
results:
- EQUAL: ${x == y}
- LESS_THAN: ${x < y}
- GREATER_THAN
The key default
is a property of an input name. It is
mapped to an expression value.
The expression's value will be passed to the flow or
operation if no other value for that
input parameter is explicitly passed or if the input's
private parameter is set to true
.
Example - default values
inputs:
- str_literal:
default: "default value"
- int_exp:
default: ${5 + 6}
- from_variable:
default: ${variable_name}
- from_system_property:
default: $ { get_sp('system.property.key') }
A default value can also be defined inline by entering it as the value mapped to the input parameter's key.
Example - inline default values
inputs:
- str_literal: "default value"
- int_exp: ${5 + 6}
- from_variable: ${variable_name}
- from_system_property: $ { get_sp('system.property.key') }
The key do
is a property of a step name, a
loop, or a parallel_loop. It is mapped to a
property that references an operation or
flow.
Calls an operation or flow and passes in relevant arguments.
The operation or flow may be called in several ways:
- by referencing the operation or flow by name when it is in the default namespace (the same namespace as the calling flow)
- by using a fully qualified name, for example,
path.to.operation.op_name
- a path is recognized as a fully qualified name if the prefix
(before the first
.
) is not a defined alias
- a path is recognized as a fully qualified name if the prefix
(before the first
- by using an alias defined in the flow's imports
section followed by the operation or
flow name (e.g
alias_name.op_name
) - by using an alias defined in the flow's imports
section followed by a continuation of the path to the
operation or flow and its name (e.g
alias_name.path.cont.op_name
)
For more information, see the :ref:`Operation Paths <example_operation_paths>` example.
Arguments are passed to a step using a list of argument names and optional mapped expressions. The step must pass values for all inputs found in the called operation or subflow that are required and don't have a default value. Argument names should be different than the output names found in the operation or subflow being called in the step.
Argument names must conform to the rules for valid :ref:`variable names <variable_names>`.
An argument name without an expression, or with a null
value will take its
value from a variable with the same name in the flow context.
Expression values will supersede values bound to flow
inputs with the same name. To force the operation
or subflow being called to use it's own default value, as opposed to
a value passed in via expression or the flow context, omit the variable from the
calling step's argument list.
For a list of which contexts are available in the arguments section of a step, see Contexts.
Example - call to a divide operation with list of mapped step arguments
do:
divide:
- dividend: ${input1}
- divisor: ${input2}
Example - force an operation to use default value for punctuation input
flow:
name: flow
inputs:
- punctuation: "!"
workflow:
- step1:
do:
punc_printer:
- text: "some text"
#- punctuation
#commenting out the above line forces the operation to use its default value (".")
#leaving it in would cause the operation to take the value from the flow context ("!")
operation:
name: operation
inputs:
- text
- punctuation: "."
python_action:
script: |
print text + punctuation
The key extensions
is mapped to information that the compiler will ignore
and can therefore be used for various purposes.
Example - a flow that contains an extensions section
namespace: examples.extensions
flow:
name: flow_with_extensions_tag
workflow:
- noop_step:
do:
noop: []
extensions:
- some_key:
a: b
c: d
- another
The key flow
is mapped to the properties which make up the flow
contents.
A flow is the basic executable unit of CloudSlang. A flow can run on its own or it can be used by another flow in the do property of a step.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
name |
yes | -- | string | name of the flow | name |
inputs |
no | -- | list | inputs for the flow | inputs |
workflow |
yes | -- | list of steps | container for
workflow steps
|
workflow |
outputs |
no | -- | list | list of outputs | outputs |
results |
no | (
SUCCESS /FAILURE ) |
list | possible results
of the flow
|
results |
Example - a flow that performs a division of two numbers
flow:
name: division
inputs:
- input1
- input2
workflow:
- divider:
do:
divide:
- dividend: ${input1}
- divisor: ${input2}
publish:
- answer: ${quotient}
navigate:
- ILLEGAL: ILLEGAL
- SUCCESS: printer
- printer:
do:
print:
- text: ${input1 + "/" + input2 + " = " + answer}
navigate:
- SUCCESS: SUCCESS
outputs:
- quotient: ${answer}
results:
- ILLEGAL
- SUCCESS
The key for
is a property of a loop or an
parallel_loop.
A for loop iterates through a list or a map.
The iterative step will run once for each element in the list or key in the map.
When iterating through a list, the for
key is mapped to an iteration
variable followed by in
followed by a list, an expression that
evaluates to a list, or a comma delimited string.
Example - loop that iterates through the values in a list
- print_values:
loop:
for: value in [1,2,3]
do:
print:
- text: ${value}
Example - loop that iterates through the values in a comma delimited string
- print_values:
loop:
for: value in "1,2,3"
do:
print:
- text: ${value}
Example - loop that iterates through the values returned from an expression
- print_values:
loop:
for: value in range(1,4)
do:
print:
- text: ${value}
When iterating through a map, the for
key is mapped to iteration
variables for the key and value followed by in
followed by a map or
an expression that evaluates to a map.
Example - step that iterates through the values returned from an expression
- print_values:
loop:
for: k, v in map
do:
print2:
- text1: ${k}
- text2: ${v}
A parallel for loop loops in parallel branches over the items in a list.
The parallel step will run one branch for each element in the list.
The for
key is mapped to an iteration variable followed by in
followed by a list or an expression that evaluates to a list.
Example - step that loops in parallel through the values in a list
- print_values:
parallel_loop:
for: value in values_list
do:
print_branch:
- ID: ${value}
The key gav
is a property of a java_action. It is
mapped to the group:artifact:version
of the Maven project in which an
annotated Java @Action resides.
Upon operation execution, the Maven project and all the
required resources specified in its pom's dependencies
will be resolved and
downloaded (if necessary).
Example - referencing Maven artifact using gav
java_action:
gav: io.cloudslang.content:score-xml:0.0.2
class_name: io.cloudslang.content.mail.actions.SendMailAction
method_name: execute
The key imports
is mapped to the files to import as follows:
- key - alias
- value - namespace of file to be imported
Specifies the file's dependencies, operations and subflows, by the namespace defined in their source file and the aliases they will be referenced by in the file.
Using an alias is one way to reference the operations and subflows used in a flow's steps. For all the ways to reference operations and subflows used in a flow's steps, see the do keyword and the :ref:`Operation Paths example <example_operation_paths>`.
Example - import operations and sublflow into flow
imports:
ops: examples.utils
subs: examples.subflows
flow:
name: hello_flow
workflow:
- print_hi:
do:
ops.print:
- text: "Hi"
- run_subflow:
do:
subs.division:
- input1: "5"
- input2: "3"
In this example, the ops
alias refers to the `examples.utils
namespace.
This alias is used in the print_hi
step to refer to the print
operation,
whose source file defines its namespace as examples.utils
. Similarly, the
subs
alias refers to the examples.subflows
namespace. The subs
alias
is used in the run_subflow
step to refer to the division
subflow, whose
source file defines its namespace as examples.subflows
.
The key inputs
is a property of a flow,
operation or decision. It is mapped to a list
of input names. Each input name may in turn be mapped to its properties or an
input expression.
Inputs are used to pass parameters to flows, operations or decisions. Input names for a specific flow, operation or decision must be different than the output names of the same flow, operation or decision.
For a list of which contexts are available in the inputs
section of a
flow, operation or decision, see
Contexts.
Input names must conform to the rules for valid :ref:`variable names <variable_names>` and :ref:`uniqueness <uniqueness_and_case_sensitivity>`.
Property | Required | Default | Value Type | Description | More info |
---|---|---|---|---|---|
required |
no | true | boolean | is the input
required
|
required |
default |
no | -- | expression | default value
of the input
|
default |
private |
no | false | boolean | if true, the
default value
always overrides
values passed in
|
private |
sensitive |
no | transitive
sensitivity
or false
|
boolean | is the input
sensitive
|
sensitive |
Example - several inputs
inputs:
- input1:
default: "default value"
private: true
- input2
- input3: "default value"
- input4: ${'var1 is ' + var1}
- password:
sensitive: true
The key java_action
is a property of an operation. It is
mapped to the properties that define where an annotated Java @Action resides.
Property | Required | Default | Value Type | Description | More info |
---|---|---|---|---|---|
gav |
yes | -- | string | group:artifact:version | gav |
class_name |
yes | -- | string | fully qualified
Java class name
|
class_name |
method_name |
no | -- | string | Java method name | method_name |
Example - CloudSlang call to a Java action
namespace: io.cloudslang.base.mail
operation:
name: send_mail
inputs:
- hostname
- port
- from
- to
- subject
- body
java_action:
gav: io.cloudslang.content:score-xml:0.0.2
class_name: io.cloudslang.content.mail.actions.SendMailAction
method_name: execute
results:
- SUCCESS: ${ returnCode == '0' }
- FAILURE
There are many existing Java actions which are bundled with the :doc:`CloudSlang CLI <cloudslang_cli>`. The source code for these Java actions can be found in the score-actions repository.
To add a new Java action:
Create a Java method that conforms to the signature
public Map<String, String> doSomething(paramaters)
and use the following
annotations from com.hp.oo.sdk.content.annotations
:
@Action: specifies action information
- name: name of the action
- outputs: array of
@Output
annotations- responses: array of
@Response
annotations@Output: action output name
@Response: action response
- text: name of the response
- field: result to be checked
- value: value to check against
- matchType: type of check
- responseType: type of response
- isDefault: whether or not response is the default response
- isOnFail: whether or not response is the failure response
@Param: action parameter
- value: name of the parameter
- required: whether or not the parameter is required
Values are passed to a Java action from an operation using CloudSlang inputs that match the annotated parameters.
Values are passed back from the Java action to an operation using the returned
Map<String, String>
, where the map's elements each correspond to a name:value
that matches a CloudSlang output.
Example - Java action
package com.example.content.actions;
import com.hp.oo.sdk.content.annotations.Action;
import com.hp.oo.sdk.content.annotations.Output;
import com.hp.oo.sdk.content.annotations.Param;
import com.hp.oo.sdk.content.annotations.Response;
import com.hp.oo.sdk.content.plugin.ActionMetadata.MatchType;
import java.util.Map;
import java.util.HashMap;
public class SaySomething {
@Action(name = "Example Test Action",
outputs = {
@Output("message")
},
responses = {
@Response(text = "success", field = "message", value = "fail", matchType = MatchType.COMPARE_NOT_EQUAL),
@Response(text = "failure", field = "message", value = "fail", matchType = MatchType.COMPARE_EQUAL, isDefault = true, isOnFail = true)
}
)
public Map<String, String> speak(@Param(value = "text", required = true) String text) {
Map<String, String> results = new HashMap<>();
System.out.println("I say " + text);
results.put("message", text);
return results;
}
}
Use Maven to package the project containing the Java action method and release it to the remote repository defined in the :ref:`CLI's configuration file <configure_cli>`.
Below is an example pom.xml file that can be used for your Maven project.
Example - sample pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.content</groupId>
<artifactId>action-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>${project.groupId}:${project.artifactId}</name>
<description>Test Java action</description>
<dependencies>
<dependency>
<groupId>com.hp.score.sdk</groupId>
<artifactId>score-content-sdk</artifactId>
<version>1.10.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Reference your Maven artifact using the gav key in the java_action section of your operation.
Upon the operation's first execution, the Maven project and all
the required resources specified in its pom's dependencies
will be resolved
and downloaded.
The key loop
is a property of an iterative
step's name. It is mapped to the iterative
step's properties.
For each value in the loop's list the do
will run an
operation or subflow. If the returned
result is in the break
list, or if break
does not appear and the
returned result is FAILURE
, or if the list has been exhausted, the
step's navigation will run.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
for |
yes | -- | variable in list |
iteration logic | for |
do |
yes | -- | operation or
subflow call
|
the operation or
subflow this step
will run iteratively
|
|
publish |
no | -- | list of
key:value pairs
|
operation or subflow
outputs to aggregate and
publish to the flow level
|
|
break |
no | -- | list of results | break |
Example: loop that breaks on a result of custom
- custom3:
loop:
for: value in "1,2,3,4,5"
do:
custom3:
- text: ${value}
break:
- CUSTOM
navigate:
- CUSTOM: aggregate
- SUCCESS: skip_this
The key method_name
is a property of a java_action. It is
mapped to the name of the Java method where an annotated @Action resides.
The key name
is a property of flow,
operation or decision. It is mapped to a value
that is used as the name of the flow or operation.
The name of a flow, operation or decision may be used when called from a flow's step.
The name of a flow, operation or decision must match the name of the file in which it resides, excluding the extension.
The name must conform to the rules for :ref:`uniqueness <uniqueness_and_case_sensitivity>`.
Example - naming the flow found in the file division_flow.sl
name: division_flow
The key namespace
is mapped to a string value that defines the
file's namespace.
The namespace of a file may be used by a flow to import dependencies.
Example - definition a namespace
namespace: examples.hello_world
Example - using a namespace in an imports definition
imports:
ops: examples.hello_world
For more information about choosing a file's namespace, see the :ref:`CloudSlang Content Best Practices <cloudslang_content_best_practices>` section.
Note
If the imported file resides in a folder that is different
from the folder in which the importing file resides, the imported file's
directory must be added using the --cp
flag when running from the
CLI (see :ref:`Run with Dependencies <run_with_dependencies>`).
The key navigate
is a property of a step name. It is
mapped to a list of key:value pairs where the key is the received
result and the value is the target step,
flow result or on_failure
.
Defines the navigation logic for a standard step, an iterative step or a parallel step. The flow will continue with the step or flow result whose value is mapped to the result returned by the called operation or subflow.
By default, if no navigate
section navigation is present, the flow continues
with the next step or navigates to the SUCCESS
result of the
flow if the step is the final non-on_failure step. The
on_failure step always navigates to the FAILURE
result of the flow. For more information, see the
:ref:`Default Navigation <example_default_navigation>` example.
All possible results returned by the called operation or subflow must be handled.
For a standard step the navigation logic runs when the step is completed.
For an iterative step the navigation logic runs when the last iteration of the step is completed or after exiting the iteration due to a break.
For a parallel step the navigation logic
runs after the last branch has completed. If any of the branches
returned a result of FAILURE
, the flow
will navigate to the step or flow
result mapped to FAILURE
. Otherwise, the
flow will navigate to the step or
flow result mapped to SUCCESS
. Note that
the only results of an operation or
subflow called in a parallel_loop that are
evaluated are SUCCESS
and FAILURE
. Any other results will be
evaluated as SUCCESS
.
For a list of which contexts are available in the navigate
section of a
step, see Contexts.
Example - ILLEGAL result will navigate to flow's FAILURE result and SUCCESS result will navigate to step named 'printer'
navigate:
- SUCCESS: printer
- ILLEGAL: ILLEGAL
- FAILURE: on_failure
The key on_failure
is a property of a workflow. It
is mapped to a step.
Defines the step, which when using default
navigation, is the target of a FAILURE
result returned from an operation or
flow. The on_failure
step can also be reached by
mapping one of a step's navigation keys to
on_failure
. If a step's navigation explicitly
maps to on_failure
, but there is no on_failure
step defined
in the flow, the flow ends with a result of FAILURE
.
The on_failure
step must be the last step in the flow.
The on_failure
step cannot contain a navigation
section. It always causes the flow to end with a result of
FAILURE
.
Example - failure step which calls a print operation to print an error message
- on_failure:
- failure:
do:
print:
- text: ${error_msg}
Example - explicitly navigating to the on_failure step
- go_to_failure:
do:
some_operation:
- input1
navigate:
- SUCCESS: SUCCESS
- FAILURE: on_failure
The key operation
is mapped to the properties which make up the
operation contents.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
name |
yes | -- | string | name of the
operation
|
name |
inputs |
no | -- | list | operation inputs | inputs |
python_action |
no | -- | script key |
operation logic | python_action |
java_action |
map | operation logic | java_action | ||
outputs |
no | -- | list | operation outputs | outputs |
results |
no | SUCCESS |
list | possible operation
results
|
results |
Example - operation that adds two inputs and outputs the answer
operation:
name: add
inputs:
- left
- right
python_action:
script: ans = left + right
outputs:
- out: ${ans}
results:
- SUCCESS
The key outputs
is a property of a flow,
operation or decision. It is mapped to a list
of output variable names. Each output name may in turn be mapped to its
properties or an output expression. Output
expressions must evaluate to strings.
Defines the parameters a flow, operation or decision exposes to possible publication by a step. The calling step refers to an output by its name.
Output names for a specific flow, operation or decision must be different than the input names of the same flow, operation or decision.
For a list of which contexts are available in the outputs
section of a
flow, operation or decision,
see Contexts.
Output identifiers must conform to the rules for valid :ref:`variable names <variable_names>` and :ref:`uniqueness <uniqueness_and_case_sensitivity>`.
Property | Required | Default | Value Type | Description | More info |
---|---|---|---|---|---|
value |
no | -- | expression | value of
the output
|
value |
sensitive |
no | transitive
sensitivity
or false
|
boolean | is the output
sensitive
|
sensitive |
Example - various types of outputs
outputs:
- existing_variable
- output2: ${some_variable}
- output3: ${5 + 6}
- password:
value: ${password}
sensitive: true
The key parallel_loop
is a property of a parallel
step's name. It is mapped to the parallel
step's properties.
For each value in the loop's list a branch is created and the do
will run an operation or subflow. When all
the branches have finished, the parallel
step's publish and
navigation will run.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
for |
yes | -- | variable
in list
|
loop values | for |
do |
yes | -- | operation or
subflow call
|
operation or subflow
this step will
run in parallel
|
Example: loop that breaks on a result of custom
- print_values:
parallel_loop:
for: value in values
do:
print_branch:
- ID: ${value}
publish:
- name_list: ${map(lambda x:str(x['name']), branches_context)}
navigate:
- SUCCESS: print_list
- FAILURE: FAILURE
The key private
is a property of an input name. It
is mapped to a boolean value.
A value of true
will ensure that the input
parameter's default value will not be overridden by
values passed into the flow or operation. An
input set as private: true
must also declare a
default value. If private
is not defined, values passed
in will override the default value.
Example - default value of text input parameter will not be overridden by values passed in
inputs:
- text:
default: "default text"
private: true
The key properties
is mapped to a list of key:value
pairs that define
one or more system properties. Each system property name may in turn be mapped
to its properties or a value.
System property names (keys) can contain alphanumeric characters (A-Za-z0-9), underscores (_) and hyphens (-). The names must conform to the rules for :ref:`uniqueness <uniqueness_and_case_sensitivity>`.
System property values are retrieved using the get_sp() function.
Note
System property values that are non-string types (numeric, list, map,
etc.) are converted to string representations. A system property may have a
value of null
.
Property | Required | Default | Value Type | Description | More info |
---|---|---|---|---|---|
value |
no | -- | value of
the property
|
value | |
sensitive |
no | false | boolean | is the property
sensitive
|
sensitive |
Example - system properties file
namespace: examples.sysprops
properties:
- host: 'localhost'
- port: 8080
- password:
value: 'pwd'
sensitive: true
An empty system properties file can be defined using an empty list.
Example - empty system properties file
namespace: examples.sysprops
properties: []
The key publish
is a property of a step name, a
loop or a parallel_loop. It is mapped to a
list of key:value pairs where the key is the published variable name and
the value is an expression, usually involving an output received
from an operation or flow.
For a list of which contexts are available in the publish
section of a
step, see Contexts.
Publish names must conform to the rules for :ref:`uniqueness <uniqueness_and_case_sensitivity>`.
In a standard step, publish
binds an
expression, usually involving an
output from an operation or
flow, to a variable whose scope is the current
flow and can therefore be used by other steps or
as the flow's own output.
Example - publish the quotient output as ans
- division1:
do:
division:
- input1: ${dividend1}
- input2: ${divisor1}
publish:
- ans: ${quotient}
In an iterative step the publish mechanism is run during each iteration after the operation or subflow has completed, therefore allowing for aggregation.
Example - publishing in an iterative step to aggregate output: add the squares of values in a range
- aggregate:
loop:
for: value in range(1,6)
do:
square:
- to_square: ${value}
- sum
publish:
- sum: ${sum + squared}
In a parallel step the publish mechanism defines the step's aggregation logic, generally making use of the branches_context construct.
After all branches of a parallel step have
completed, execution of the flow continues with the publish
section. The
expression of each name:value pair is evaluated and published to the
flow's scope. The expression generally makes use of the
branches_context construct to access the values
published by each of the parallel loop's branches and their
results using the branch_result key.
For a list of which contexts are available in the publish
section of a
step, see Contexts.
For more information, see the :ref:`Parallel Loop <example_parallel_loop>` example.
Example - publishing in an parallel step to aggregate output
- print_values:
parallel_loop:
for: value in values_list
do:
print_branch:
- ID: ${value}
publish:
- name_list: ${map(lambda x:str(x['name']), branches_context)}
Example - extracting information from a specific branch
- print_values:
parallel_loop:
for: value in values_list
do:
print_branch:
- ID: ${value}
publish:
- first_name: ${branches_context[0]['name']}
Example - create a list of branch results
- print_values:
parallel_loop:
for: value in values
do:
print_branch:
- ID: ${ value }
publish:
- branch_results_list: ${map(lambda x:str(x['branch_result']), branches_context)}
The key python_action
is a property of an operation. It is
mapped to a script property that contains the actual Python script.
The key results
is a property of a flow,
operation or decision.
The results of a flow, operation or decision can be used by the calling step for navigation purposes.
Result names must conform to the rules for :ref:`uniqueness <uniqueness_and_case_sensitivity>`.
Note
The only results of an operation, decision
or subflow called in a parallel_loop that
are evaluated are SUCCESS
and FAILURE
. Any other results will be
evaluated as SUCCESS
.
In a flow, the key results
is mapped to a list of result
names.
Defines the possible results of the flow. By default a
flow has two results, SUCCESS
and FAILURE
. The
defaults can be overridden with any number of user-defined results.
When overriding, the defaults are lost and must be redefined if they are to be used.
All result possibilities must be listed. When being used as a subflow all flow results must be handled by the calling step.
Example - a user-defined result
results:
- SUCCESS
- ILLEGAL
- FAILURE
In an operation or decision the key results
is mapped to a list of key:value pairs of result names and boolean
expressions.
Defines the possible results of the operation or
decision. By default, if no results exist, the result is
SUCCESS
. The first result in the list whose expression evaluates to true, or
does not have an expression at all, will be passed back to the calling
step to be used for navigation purposes.
All operation or decision results must be handled by the calling step.
For a list of which contexts are available in the results
section of an
operation or decision, see
Contexts.
Example - three user-defined results
results:
- POSITIVE: ${polarity == '+'}
- NEGATIVE: ${polarity == '-'}
- NEUTRAL
The key required
is a property of an input name. It is
mapped to a boolean value.
A value of false
will allow the flow or
operation to be called without passing the
input parameter. If required
is not defined, the
input parameter defaults to being required. Required inputs must
receive a value or declare a default value.
Example - input2 is optional
inputs:
- input1
- input2:
required: false
The key script
is a property of python_action.
It is mapped to a value containing a Python script.
All variables in scope at the conclusion of the Python script must be
serializable. If non-serializable variables are used, remove them from
scope by using the del
keyword before the script exits.
Note
CloudSlang uses the Jython implementation of Python 2.7. For information on Jython's limitations, see the Jython FAQ.
Example - action with Python script that divides two numbers
name: divide
inputs:
- dividend
- divisor
python_action:
script: |
if divisor == '0':
quotient = 'division by zero error'
else:
quotient = float(dividend) / float(divisor)
outputs:
- quotient
results:
- ILLEGAL: ${quotient == 'division by zero error'}
- SUCCESS
Note
Single-line Python scripts can be written inline with the
script
key. Multi-line Python scripts can use the YAML pipe
(|
) indicator as in the example above.
There are three approaches to importing and using external Python modules:
- Installing packages into the python-lib folder
- Editing the executable file
- Adding the package location to
sys.path
Prerequisites: Python 2.7 and pip.
You can download Python (version 2.7) from here. Python 2.7.9 and later include pip by default. If you already have Python but don't have pip, see the pip documentation for installation instructions.
Edit the requirements.txt file in the python-lib folder, which is found at the same level as the bin folder that contains the CLI executable.
- If not using a pre-built CLI, you may have to create the python-lib folder and requirements.txt file.
Enter the Python package and all its dependencies in the requirements file.
- See the pip documentation for information on how to format the requirements file (see example below).
Run the following command from inside the python-lib folder:
pip install -r requirements.txt -t
.Note
If your machine is behind a proxy you will need to specify the proxy using pip's
--proxy
flag.Import the package as you normally would in Python from within the action's
script
:
python_action:
script: |
from pyfiglet import Figlet
f = Figlet(font='slant')
print f.renderText(text)
Example - requirements file
pyfiglet == 0.7.2 setuptools
Note
If you have defined a JYTHONPATH
environment variable, you
will need to add the python-lib folder's path to its value.
- Open the executable found in the bin folder for editing.
- Change the
Dpython.path
key's value to the desired path. - Import the package as you normally would in Python from within the
action's
script
.
- In the action's Pyton script, import the
sys
module. - Use
sys.path.append()
to add the path to the desired module. - Import the module and use it.
Example - takes path as input parameter, adds it to sys.path and imports desired module
inputs:
- path
python_action:
script: |
import sys
sys.path.append(path)
import module_to_import
print module_to_import.something()
To import a Python script in a python_action
:
- Add the Python script to the python-lib folder, which is found at the same level as the bin folder that contains the CLI executable.
- Import the script as you normally would in Python from within the
action's
script
.
Note
If you have defined a JYTHONPATH
environment variable, you
will need to add the python-lib folder's path to its value.
The key sensitive
is a property of an input,
output or system property name. It is mapped to
a boolean value.
The sensitivity of an input or output is
transitive, and is therefore determined by its sensitive
property and by the
sensitivity of variables used in its related value expression.
Values that are sensitive
will not be printed in logs, events or in outputs
of the :doc:`CLI <cloudslang_cli>` and :doc:`Build Tool <cloudslang_build_tool>`.
Example - two sensitive inputs
inputs:
- input1:
default: "default value"
sensitive: true
- input1plus:
default: ${ get("input1") + "something else" }
Example - two sensitive outputs
outputs:
- output1:
value: ${output1}
sensitive: true
- output2: ${already_sensitive_value}
Example - a sensitive system property
properties:
- password:
value: 'pwd'
sensitive: true
A name of a step which is a property of workflow or on_failure.
Every step which is not an on_failure step must be reachable from another step.
There are several types of steps:
Example - step with two arguments, one of which contains a default value
- divider:
do:
some_op:
- host
- port: 25
A standard step calls an operation or subflow once.
The step name is mapped to the step's properties.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
do |
yes | -- | operation
or subflow
call
|
the operation or
subflow this step
will run
|
|
publish |
no | -- | list of
key:value
pairs
|
operation outputs
to publish to the
flow level
|
|
navigate |
no | FAILURE : on_failureor flow finish
SUCCESS : next step |
list of
key:value
pairs
|
navigation logic
from operation or
flow results
|
Example - step that performs a division of two inputs, publishes the answer and navigates accordingly
- divider:
do:
divide:
- dividend: ${input1}
- divisor: ${input2}
publish:
- answer: ${quotient}
navigate:
- ILLEGAL: FAILURE
- SUCCESS: printer
An iterative step calls an operation or subflow iteratively, for each value in a list.
The step name is mapped to the iterative step's properties.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
loop |
yes | -- | key | container for
loop properties
|
for |
navigate |
no | FAILURE :on_failure
or flow finish
SUCCESS :next step
|
key:value
pairs
|
Example - step prints all the values in value_list and then navigates to a step named "another_step"
- print_values:
loop:
for: value in value_list
do:
print:
- text: ${value}
navigate:
- SUCCESS: another_step
- FAILURE: FAILURE
A parallel step calls an operation or subflow in parallel branches, for each value in a list.
The step name is mapped to the parallel step's properties.
Property | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
parallel_loop |
yes | -- | key | container for
parallel loop
properties
|
parallel_loop |
publish |
no | -- | list of
key:values
|
values to
aggregate from
parallel branches
loop properties
|
publish |
navigate |
no | FAILURE : on_failureor flow finish
SUCCESS : next step |
key:value
pairs
|
navigation logic |
Example - step prints all the values in value_list in parallel and then navigates to a step named "another_step"
- print_values:
parallel_loop:
for: value in values_list
do:
print_branch:
- ID: ${value}
publish:
- name_list: ${map(lambda x:str(x['name']), branches_context)}
navigate:
- SUCCESS: another_step
- FAILURE: FAILURE
The key value
is a property of an output or
system property name. In an output, the key is
mapped to an expression value. In a
system property, the key is mapped to a valid
system property value.
The value key is most often used in conjunction with the sensitive key. Otherwise, an output or system property's value can be defined inline by mapping it to the output or system property's name.
Example - output values
outputs:
- password:
value: ${password}
sensitive: true
- another_output: ${op_output}
Example - system property values
properties:
- props.password:
value: 'pwd'
sensitive: true
- props.another_property: 'prop value'
The key workflow
is a property of a flow. It is mapped
to a list of the workflow's steps.
Defines a container for the steps, their published variables and navigation logic.
The first step in the workflow is the starting
step of the flow. From there the flow continues sequentially
by default upon receiving results of SUCCESS
, to the
flow finish or to on_failure upon a
result of FAILURE
, or following whatever overriding
navigation logic that is present.
Propery | Required | Default | Value Type | Description | More Info |
---|---|---|---|---|---|
on_failure |
no | -- | step | default navigation
target for
FAILURE |
Example - workflow that divides two numbers and prints them out if the division was legal
workflow:
- divider:
do:
divide:
- dividend: ${input1}
- divisor: ${input2}
publish:
- answer: ${quotient}
navigate:
- ILLEGAL: FAILURE
- SUCCESS: printer
- printer:
do:
print:
- text: ${input1 + "/" + input2 + " = " + answer}
May appear in the value of an input, output, publish or result expression.
The function in the form of check_empty(expression1, expression2)
returns
the value associated with expression1
if expression1
does not evaluate
to None
. If expression1
evaluates to None
the function returns the
value associated with expression2
.
Example - usage of check_empty to check operation output in a flow
flow:
name: flow
inputs:
- in1
workflow:
- step1:
do:
operation:
- in1
publish:
- pub1: ${check_empty(out1, 'x marks the spot')}
#if in1 was not 'x' then out1 is 'not x' and pub1 is therefore 'not x'
#if in1 was 'x' then out1 is None and pub1 is therefore 'x marks the spot'
outputs:
- pub1
operation:
name: operation
inputs:
- in1
python_action:
script: |
out1 = 'not x' if in1 != 'x' else None
outputs:
- out1
May appear in the value of an input, output, publish or result expression.
The function in the form of get('key')
returns the value associated with
key
if the key is defined. If the key is undefined the function returns
None
.
The function in the form of get('key', 'default_value')
returns the
value associated with key
if the key is defined and its value is not
None
. If the key is undefined or its value is None
the function
returns the default_value
.
Example - usage of get function in inputs and outputs
inputs:
- input1:
required: false
- input1_safe:
default: ${get('input1', 'default_input')}
private: true
workflow:
- step1:
do:
print:
- text: ${input1_safe}
publish:
- some_output: ${get('output1', 'default_output')}
outputs:
- some_output
May appear in the value of an input, step argument, publish, output or result expression.
The function in the form of get_sp('key', 'default_value')
returns the
value associated with the system property named key
if the
key is defined and its value is not null
. If the key is undefined or its
value is null
the function returns the default_value
. The key
is the
fully qualified name of the system property, meaning the
namespace (if there is one) of the file in which it is found followed by a dot
.
and the name of the key.
System property values are always strings or null
. Values
of other types (numeric, list, map, etc.) are converted to string
representations.
System properties are not enforced at compile time. They are assigned at runtime.
Note
If multiple system properties files are being used and they contain a system property with the same fully qualified name, the property in the file that is loaded last will overwrite the others with the same name.
Example - system properties file
namespace: examples.sysprops
properties:
- host: 'localhost'
- port: 8080
Example - system properties used as input values
inputs:
- host: ${get_sp('examples.sysprops.hostname')}
- port: ${get_sp('examples.sysprops.port', '8080')}
To pass a system properties file to the CLI, see :ref:`Run with System Properties <run_with_system_properties>`.