Hi everyone, in continuation of our discussion in the ad hoc today about workflows, here is a suggestion for how we could allow for imperative DAG workflows by using node templates.
The idea is to add new keywords to relationships in order to support execution:
- "call": to call an operation on the relationship interfaces
- "call_source": to call an operation on the relationship target node interfaces
- "call_target": to call an operation on the relationship target node interfaces
- "on_success": to "flow" in this direction when all operations succeed
- "on_failure": to "flow" in this direction if any operation fails
By putting these keywords in relationships, rather than nodes, we can allow for call graphs in addition to simple calls.
A TOSCA orchestrator could then start a workflow by specifying a starting node and then traverse the relationships and execute the called operations. If there are multiple outgoing callable relationships then they would/could be called in parallel.
The advantage, as I see it, is that this grammar integrates with TOSCA's type system and inherent graphs to allow for variation and specificities of implementations. So, they can be included in a profile for a specific orchestration platform.
And also the workflow graph will be clearly visible via usual TOSCA visualization tools -- these are just nodes and relationships.
An example:
relationship_types:
 ExecuteOnTarget:
ÂÂÂ # in the relationship type "call_target" is a boolean, a declaration that execution must be assigned
ÂÂÂ call_target: true
ÂÂÂ # properties can be used for orchestrator-specific features
ÂÂÂ properties:
ÂÂÂÂÂ executor:
ÂÂÂÂÂÂÂ type: string
ÂÂÂÂÂÂÂ default: REST
ÂÂÂ # attributes can be used for orchestrator-specific state (and notifications can be used to update them)
ÂÂÂ attributes:
ÂÂÂÂÂ error_message:
ÂÂÂÂÂÂÂ type: string
 OnSuccess:
ÂÂÂ on_success: true
ÂÂÂ # properties can be used orchestrator-specific considerations
ÂÂÂ properties:
ÂÂÂÂÂ timeout:
ÂÂÂÂÂÂÂ type: scalar-unit.time
ÂÂÂÂÂÂÂ default: 5 s
node_types:
 Task:
ÂÂÂ requirements:
ÂÂÂ - execute_on:
ÂÂÂÂÂÂÂ node: Server
ÂÂÂÂÂÂÂ relationship: ExecuteOnTarget
ÂÂÂ - on_success:
ÂÂÂÂÂÂÂ node: Task
ÂÂÂÂÂÂÂ relationship: OnSuccess
node_templates:
 server1:
ÂÂÂ type: Server
 server2:
ÂÂÂ type: Server
 create:
ÂÂÂ type: Task
ÂÂÂ requirements:
ÂÂÂ # both of these operations will be called in parallel:
ÂÂÂ - execute_on:
ÂÂ ÂÂÂÂ node: server1
ÂÂ ÂÂÂÂ relationship:
ÂÂ Â Â ÂÂ # in the relationship assignment "call_target" is a string, which operation to call on node
 Â Â call_target: MyInterface1.create
ÂÂÂ - execute_on:
ÂÂ ÂÂÂÂ node: server2
ÂÂ ÂÂÂÂ relationship:
 Â Â call_target: MyInterface2.provision
ÂÂÂÂ # the workflow will continue to both of these next steps in parallel
ÂÂÂÂ # (we could have limited this count via relationship type "occurrences")
ÂÂÂÂ - on_success: install
ÂÂÂÂ - on_success: notify_admin
 install:
ÂÂÂ type: Task
ÂÂÂ ...
 notify_admin:
ÂÂÂ type: Task
ÂÂÂ ...