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:openAPIobjects.a solution with the Codex workflow where the
zodiac:functionis 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.jsonis 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:openAPIand refer it inside the function object. For example, the followingcodexzodiactest.jsonis 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.jsonis 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.jsonis 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.jsonfile, declarecontractsandzodiacas 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
solutionVersioninmanifest.json.Check your solution with the fsoc solution check command.
Run the fsoc solution validate command to catch errors that would cause
fsoc solution pushto 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:functiondefinition. 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:SolutionPermissionsthat provides access between your Codex solution and the Zodiac function. For example, the followingsolutionPermissions.jsonis 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 pushto 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:functionmust be rest.The operation must begin with
zodiac:function/solutionName:functionName#operationId.solutionNameis the name of the solution where the function has been defined.functionNameis the name of the zodiac function.operationIdis 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:functionshould exist in the solution.contracts:openAPI object should follow the following:
- For POST, PUT, or PATCH, the
requestBodyis mandatory. - For POST, PUT, or PATCH, the
requestBodyschema should always be of the type object. - For POST, PUT, or PATCH, the
requestBodythecontentTypeshould always beapplication/json. - For GET or DELETE , the
requestBodymust be null.
- For POST, PUT, or PATCH, the