This documentation and the Cisco Observability Platform functionalities it describes are subject to change. Data saved on the platform may disappear and APIs may change without notice.
Solution Services Integration
In a solution, you can leverage the capabilities of zodiac:function in your Codex workflows to process any complex logic. The zodiac:function
is invoked from the Codex workflow.
Important
You can invoke zodiac:function in your Codex workflows that are part of a solution layer, which tenants can subscribe to. It can not be invoked in Codex workflows that are part of a tenant layer.
To use the zodiac:function
in a Codex workflow of your solution, you need to deploy:
a solution with
zodiac:function
,iam:Permission
,iam:RoleToPermissionMapping
, andcontracts:openAPI
objects.a solution with the Codex workflow where the
zodiac:function
is invoked.
The solution with zodiac:function
objects must be deployed before the solution with the Codex workflow.
Deploy Solution with Zodiac Function Objects
To add the zodiac:function
objects in your solution bundle:
Create an object of type zodiac:function. For example, the following
codex-function.json
is an object of the typezodiac:function
:{ "name": "codex-function", "image": "<CONTAINER_REGISTRY_ENDPOINT>:/codex-zodiac-image:1.0-65", "openAPI":"contracts:openAPI/codexzodiactest:/info/title=codexzodiactest;/info/version=0.1", "scaleBounds": { "lower": 2, "upper": 20 }, "concurrency": { "softLimit": 500, "targetUtilizationPercentage" : 20 }, "resources": { "requests": { "memory":"1Gi", "cpu": "2" }, "limits": { "memory":"2Gi", "cpu":"4" } } }
Create an object of the type
contracts:openAPI
and refer it inside the function object. For example, the followingcodexzodiactest.json
is an object of the typecontracts:openAPI
:{ "openapi": "3.0.1", "info": { "title": "codexzodiactest", "description": "A Codex Zodiac integration Function API", "contact": { "name": "CodexZodiacIntegration", "url": "https://appd-server.com", "email": "support@appd-server.com" }, "license": { "name": "Apache 2.0", "url": "https://foo.bar" }, "version": "0.1" }, "servers": [ { "url": "", "description": "Codex Zodiac integration Function call" } ], "paths": { "/data": { "get": { "tags": [ "test-controller" ], "summary": "Retrieve data by codextest parameter", "description": "Retrieves data based on the provided codextest parameter or returns default data if not provided", "operationId": "getData", "parameters": [ { "name": "codextest", "in": "query", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Successful retrieval of data", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DataDto" } } } } } } }, "components": { "schemas": { "KeyValueDto": { "type": "object", "properties": { "key": { "type": "string" }, "value": { "type": "string" } } }, "DataDto": { "type": "object", "properties": { "data": { "type": "object", "additionalProperties": { "type": "string" } } } } } } } }
Create an object of the type
iam:Permission
. For example, the followingzodiac-permission.json
is an object of the typeiam:Permission
:[ { "name": "data", "description": "Permissions to use function endpoint", "displayName": "Codex Zodiac Function", "actionAndResources": [ { "action": { "type": "HttpAction", "method": "GET", "classification": "READ", "pathPattern": "/codex-function-perf-test/data" } } ] }, { "name": "testdata", "description": "Permissions to use function endpoint", "displayName": "Codex Zodiac Function", "actionAndResources": [ { "action": { "type": "HttpAction", "method": "POST", "classification": "READ", "pathPattern": "/codex-function-perf-test/testdata" } } ] }, { "name": "codexqe", "description": "Permissions to use function endpoint", "displayName": "Codex Zodiac Function", "actionAndResources": [ { "action": { "type": "HttpAction", "method": "POST", "classification": "CREATE", "pathPattern": "/codex-function-perf-test/codexqe" } }, { "action": { "type": "HttpAction", "method": "GET", "classification": "READ", "pathPattern": "/codex-function-perf-test/codexqe" } }, { "action": { "type": "HttpAction", "method": "PUT", "classification": "UPDATE", "pathPattern": "/codex-function-perf-test/codexqe" } }, { "action": { "type": "HttpAction", "method": "DELETE", "classification": "DELETE", "pathPattern": "/codex-function-perf-test/codexqe" } }, { "action": { "type": "HttpAction", "method": "PATCH", "classification": "UPDATE", "pathPattern": "/codex-function-perf-test/codexqe" } } ] } ]
Create an object of the type
iam:RoleToPermissionMapping
. For example, the followingrole-to-permission-mappings.json
is an object of the typeiam:RoleToPermissionMapping
:[ { "name": "tenantAdminPermissions", "roles": [ "iam:tenantAdmin", "iam:observer" ], "permissions": [ { "id": "codexzodiacperf:data" }, { "id": "codexzodiacperf:testdata" }, { "id": "codexzodiacperf:codexqe" } ] } ]
In your solution's
manifest.json
file, declarecontracts
andzodiac
as dependencies and define the objects. For example:{ "name": "codexzodiactest", "solutionVersion": "1.0.1", "manifestVersion": "1.0.0", "dependencies": ["zodiac", "contracts"], "description": "Zodiac objects for Perf testing", "contact": "support@appd.com", "gitRepoUrl": "<Your git URL>", "types": [], "objects": [ { "type": "zodiac:function", "objectsFile": "objects/functions/codex-function-perf.json" }, { "type": "iam:Permission" "objectsFile": "objects/iam/zodiac-permission.json", }, { "type": "iam:RoleToPermissionMapping" "objectsFile": "objects/iam/role-to-permission-mappings.json", }, { "type": "contracts:openAPI", "objectsFile": "objects/openapi/codexzodiactest.json" } ] }
Each time you modify your solution:
Increment
solutionVersion
inmanifest.json
.Check your solution with the fsoc solution check command.
Run the fsoc solution validate command to catch errors that would cause
fsoc solution push
to fail.Republish your solution with the fsoc solution push command.
Deploy a Solution with Codex Workflow
In the solution with the Codex workflow, do the following:
In the Codex workflow, define the
zodiac:function
definition. For example:{ "name": "getrestFunction", "type": "rest", "operation": "zodiac://zodiac:function/codexzodiac:codex-function#getData" }
In the Codex workflow, invoke the
zodiac:function
. For example:{ "name": "InvokeRestFunction", "type": "operation", "actions": [ { "functionRef": { "refName": "getrestFunction", "arguments": { "codextest":"trace2event-http-get" } }, "actionDataFilter": { "toStateData": "${ getOutput }" } } ], "transition": "CreateEvent" }
Create an object of the type
iam:SolutionPermissions
that provides access between your Codex solution and the Zodiac function. For example, the followingsolutionPermissions.json
is an object of the typeiam:SolutionPermissions
:{ "permissions": [ { "id": "codexzodiactest:codexqe", "can_access_in_background": true } ], "name": "default" }
In your solution's manifest.json file, declare the types codex and iam as dependencies and the objects. For example:
{ "name": "codexzodiacwfperf", "description": "codex zodiac workflow for validation", "readme": "readme.md", "dependencies": ["codex", "iam"], "homepage": "solutions.appd.com/codex", "solutionVersion": "1.0.12", "manifestVersion": "1.0.0", "contact": "support@appd.com", "gitRepoUrl": "<Your Git Repo URL>", "objects": [{ "objectsFile": "objects/codex/trace2eventget.json", "type": "codex:workflow" }, { "type": "iam:SolutionPermissions", "objectsFile": "objects/iam/solutionPermissions.json" }] }
Each time you modify your solution:
Increment solutionVersion in
manifest.json
.Check your solution with the fsoc solution check command.
Run the fsoc solution validate command to catch errors that would cause
fsoc solution push
to fail.Republish your solution with the fsoc solution push command.
Workflow example:
{
"id": "trace2event-zodiac-codex",
"version": "1.0",
"specVersion": "0.8",
"name": "trace2event-zodiac-codex",
"description": "trace to event workflow with zodiac function call",
"expressionLang": "Jsonata",
"start": "ReadTrace",
"events": [
{
"name": "TraceReceived",
"type": "contracts:cloudevent/platform:trace.enriched.v1",
"source": "platform",
"kind": "consumed"
},
{
"name": "EventCreated",
"type": "contracts:cloudevent/platform:event.received.v1",
"source": "platform",
"kind": "produced"
}
],
"functions": [
{
"name": "generateEvents",
"type": "expression",
"operation": "{\"event\" :groupedSpans[0].spans.{\"entities\" : entities, \"type\": \"k8s:native_event\", \"timestamp\" : startedAt, \"raw\":\"trace to event workflow and zodiac function perf\", \"spanId\": \"\", \"traceId\": \"\", \"attributes\": $merge([{\"severity\": \"DEBUG\", \"workflow\":\"trace2event-zodiac-get\", \"appd.isevent\": true},$$.getOutput.data]) }}"
},
{
"name": "getrestFunction",
"type": "rest",
"operation": "zodiac://zodiac:function/codexzodiactest:codex-function#getData"
}
],
"states": [
{
"name": "ReadTrace",
"type": "event",
"onEvents": [
{
"eventRefs": [
"TraceReceived"
],
"eventDataFilter": {
"data": "${ data }"
}
}
],
"transition": "InvokeRestFunction"
},
{
"name": "InvokeRestFunction",
"type": "operation",
"actions": [
{
"functionRef": {
"refName": "getrestFunction",
"arguments": {
"codextest":"trace2event-http-get"
}
},
"actionDataFilter": {
"toStateData": "${ getOutput }"
}
}
],
"transition": "CreateEvent"
},
{
"name": "CreateEvent",
"type": "operation",
"actions": [
{
"functionRef": {
"refName": "generateEvents"
}
}
],
"end": {
"terminate": true,
"produceEvents": [
{
"eventRef": "EventCreated",
"data": "${ event }"
}
]
}
}
]
}
Points to consider:
The type of the
zodiac:function
must be rest.The operation must begin with
zodiac:function/solutionName:functionName#operationId
.solutionName
is the name of the solution where the function has been defined.functionName
is the name of the zodiac function.operationId
is the operation ID in the OpenAPI spec of the zodiac function that needs to be invoked.
zodiac:function object must contain a reference to the OpenAPI spec. For example:
"openAPI":"contracts:openAPI/codexzodiactest:/info/title=codexzodiactest;/info/version=0.1",
OpenAPI spec referred inside the
zodiac:function
should exist in the solution.contracts:openAPI object should follow the following:
- For POST, PUT, or PATCH, the
requestBody
is mandatory. - For POST, PUT, or PATCH, the
requestBody
schema should always be of the type object. - For POST, PUT, or PATCH, the
requestBody
thecontentType
should always beapplication/json
. - For GET or DELETE , the
requestBody
must be null.
- For POST, PUT, or PATCH, the