Skip to main content

Cortex

A Cortex portal publishes Promises and Resources as Cortex entities, and generates Cortex workflows so developers can request, update and delete Resources from Cortex.

The journey runs in both directions:

  1. A platform engineer binds a Promise to Cortex. The Portal Controller publishes its entity, resource entity type and workflows.
  2. A developer runs a Cortex workflow. Cortex commits a resource request to Git.
  3. The platform GitOps agent applies the request to the cluster, and Kratix reconciles it.
  4. Resource sync publishes the entity definition; the Cortex exporter sends subsequent status updates back to Cortex.

Start with Generate entities, then Send resource requests. Use Customise entities and workflows to adjust the generated documents.

Unlike Backstage, the Portal Controller calls the Cortex API directly. A Cortex portal therefore needs a URL and a credential. Both portal types run a setup Job, but Cortex also runs a long-lived status exporter.

Prepare your Cortex workspace​

Before configuring the portal:

  1. Choose an existing GitHub or GitLab repository and branch to receive Resource requests. This repository is for platform requests, not for publishing Cortex entities.
  2. Configure Cortex's GitHub or GitLab integration with permission to read and write files in that repository. Record its alias for config.integrationAlias below.
  3. Obtain a Cortex API credential suitable for the adapter's entity, entity type, relationship, workflow and custom-data API operations under your workspace's access controls. Store the credential in the Kubernetes Secret shown below.
  4. Configure a platform GitOps agent to apply Resource requests from the chosen repository, branch and path. Without it, Cortex can commit a request but Kratix will not receive it.

Configuration​

apiVersion: v1
kind: Secret
metadata:
name: cortex-token
namespace: kratix-platform-system
type: Opaque
stringData:
token: <cortex-api-token>
---
apiVersion: platform.syntasso.io/v1alpha1
kind: SKEIntegration
metadata:
name: portal-controller
spec:
type: portal-controller
version: v0.6.1
portals:
- name: prod
type: cortex
url: https://api.getcortexapp.com
secretRef:
name: cortex-token
config:
repositoryName: syntasso/platform-catalog
provider: github
integrationAlias: github-main
branch: main

url and secretRef.name are both required. The Secret must exist in kratix-platform-system with the credential under a token key, see Credential Secret handling.

config takes:

KeyRequiredMeaningDefault
repositoryNameyesThe Git repository the generated Cortex workflows commit requests into
provideryesgithub or gitlab
integrationAliasyesThe Cortex Git integration alias
branchnoBranch the workflows commit tomain
pathnoDirectory within the repositorykratix-resource-requests

Requests are committed to <path>/<promise>/<namespace>-<name>.yaml.

What happens when a developer creates a request​

The create workflow registers <name> request (pending), owned by the requester, then commits the request to Git. Once GitOps applies the request, resource sync replaces the pending definition with the Resource definition. The exporter writes later status changes to Cortex custom data under status. See Send resource requests for create, update, deletion and reconciliation checks.

What gets deployed​

Alongside the usual generate → configure → writer pipeline, a Cortex portal runs:

  • A one-time, portal-scoped setup Job that idempotently ensures the shared Cortex relationship type and entity type this integration depends on exist. Editing that portal's connection configuration reruns its setup.
  • A long-lived status exporter, a Deployment and Service running one replica as the ske-portal-exporter Service Account, which pushes resource status changes to the Cortex API as they happen. The controller removes the exporter when its portal configuration is removed.

Tuning the exporter​

portals:
- name: prod
type: cortex
# ... url, secretRef, config as above
adapterConfig:
imagePullSecrets: # extra pull-secret names, always merged with syntasso-registry
- customer-registry
exporter:
deploymentSpec: # partial Deployment spec, merged into the exporter Deployment
template:
spec:
nodeSelector:
tier: portal
tolerations:
- key: dedicated
operator: Equal
value: portal
effect: NoSchedule

exporter.deploymentSpec is merged into the exporter Deployment. Prefer pod-level fields such as nodeSelector, tolerations and affinity. Controller-owned fields, including the exporter container itself, its Service Account, labels, credential injection and pull secrets, are always re-applied afterwards, so a containers entry in the overlay is discarded rather than replacing the exporter's own container.

Fixing the namespace​

adapterConfig.generate.args accepts --fixed-namespace=<value> for a Cortex portal, which fixes the namespace on the generated create workflow and hides the namespace input:

adapterConfig:
generate:
args:
- "--fixed-namespace=team-a"

The value must be a valid DNS-1123 label. This is portal-wide, so every Promise routed through the portal gets it.

The update and delete workflows are unaffected, since they act on an entity the user picks and take its namespace from the entity itself.

Renaming the identity fields​

Four annotations on a Promise change how the Name and Namespace inputs are labelled on its generated workflows:

AnnotationEffect
kratix.io/cortex-name-field-nameThe Name input's label
kratix.io/cortex-name-field-descriptionThe Name input's description
kratix.io/cortex-namespace-field-nameThe Namespace input's label
kratix.io/cortex-namespace-field-descriptionThe Namespace input's description

These are per-Promise and remain supported.

Deletion​

warning

Deleting a Promise removes every Cortex entity of that Promise's type, not just the Promise entity. The Portal Controller issues a bulk delete for the Promise's type before removing the Promise entity, its workflows and its entity type.

If Resources of that Promise still exist, their Cortex entities go with it. Detach the Promise from the portal first, by removing its kratix.io/portal-cortex label, if you want to keep them.

Deleting a single Resource request removes only that Resource's entity.

Entity naming​

Generated entities use predictable tags, which matters if you write Cortex queries or scorecards against them:

EntityTag
Promisepromise-<promise>
Resource<promise>-<name>-<namespace>

Resource entities carry the Promise's name as their Cortex type, sit in the kratix-resources group, and hold their Kubernetes identity in custom metadata.

Next steps​