From 98b5969b275c63c24fa3ec84d8052b7a49fe7bc3 Mon Sep 17 00:00:00 2001 From: "a.sreekumar" Date: Fri, 23 Jul 2021 13:38:06 +0100 Subject: APEX doc updates for multiple output support Change-Id: I1867c7ecc5405e972401a9ed647b7ff71ba2a88e Issue-ID: POLICY-3512 Signed-off-by: a.sreekumar --- docs/apex/APEX-Policy-Guide.rst | 175 +++++++++++++++++++++++++++++++++++++--- docs/apex/APEX-User-Manual.rst | 10 +-- 2 files changed, 169 insertions(+), 16 deletions(-) diff --git a/docs/apex/APEX-Policy-Guide.rst b/docs/apex/APEX-Policy-Guide.rst index 4b11413f..1871fb2a 100644 --- a/docs/apex/APEX-Policy-Guide.rst +++ b/docs/apex/APEX-Policy-Guide.rst @@ -540,6 +540,11 @@ Concept: State policy may only output a single event and all tasks of that state may also only output that single event. In future work, the concept of having a less restrictive trigger pattern will be examined. +.. container:: paragraph + + A state that is the final state of a policy may output multiple events, and the task associated with the final state + outputs those events. + .. container:: paragraph A *State* concept is keyed with a ``ReferenceKey`` key, which references the *Policy* concept that owns the state. @@ -606,7 +611,8 @@ Writing APEX Task Logic What do Tasks do? The function of an Apex Task is to provide the logic that can be executed for an Apex State as one of the steps in an Apex Policy. Each task receives some *incoming fields*, executes some logic (e.g: make a decision based on *shared state* or *context*, *incoming fields*, *external context*, etc.), perhaps set some *shared state* - or *context* and then emits *outgoing fields*. The state that uses the task is responsible for extracting the + or *context* and then emits *outgoing fields* (in case of a single outgoing event), or a set of *outgoing fields* + (in case of multiple outgoing events). The state that uses the task is responsible for extracting the *incoming fields* from the state input event. The state also has an *output mapper* associated with the task, and this *output mapper* is responsible for mapping the *outgoing fields* from the task into an appropriate output event for the state. @@ -852,7 +858,8 @@ Table 1. The ``executor`` Fields / Methods +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+ | outFields | Fields | java.util.Map |The outgoing task fields. This is implemented as a standard initially empty Java | | | | |(modifiable) Map. To create a new schema-compliant instance of a field object | - | | | |see the utility method subject.getOutFieldSchemaHelper() below | + | | | |see the utility method subject.getOutFieldSchemaHelper() below that takes the | + | | | |fieldName as an argument. | | | | | | | | | |**Example:** | | | | | | @@ -860,6 +867,32 @@ Table 1. The ``executor`` Fields / Methods | | | | | | | | | executor.outFields["authorised"] = false; | +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+ + | outFieldsList | Fields | java.util.Collection |The collection of outgoing task fields when there are multiple outputs from the | + | | | > |final state. To create a new schema-compliant instance of a field, see the | + | | | |utility method subject.getOutFieldSchemaHelper() below that takes eventName and | + | | | |fieldName as arguments. | + | | | |To add the set of output fields to the outFieldsList, the utility method | + | | | |executor.addFieldsToOutput can be used as shown below. | + +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+ + | void addFieldsToOutput(Map fields) |A utility method to add fields to outgoing fields. | | | + | |When there are multiple output events emitted from the task associated | | | + | |with a final state, this utility method can be used to add the | | | + | |corresponding fields to the outFieldsList. | | | + | | | | | + | |**Example:** | | | + | | | | | + | |.. code:: javascript | | | + | | | | | + | | var cdsRequestEventFields = java.util.HashMap(); | | | + | | var actionIdentifiers = executor.subject.getOutFieldSchemaHelper | | | + | | ("CDSRequestEvent","actionIdentifiers").createNewInstance(); | | | + | | cdsRequestEventFields.put("actionIdentifiers", actionIdentifiers); | | | + | | executor.addFieldsToOutput(cdsRequestEventFields); | | | + | | | | | + | | var logEventFields = java.util.HashMap(); | | | + | | logEventFields.put("status", "FINAL_SUCCESS"); | | | + | | executor.addFieldsToOutput(logEventFields); | | | + +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+ | logger | Logger | org.slf4j.ext.XLogger |A helpful logger | | | | | | | | | |**Example:** | @@ -898,7 +931,18 @@ Table 1. The ``executor`` Fields / Methods | | | | get a ``SchemaHelper`` helper object to manipulate outgoing | | | | | task fields in a schema-aware manner, e.g. to instantiate new | | | | | schema-compliant field objects to populate the | - | | | | ``executor.outFields`` outgoing fields map | + | | | | ``executor.outFields`` outgoing fields map. This can be used only when there | + | | | | is a single outgoing event from a task. | + | | | | | + | | | | - **SchemaHelper getOutFieldSchemaHelper( String eventname, String fieldName )**| + | | | | to get a ``SchemaHelper`` helper object to manipulate outgoing | + | | | | task fields in a schema-aware manner, e.g. to instantiate new | + | | | | schema-compliant field objects to populate the | + | | | | ``executor.outFieldsList`` collection of outgoing fields map. This must be | + | | | | used in case of multiple outgoing events from a task, as the intention is to | + | | | | fetch the schema of a field associated to one of the expected events. | + | | | | This method works fine in case of single outgoing event too, but the previous | + | | | | method is enough as the field anyway belongs to the single event. | | | | | | | | | |**Example:** | | | | | | @@ -906,12 +950,15 @@ Table 1. The ``executor`` Fields / Methods | | | | | | | | | executor.logger.info("Task name: " + executor.subject.getTaskName()); | | | | | executor.logger.info("Task id: " + executor.subject.getId()); | - | | | | executor.logger.info("Task inputs definitions: " | - | | | | + "executor.subject.task.getInputFieldSet()); | - | | | | executor.logger.info("Task outputs definitions: " | - | | | | + "executor.subject.task.getOutputFieldSet()); | | | | | executor.outFields["authorised"] = executor.subject | | | | | .getOutFieldSchemaHelper("authorised").createNewInstance("false"); | + | | | | | + | | | | var actionIdentifiers = executor.subject.getOutFieldSchemaHelper | + | | | | ("CDSRequestEvent","actionIdentifiers").createNewInstance(); | + | | | | actionIdentifiers.put("blueprintName", "sample-bp"); | + | | | | var cdsRequestEventFields = java.util.HashMap(); | + | | | | cdsRequestEventFields.put("actionIdentifiers", actionIdentifiers); | + | | | | executor.addFieldsToOutput(cdsRequestEventFields); | +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+ | ContextAlbum getContextAlbum(String ctxtAlbumName ) |A utility method to retrieve a ``ContextAlbum`` for use in the task. | | | | |This is how you access the context used by the task. The returned | | | @@ -1159,10 +1206,6 @@ Table 2. The ``executor`` Fields / Methods | | | | | | | | | executor.logger.info("Task name: " + executor.subject.getTaskName()); | | | | | executor.logger.info("Task id: " + executor.subject.getId()); | - | | | | executor.logger.info("Task inputs definitions: " | - | | | | + "executor.subject.task.getInputFieldSet()); | - | | | | executor.logger.info("Task outputs definitions: " | - | | | | + "executor.subject.task.getOutputFieldSet()); | | | | | executor.outFields["authorised"] = executor.subject | | | | | .getOutFieldSchemaHelper("authorised") | | | | | .createNewInstance("false"); | @@ -1414,8 +1457,11 @@ Create a instance of an Outfield using Schemas If the backend is Java, then the Java class implementing the schema needs to be imported. +*Single outgoing event* + .. container:: paragraph + When there is a single outgoing event associated with a task, the fieldName alone is enough to fetch its schema. The following example assumes an outfield ``situation``. The ``subject`` method ``getOutFieldSchemaHelper()`` is used to create a new instance. @@ -1449,6 +1495,23 @@ Create a instance of an Outfield using Schemas situation.put("problemID", "my-problem"); +*Multiple outgoing events* + +.. container:: paragraph + + When there are multiple outgoing events associated with a task, the fieldName along with the eventName it belongs to + are needed to fetch its schema. + The following example assumes an outfield ``actionIdentifiers`` which belongs to ``CDSRequestEvent``. + The ``subject`` method ``getOutFieldSchemaHelper()`` is used to create a new instance. + +.. container:: listingblock + + .. container:: content + + .. code:: javascript + + var actionIdentifiers = executor.subject.getOutFieldSchemaHelper("CDSRequestEvent", "actionIdentifiers").createNewInstance(); + Create a instance of an Context Album entry using Schemas --------------------------------------------------------- @@ -1788,6 +1851,96 @@ The *Equal Value and Equal Type* operator ``===`` is not supported in Rhino. Dev operator ``==`` instead. To check types, they may need to explicitly find and check the type of the variables they are using. +************************************************* +Writing Multiple Output Events from a Final State +************************************************* + +.. container:: paragraph + + APEX-PDP now supports sending multiple events from a final state in a Policy. The task assocaiated with the final + state can populate the fields of multiple events, and then they can be passed over as the output events from the final + state of a policy. + +.. note:: + inputfields and outputfields are not needed as part of the task definition anymore. Fields of an event are already + defined as part of the event definition. Input event (single trigger event) and output event/events can be populated + to a task as part of the policy/state definition because the event tagging is done there anyway. + +.. container:: paragraph + + Consider a simple example where a policy *CDSActionPolicy* has a state *MakeCDSRequestState* which is also a final + state. The state is triggered by an event *AAIEvent*. A task called *HandleCDSActionTask* is associated with + *MakeCDSRequestState*.There are two output events expected from *MakeCDSRequestState* which are *CDSRequestEvent* + (request event sent to CDS) and *LogEvent* (log event sent to DMaaP). + Writing an APEX policy with this example will involve the below changes. + +*Command File:* + +.. container:: listingblock + + .. container:: title + + Define all the concepts in the Policy. Only relevant parts for the multiple output support are shown. + + .. container:: content + + .. code:: + + ## Define Events + event create name=AAIEvent version=0.0.1 nameSpace=org.onap.policy.apex.test source=AAI target=APEX + .. + event create name=CDSRequestEvent version=0.0.1 nameSpace=org.onap.policy.apex.test source=APEX target=CDS + event parameter create name=CDSRequestEvent parName=actionIdentifiers schemaName=CDSActionIdentifiersType + .. + event create name=LogEvent version=0.0.1 nameSpace=org.onap.policy.apex.test source=APEX target=DMaaP + event parameter create name=LogEvent parName=status schemaName=SimpleStringType + .. + + ## Define Tasks + task create name=HandleCDSActionTask + task contextref create name=HandleCDSActionTask albumName=EventDetailsAlbum + task logic create name=HandleCDSActionTask logicFlavour=JAVASCRIPT logic=LS + #MACROFILE:"src/main/resources/logic/HandleCDSActionTask.js" + LE + .. + + ## Define Policies and States + policy create name=CDSActionPolicy template=Freestyle firstState=MakeCDSRequestState + policy state create name=CDSActionPolicy stateName=MakeCDSRequestState triggerName=AAIEvent defaultTaskName=HandleCDSActionTask + # Specify CDSRequestEvent as output + policy state output create name=CDSActionPolicy stateName=MakeCDSRequestState outputName=CDSActionStateOutput eventName=CDSRequestEvent + # Specify LogEvent as output + policy state output create name=CDSActionPolicy stateName=MakeCDSRequestState outputName=CDSActionStateOutput eventName=LogEvent + policy state taskref create name=CDSActionPolicy stateName=MakeCDSRequestState taskName=HandleCDSActionTask outputType=DIRECT outputName=CDSActionStateOutput + +*Task Logic File:* + +.. container:: listingblock + + .. container:: title + + Create outfields' instance if required, populate and add them the output events + + .. container:: content + + .. code:: javascript + + .. + var cdsRequestEventFields = java.util.HashMap(); + var actionIdentifiers = executor.subject.getOutFieldSchemaHelper("CDSRequestEvent","actionIdentifiers").createNewInstance(); + actionIdentifiers.put("blueprintName", "sample-bp"); + cdsRequestEventFields.put("actionIdentifiers", actionIdentifiers); + executor.addFieldsToOutput(cdsRequestEventFields); + + var logEventFields = java.util.HashMap(); + logEventFields.put("status", "FINAL_SUCCESS"); + executor.addFieldsToOutput(logEventFields); + +.. container:: paragraph + + With the above changes, the task populates the fields for both the expected events, and the corresponding state which + is *MakeCDSRequestState* outputs both *CDSRequestEvent* and *LogEvent* + .. |APEX Policy Matrix| image:: images/apex-intro/ApexPolicyMatrix.png .. |APEX Policy Model for Execution| image:: images/apex-policy-model/UmlPolicyModels.png .. |Concepts and Keys| image:: images/apex-policy-model/ConceptsKeys.png diff --git a/docs/apex/APEX-User-Manual.rst b/docs/apex/APEX-User-Manual.rst index 75032466..3452e779 100644 --- a/docs/apex/APEX-User-Manual.rst +++ b/docs/apex/APEX-User-Manual.rst @@ -5453,7 +5453,7 @@ Demo with VPN Policy Model in an editor (we need to send those events to APEX) A Websocket Configuration for the VPN Domain -******************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. container:: paragraph @@ -5520,7 +5520,7 @@ A Websocket Configuration for the VPN Domain } Start APEX Engine -***************** +^^^^^^^^^^^^^^^^^ .. container:: paragraph @@ -5571,7 +5571,7 @@ Start APEX Engine policy is triggered/executed. Run the Websocket Echo Client -***************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. container:: paragraph @@ -5661,7 +5661,7 @@ Run the Websocket Echo Client ws-simple-echo: opened connection to APEX (Web Socket Protocol Handshake) Run the Websocket Console Client -******************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. container:: paragraph @@ -5752,7 +5752,7 @@ Run the Websocket Console Client ws-simple-console: opened connection to APEX (Web Socket Protocol Handshake) Send Events -*********** +^^^^^^^^^^^ .. container:: paragraph -- cgit 1.2.3-korg