From custom resources to a running app
Click any step on the map or the navigation below — or press Play to tour the sequence.
This is the multi-page printable view of this section. Click here to print.
CAP Operator takes the complexity out of running SAP Cloud Application Programming Model (CAP) applications on Kubernetes — so you ship features, not infrastructure.
Whether you’re building a full SaaS platform with hundreds of tenants or a lean shared service with no tenant lifecycle at all, CAP Operator handles the heavy lifting:
Deploy fast, deploy clean
Own your tenant lifecycle
Networking that just works
Built for production operations
The following interactive walkthrough shows the major automation steps handled by CAP Operator during application deployment — step through them, or press Play to watch the sequence:
Click any step on the map or the navigation below — or press Play to tour the sequence.
Explore the following sections to learn more.
Provisioning and operating an SAP Cloud Application Programming Model (CAP) application on a Kubernetes cluster requires deploying various components in addition to the CAP application server (see a list of typical components). Some of these components can be created during initial system provisioning, while others need to be created or updated at different points in the application lifecycle (Day 2 operations).
Using Helm charts to manage the deployment of a CAP application supports initial system provisioning, but further lifecycle operations (such as tenant provisioning) triggered by external components (SAP BTP) require manual adjustment of the deployed resources. For example, Istio VirtualService resources must be created during tenant provisioning to route incoming HTTP requests on the new tenant subdomain to the application server. Another limitation of Helm charts is the lack of control over the order in which resources are created.
You can gain greater control over deployment and automate lifecycle operations by extending the Kubernetes API with custom resources that describe CAP application components and their configuration, along with controllers to reconcile them. Like standard Kubernetes controllers, these custom controllers watch for changes in custom resource objects and work to bring the cluster state to the desired state.
CAP Operator comprises custom resource definitions that describe CAP application components, a controller that reconciles these resources, and additional components that support lifecycle management.
CAP Operator consists of the following components:
saas-registry service instances during tenant subscription and unsubscription.The following diagram shows how the main components interact when deployed to a cluster:
For more details about each component, see the following pages.
The CAP controller uses client-go from Kubernetes, which provides the tools and utilities needed to interact with the Kubernetes API server and manage the custom resources defined by CAP Operator.
The controller uses Informers to watch certain resources and invokes registered event handlers when these resources are modified. To streamline the processing of such notifications, rate-limiting queues are implemented that store changes and allow processing of items in independent reconciliation threads (goroutines). This design enables sequential processing of changed items and avoids conflicts.
The following namespaced custom resources are reconciled by the CAP controller:
CAPApplication: Defines a high-level application, its domains, and the consumed SAP BTP services.CAPApplicationVersion: A child resource of CAPApplication that contains container images used to deploy application components (workloads) of a specific version.CAPTenant: A child resource of CAPApplication that corresponds to an SAP BTP subaccount subscribed to the application.CAPTenantOperation: Represents a provisioning, deprovisioning, or upgrade operation on a tenant, scheduled as a child resource of a CAPTenant and executed as a sequence of specified steps.Parent-child relationships between custom resources are established by defining owner references for the children.
The Subscription Server handles HTTP requests from the SAP Software-as-a-Service Provisioning service for tenant subscription operations on SAP Cloud Application Programming Model applications installed in the cluster.
During the creation of a saas-registry service instance (in the provider subaccount), callback URLs are configured to point to the subscription server routes. Additionally, the getDependencies URLs can also be configured to point to the subscription server routes.
When a consumer tenant subscribes to an application managed by the operator, the subscription server receives the callback, validates the request using credentials from the corresponding SubscriptionProvider resource, and creates a Subscription resource in the namespace of the identified CAPApplication. The controller then creates the CAPTenant and drives it through the provisioning flow.
The subscription server returns an Accepted (202) response and starts a background routine that polls Subscription.status while the Subscription and CAPTenant resources are independently reconciled by the controller.
Once the tenant provisioning process completes (or fails), the tracking routine returns the appropriate status to the SaaS Registry via an asynchronous callback.
(More details about asynchronous tenant subscription)
This asynchronous approach avoids timeouts during synchronous calls and enables the scheduling of dedicated jobs (via CAPTenantOperation) for completing the subscription and performing any additional cluster tasks (for example, creating an Istio VirtualService for the tenant subdomain).
A full-stack application built with the SAP Cloud Application Programming Model has the following components:
Multi-tenant CAP-based applications consume services from SAP BTP such as SAP Authorization and Trust Management Service and SAP Software-as-a-Service Provisioning service. You need to create these service instances within an SAP BTP provider account along with service keys (bindings) that generate the credentials used by the application to access these services.
The application provides data models that are deployed to the connected database. An HTTP server exposes defined services and handles server-side application logic. For more details, see the SAP Cloud Application Programming Model documentation. It is also possible to split the application into multiple servers (services) that work together.
CAP provides the module @sap/cds-mtxs, which can be operated as a sidecar (a component running independently from the application server). This component handles requests related to tenant management, such as onboarding, which creates the required schema in the connected database. This module also supports triggering tenant management tasks as CLI commands.
The Approuter, or an extended version of it, authenticates requests (using the SAP Authorization and Trust Management Service) and routes them to the application servers or related services (for example, SAP HTML5 Application Repository service for SAP BTP).
Multiple SAP Fiori front-end applications can connect to the CAP application back end. These UI5 applications are deployed to the SAP HTML5 Application Repository service for SAP BTP and served from there. Similarly, the application can have content specific to other services that needs to be deployed.
CAP Operator now uses v1alpha2 as the default API version (from release 0.37.0). The new version removes the deprecated globalAccountId and domains fields from CAPApplication. See the CAPApplication resource reference for the updated spec.
The new Subscription resource represents an active consumer subscription to a CAP application. It is created and managed by the subscription server in response to SaaS Provisioning service callbacks. Learn more about the Subscription resource.
The new SubscriptionProvider resource is automatically maintained by the controller to cache subscription credentials and pre-computed dependency information for efficient handling of subscription requests. Learn more about the SubscriptionProvider resource.
CAP Operator now triggers a rollout of relevant workloads when credentials (service bindings) are updated. Learn more about Rollout on Credential Update.
As of version 0.31.0, the provider section in CAPApplication is deprecated and can be omitted entirely, even for multi-tenant applications. Omitting it also skips the creation of a provider tenant.
The subscription server now supports the getDependencies callback, enabling CAP applications to return dependencies during tenant subscription. Learn more about getDependencies support.
CAP Operator now allows any deployment workload to be exposed as a service. Learn more about Service Exposure.
CAP Operator now includes enhanced domain management features. Learn more about Domain Management.
CAP Operator now supports Services Only applications that are tenant-agnostic. Learn more about Services-Only Applications.
This page provides an overview of available methods to install CAP Operator on a Kubernetes cluster.
We recommend using a “Gardener” managed cluster to deploy CAP applications managed with CAP Operator.
Set up the following prerequisites in the Kubernetes cluster before installing CAP Operator:
The Istio service mesh is used for HTTP traffic management. CAP Operator creates Istio resources to manage incoming HTTP requests to the application and to route requests on specific (tenant) subdomains.
Determine the public ingress gateway subdomain and the overall shoot domain for the system, and specify them in the chart values. See here for an example.
Note: Istio promoted many of its APIs to v1 in the 1.22 release. As of CAP Operator release v0.11.0, Istio version >= 1.22 is therefore a prerequisite.
These operators manage SAP BTP service instances and service bindings from within the Kubernetes cluster.
If some SAP BTP services are not available for Kubernetes platforms, you can use cf-service-operator, which creates the services for a Cloud Foundry space and inserts the required access credentials as Secrets into the Kubernetes cluster.
Service credentials added as Kubernetes Secrets by these operators support additional metadata. If you do not use this feature, set
secretKey: credentialsin the spec to ensure that service credentials retain JSON data as-is. We recommend usingsecretKeyeven when credential metadata is available, to reduce the overhead of parsing multiple JSON attributes.
This component is available in “Gardener” managed clusters and is used to manage TLS certificates and issuers. Alternatively, you can use cert-manager.io cert-manager.
To install CAP Operator components, use the Helm chart published as an OCI package at oci://ghcr.io/sap/cap-operator-lifecycle/helm/cap-operator.
Create a namespace and install the Helm chart in that namespace by specifying the domain and dnsTarget for your subscription server, either:
kubectl create namespace cap-operator-system
helm upgrade -i -n cap-operator-system cap-operator oci://ghcr.io/sap/cap-operator-lifecycle/helm/cap-operator --set subscriptionServer.domain=cap-operator.<CLUSTER-DOMAIN> --set subscriptionServer.dnsTarget=public-ingress.<CLUSTER-DOMAIN>
YAML values file:kubectl create namespace cap-operator-system
helm upgrade -i -n cap-operator-system cap-operator oci://ghcr.io/sap/cap-operator-lifecycle/helm/cap-operator -f my-cap-operator-values.yaml
The values file my-cap-operator-values.yaml can have the following content:
subscriptionServer:
dnsTarget: public-ingress.<CLUSTER-DOMAIN>
domain: cap-operator.<CLUSTER-DOMAIN>
To enable monitoring via metrics emitted by CAP Operator components, set the following value:
monitoring:
enabled: true # <-- enables creation of service monitors for metrics emitted by CAP Operator components
To enable detailed operational metrics for the controller:
controller:
detailedOperationalMetrics: true
To use the Version Monitoring feature, provide a Prometheus server URL to the CAP Operator. When installing with the Helm chart, specify the following values:
controller:
versionMonitoring:
prometheusAddress: "http://prometheus-operated.monitoring.svc.cluster.local:9090" # <-- example of a Prometheus server running inside the same cluster
promClientAcquireRetryDelay: "2h"
metricsEvaluationInterval: "30m" # <-- interval at which version metrics are evaluated
On startup, the controller attempts to connect to the Prometheus server and fetch runtime information to verify the connection. If the connection fails, the controller retries after the delay specified in controller.versionMonitoring.promClientAcquireRetryDelay. See default values here.
NetworkPolicy resources required for connecting to the service in the Prometheus namespace are also created.The controller reconciles each resource type with a built-in default concurrency. To override these defaults, configure the values explicitly:
controller:
maxConcurrentReconciles:
capApplication: "1" # default: 1
capApplicationVersion: "3" # default: 3
capTenant: "10" # default: 10
capTenantOperation: "10" # default: 10
domain: "1" # default: 1
clusterDomain: "1" # default: 1
subscription: "10" # default: 10 or <value of capTenant config, if specified>
To control the rate at which the controller client sends requests to the Kubernetes API server, configure the QPS (queries per second) and burst values:
controller:
clientRateLimiting:
qps: "20" # <-- maximum queries per second
burst: "30" # <-- maximum burst for throttle
To introduce a delay before the controller rolls out workloads of relevant application versions on credential update (e.g. to allow a safe rollout window), set the rollout delay:
controller:
rolloutDelay: "1h" # <-- duration to wait before rolling out version workloads on credential update
To install the CAP Operator using CAP Operator Manager, run the following command:
kubectl apply -f https://github.com/SAP/cap-operator-lifecycle/releases/latest/download/manager_manifest.yaml
This creates the cap-operator-system namespace with CAP Operator Manager installed. Once the CAP Operator Manager pod is running, install the CAP Operator by running:
kubectl apply -n cap-operator-system -f https://github.com/SAP/cap-operator-lifecycle/releases/latest/download/manager_default_CR.yaml
This works only if the ingressGatewayLabels in your cluster match the following values:
ingressGatewayLabels:
- name: istio
value: ingressgateway
- name: app
value: istio-ingressgateway
If not, you must create the CAPOperator resource manually. For details, see the documentation.
See installation steps here: https://sap.github.io/cap-operator-lifecycle/docs/installation/kyma-cluster/
The following environment variables are used to configure CAP Operator.
CERT_MANAGER: The certificate manager used for TLS certificates. Possible values:gardener: “Gardener” certificate managementcert-manager.io: cert-manager.io cert-managerDNS_MANAGER: The external DNS manager to use. Possible values:gardener: “Gardener” external DNS managerkubernetes: External DNS management from KubernetesPROMETHEUS_ADDRESS: URL of the Prometheus server for executing PromQL queries, for example http://prometheus-operated.monitoring.svc.cluster.local:9090. If not set, the controller still runs the version cleanup loop; however, only versions whose workloads have no deletionRules defined are eligible for cleanup — versions that have deletionRules are skipped until a Prometheus connection becomes available.PROM_ACQUIRE_CLIENT_RETRY_DELAY: Time delay between retries when Prometheus client creation or connection check fails.METRICS_EVAL_INTERVAL: Time interval between iterations where outdated versions are identified and queued for evaluation.MAX_CONCURRENT_RECONCILES_CAP_APPLICATION: Maximum number of concurrent reconciles for CAPApplication (for example, 1).MAX_CONCURRENT_RECONCILES_CAP_APPLICATION_VERSION: Maximum number of concurrent reconciles for CAPApplicationVersion (for example, 3).MAX_CONCURRENT_RECONCILES_CAP_TENANT: Maximum number of concurrent reconciles for CAPTenant (for example, 10).MAX_CONCURRENT_RECONCILES_CAP_TENANT_OPERATION: Maximum number of concurrent reconciles for CAPTenantOperation (for example, 10).MAX_CONCURRENT_RECONCILES_DOMAIN: Maximum number of concurrent reconciles for Domain (for example, 1).MAX_CONCURRENT_RECONCILES_CLUSTER_DOMAIN: Maximum number of concurrent reconciles for ClusterDomain (for example, 1).MAX_CONCURRENT_RECONCILES_SUBSCRIPTION: Maximum number of concurrent reconciles for Subscription (for example, 10).CLIENT_QPS: Maximum queries per second for the Kubernetes client-side rate limiter (for example, 25). Defaults to 25.CLIENT_BURST: Maximum burst size for the Kubernetes client-side rate limiter (for example, 50). Defaults to 50.ROLLOUT_DELAY: Delay window used to batch credential-rotation work triggered by BTP service secret changes. Accepts Go duration strings (for example, 30m, 2h). Defaults to 1h. Values below 30s are clamped to 30s.CAP-based applications use various SAP BTP services created in a provider subaccount. Before deploying the application, create a global account and entitle the required services, then create a provider subaccount where the service instances can be created. See the SAP BTP account administration documentation for details.
A multi-tenant CAP-based application consumes the following SAP BTP services. Some parameters require special attention during service instance creation. Service keys (bindings) generate access credentials that must be provided as Kubernetes Secrets in the namespace where the application is deployed.
Other services (not listed here) may also be required depending on your application (for example, SAP HTML5 Application Repository service for SAP BTP, Business Logging, and others).
Note: If some SAP BTP services are not available on Kubernetes, enable Cloud Foundry for the provider subaccount. In such cases, use the cf-service-operator to manage service instances and bindings directly from within the Kubernetes cluster. It automatically generates Secrets containing service access credentials based on the service bindings.
The parameter oauth2-configuration.redirect-uris must include the domain used by the application. For example, if the application is hosted in a “Gardener” managed cluster, the entry may have the form https://*<application-specific-prefix>.<cluster-id>.<gardener-project-id>.shoot.url.k8s.example.com/**.
Scopes required for asynchronous tenant subscription operations must also be included. Additionally, check the CAP Multitenancy documentation for additional required scopes.
parameters:
authorities:
- $XSAPPNAME.mtcallback
- $XSAPPNAME.mtdeployment
oauth2-configuration:
redirect-uris:
- https://*my-cap-app.cluster-x.my-project.shoot.url.k8s.example.com/**
role-collections:
...
role-templates:
...
scopes:
- description: UAA
name: uaa.user
- description: With this scope set, the callbacks for tenant onboarding, offboarding, and getDependencies can be called
grant-as-authority-to-apps:
- $XSAPPNAME(application,sap-provisioning,tenant-onboarding)
name: $XSAPPNAME.Callback
- description: Async callback to update the saas-registry (provisioning succeeded/failed)
name: $XSAPPNAME.subscription.write
- description: Deploy applications
name: $XSAPPNAME.mtdeployment
- description: Subscribe to applications
grant-as-authority-to-apps:
- $XSAPPNAME(application,sap-provisioning,tenant-onboarding)
name: $XSAPPNAME.mtcallback
...
When using multiple SAP Authorization and Trust Management Service instances in the application (for example, one for application and another for apiaccess), set the primary instance using the annotation sme.sap.com/primary-xsuaa with the name of the service instance:
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
annotations:
"sme.sap.com/primary-xsuaa": "my-cap-app-uaa" # Tells CAP Operator which UAA instance to use for the application
name: test-cap-01
...
spec:
btp:
services:
- class: xsuaa
name: my-cap-app-uaa-api
secret: my-cap-app-uaa-api-bind-cf
- class: xsuaa
name: my-cap-app-uaa
secret: my-cap-app-uaa-bind-cf
- class: saas-registry
name: my-cap-app-saas-registry
secret: my-cap-app-saas-bind-cf
...
btpAppName: my-cap-app
...
When creating an instance of the SaaS Provisioning service, configure asynchronous tenant subscription callbacks. See Register Your Multi-Tenant Application/Service in SaaS Provisioning for details.
parameters:
appName: <short-application-name>
appUrls:
callbackTimeoutMillis: 300000 # <-- fails the subscription process when no response is received within this timeout
getDependencies: https://<cap-operator-subscription-server-domain>/dependencies/<providerSubaccountId>/<btpAppName>/ # the /getDependencies route is forwarded directly to CAP Operator (Subscription Server) and must be specified as such
onSubscription: https://<cap-operator-subscription-server-domain>/provision/tenants/{tenantId} # <-- the /provision route is forwarded directly to CAP Operator (Subscription Server) and must be specified as such
onSubscriptionAsync: true
onUnSubscriptionAsync: true
An SAP HANA Cloud instance (preferably shared and accessible from the provider subaccount) is required. Note the instance ID of the database for use in relevant workloads. The SAP HANA Schemas & HDI Containers service must also be entitled for the provider subaccount.
The SAP Service Manager service allows CAP to retrieve schema-specific (tenant-specific) credentials for connecting to the SAP HANA Cloud database.
Deploying a multi-tenant CAP application involves defining several key resources provided by CAP Operator. These resources manage the application’s runtime components and external traffic routing.
CAPApplication (capapplications.sme.sap.com): A namespaced resource that represents the application.
CAPApplicationVersion (capapplicationversions.sme.sap.com): A namespaced resource that specifies the version of the application being deployed. It ensures that all runtime components (Deployments, Services, and Jobs) are created with the specified image version in the same namespace.
Domain resources: These resources determine how external traffic reaches the application and how DNS and TLS settings are applied. You can choose between:
domains.sme.sap.com): A namespaced resource for a single application.clusterdomains.sme.sap.com): A cluster-scoped resource that can be shared across multiple applications.Create the CAPApplication and CAPApplicationVersion resources in the same namespace. This allows CAP Operator to manage all associated runtime components. For external traffic management, define either a Domain or ClusterDomain resource.
apiVersion: sme.sap.com/v1alpha2
kind: Domain
metadata:
namespace: cap-app-01
name: cap-app-01-primary
spec:
domain: my.cluster.shoot.url.k8s.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Simple
dnsMode: Wildcard
The ClusterDomain resource is cluster-scoped and suited for global or shared domain configurations — for example, when multiple applications share the same external domain. See API Reference.
apiVersion: sme.sap.com/v1alpha2
kind: ClusterDomain
metadata:
name: common-external-domain
spec:
domain: my.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Simple
dnsMode: Subdomain
The CAPApplication resource describes the high-level attributes of an application: the SAP BTP account where it is hosted, the consumed SAP BTP services, and references to Domain and ClusterDomain resources. See API Reference.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: cap-app-01
namespace: cap-app-01
spec:
btpAppName: cap-app-01 # <-- short name (equivalent to SAP BTP XSAPPNAME)
btp:
services:
- class: xsuaa # <-- SAP BTP service technical name
name: app-uaa # <-- name of the service instance
secret: cap-app-01-uaa-bind-cf # <-- secret containing credentials for accessing the service (must exist in the same namespace)
- class: saas-registry
name: app-saas-registry
secret: cap-app-01-saas-bind-cf
- class: service-manager
name: app-service-manager
secret: cap-app-01-svc-man-bind-cf
- class: destination
name: app-destination
secret: cap-app-01-dest-bind-cf
- class: html5-apps-repo
name: app-html5-repo-host
secret: cap-app-01-html5-repo-bind-cf
- class: html5-apps-repo
name: app-html5-repo-runtime
secret: cap-app-01-html5-rt-bind-cf
- class: some-content-service
name: app-some-content-service
secret: cap-app-01-some-content-service-bind-cf
domainRefs:
- kind: Domain
name: cap-app-01-primary # <-- reference to Domain resource in the same namespace
- kind: ClusterDomain
name: common-external-domain # <-- reference to ClusterDomain resource in the cluster
providerSubaccountId: provider-subaccount-id
The CAPApplicationVersion describes the components of an application version, including the container images to use and the services consumed by each component. It must be created in the same namespace as the CAPApplication and must reference it. See API Reference.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-01-1
namespace: cap-app-01
spec:
capApplicationInstance: cap-app-01 # <-- reference to CAPApplication in the same namespace
version: "1" # <-- semantic version
registrySecrets:
- regcred
workloads:
- name: cap-backend
consumedBTPServices: # <-- services used by the application server (defined in CAPApplication). Credential secrets are mounted as volumes on component pods.
- app-uaa
- app-service-manager
- app-saas-registry
deploymentDefinition:
type: CAP # <-- indicates the CAP application server
image: app.some.repo.example.com/srv/server:0.0.1
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: app-router
consumedBTPServices:
- app-uaa
- app-destination
- app-saas-registry
- app-html5-repo-runtime
- app-some-content-service
deploymentDefinition:
type: Router
image: app.some.repo.example.com/approuter/approuter:0.0.1
env:
- name: PORT
value: "4000"
- name: TENANT_HOST_PATTERN
value: "^(.*).(my.cluster.shoot.url.k8s.example.com|my.example.com)"
- name: service-content
consumedBTPServices:
- app-uaa
- app-html5-repo-host
- app-some-content-service
jobDefinition:
type: Content
image: app.some.repo.example.com/approuter/content:0.0.1
backoffLimit: 1
- name: tenant-op
consumedBTPServices:
- app-uaa
jobDefinition:
type: TenentOperation
image: app.some.repo.example.com/srv/mtxs:0.0.1
backoffLimit: 1
NOTE: The example above shows a minimal
CAPApplicationVersion. For a complete configuration with explanations, see here.
The CAP Operator controller reacts to these objects and creates additional resources that constitute a running application:
VCAP_SERVICES environment variableThe content deployer deploys content or configuration to SAP BTP services before they are consumed.
Once these resources are available, the CAPApplicationVersion status changes to Ready. The controller reconciles tenants once subscriptions are triggered for the application. See tenant subscription for details on how the CAPTenant resource is reconciled.
The
CAPApplicationVersionresource is immutable — its spec must not be modified after deployment. This is enforced by webhooks, which we recommend keeping active (the default).
NOTE: Follow the recommended security measures to safeguard exposed workloads.
NOTE: If SAP BTP service credentials are rotated after deployment, CAP Operator can automatically restart affected workloads. See Rollout on Credential Update to learn how to enable this.
CAP Operator manages networking for CAP applications through Domain and ClusterDomain resources. These resources control TLS handling, ingress routing, and DNS setup for your application’s domains. A CAPApplication references them via domainRefs.
Use a Domain resource for a domain that belongs to a specific application namespace. The operator creates the Gateway and DNSEntry in that namespace. The Certificate placement depends on the certificate manager in use — see the Domain resource reference for details.
apiVersion: sme.sap.com/v1alpha2
kind: Domain
metadata:
namespace: cap-app-01
name: cap-app-01-primary
spec:
domain: my.cluster.shoot.url.k8s.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Simple # Simple (default), Mutual, or OptionalMutual
dnsMode: Wildcard # None (default), Wildcard, Subdomain, or Custom
The dnsTarget field is optional. If omitted, the target is derived from the Istio Ingress Gateway selected by ingressSelector.
Use a ClusterDomain resource for a domain shared across multiple applications or namespaces. The operator creates the Gateway and DNSEntry in the CAP Operator installation namespace. The Certificate placement depends on the certificate manager in use — see the ClusterDomain resource reference for details.
apiVersion: sme.sap.com/v1alpha2
kind: ClusterDomain
metadata:
name: common-external-domain
spec:
domain: my.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Simple # Simple (default) or Mutual
dnsMode: Subdomain # None (default), Wildcard, Subdomain, or Custom
When X509 client authentication is required (tlsMode: Mutual or OptionalMutual), provide additional CA certificates for Istio to verify client certificates via certConfig.additionalCACertificate.
Once your Domain and ClusterDomain resources are defined, reference them in the CAPApplication spec using domainRefs:
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: cap-app-01
namespace: cap-app-01
spec:
domainRefs:
- kind: Domain
name: cap-app-01-primary # Namespaced Domain resource
- kind: ClusterDomain
name: common-external-domain # Shared ClusterDomain resource
The first entry in domainRefs is treated as the primary domain. You can mix Domain and ClusterDomain references in the same application.
domains sectionEarlier versions of CAP Operator used an inline domains section directly in CAPApplication. This section is deprecated and no longer supported. If you are still using it, migrate to domainRefs as described below.
domains sectionapiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: cap-app-01
namespace: cap-app-01
spec:
domains:
istioIngressGatewayLabels:
- name: app
value: istio-ingressgateway
- name: istio
value: ingressgateway
primary: my.cluster.shoot.url.k8s.example.com
secondary:
- my.example.com
domainRefs with explicit resourcesCreate the Domain and ClusterDomain resources manually (see sections above), then update your CAPApplication to use domainRefs.
The mutating webhook has been removed as of v0.37.0
The automatic migration routine was available from v0.15.0 through v0.25.0 and has been removed as of v0.26.0. If you need this migration, first upgrade to v0.25.0 (or lower), allow the migration to complete, and then upgrade to the latest release.
Upgrading to CAP Operator v0.15.0 through v0.25.0 triggered an automatic migration routine that:
CAPApplication resources.domains.Domain or ClusterDomain resources.CAPApplication resources to use domainRefs.After migrating, confirm the resources are in the expected state:
kubectl get capapplication -n <your-app-namespace> <your-ca-name> -o yaml
Ensure that:
domains section is absent.domainRefs entries are present.Domain or ClusterDomain resources exist in the cluster.Domain or ClusterDomainWhen dnsMode is set to Custom, the operator creates DNS entries according to the dnsTemplates field instead of the fixed patterns used by Wildcard and Subdomain modes. This lets you generate multiple DNS records per domain, map subdomains to external names, or combine wildcard and per-subdomain entries in one resource.
DNS entry creation requires the Gardener external-dns-management controller. When using the Kubernetes DNS manager, dnsMode is ignored and no DNS entries are created regardless of the mode chosen.
Each entry in dnsTemplates produces one or more DNS records. Up to 10 templates are allowed per resource. The name and target fields are rendered using Go templates. A template has two fields:
| Field | Description |
|---|---|
name | DNS name for the record — rendered as a Go template |
target | DNS target (hostname or IP) — rendered as a Go template |
The following variables are available in both name and target:
| Variable | Value |
|---|---|
{{.domain}} | The value of spec.domain |
{{.dnsTarget}} | The effective ingress target: spec.dnsTarget, or DNS_TARGET env var, or the load balancer service annotation on the Istio Ingress Gateway |
{{.subDomain}} | A subdomain collected from referencing applications — see Subdomain expansion |
Functions from the Slim Sprig library are available in all templates.
When {{.subDomain}} appears in a template’s name, the operator expands that template once for each subdomain observed across all CAPApplication resources that reference the domain. A template whose name does not contain {{.subDomain}} is rendered exactly once.
Subdomains are collected from two sources and tracked in CAPApplication.status.observedSubdomains:
CAPTenant.spec.subDomain — each tenant’s subdomainCAPApplicationVersion.spec.serviceExposures[].subDomain — subdomains declared in version service exposures{{.subDomain}} may also be used in target, but only when name also contains {{.subDomain}}.
If the same subdomain appears in two different CAPApplication resources that both reference the same domain, that subdomain is skipped for the second application and a SubdomainAlreadyInUse warning event is raised on it.
The following configuration combines a wildcard record with per-subdomain records on the primary domain, and a CNAME chain that maps each subdomain on an external domain to the corresponding subdomain on the primary domain:
apiVersion: sme.sap.com/v1alpha2
kind: Domain # also applies to ClusterDomain
metadata:
namespace: cap-app-01
name: cap-app-01-primary
spec:
domain: my.cluster.shoot.url.k8s.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
dnsMode: Custom
dnsTemplates:
- name: '*.{{ .domain }}'
target: '{{ .dnsTarget }}'
- name: '{{ .subDomain }}.{{ .domain }}'
target: '{{ .dnsTarget }}'
- name: '{{ .subDomain }}.myapp.com'
target: '{{ .subDomain }}.{{ .domain }}'
For an application with subdomains tenant-a and tenant-b, this produces five DNS records:
| DNS name | Target |
|---|---|
*.my.cluster.shoot.url.k8s.example.com | <ingress target> |
tenant-a.my.cluster.shoot.url.k8s.example.com | <ingress target> |
tenant-b.my.cluster.shoot.url.k8s.example.com | <ingress target> |
tenant-a.myapp.com | tenant-a.my.cluster.shoot.url.k8s.example.com |
tenant-b.myapp.com | tenant-b.my.cluster.shoot.url.k8s.example.com |
Domain or ClusterDomainWhen tlsMode is set to Mutual or OptionalMutual on a Domain or ClusterDomain, Istio requires a CA certificate to verify client certificates presented during the TLS handshake. Provide this certificate via certConfig.additionalCACertificate.
The operator stores the certificate as a Kubernetes Secret (key: ca.crt) in the Istio Ingress Gateway namespace, where Istio reads it.
apiVersion: sme.sap.com/v1alpha2
kind: ClusterDomain # also applies to Domain
metadata:
name: cap-example-domain
spec:
domain: myapp.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Mutual
certConfig:
additionalCACertificate: |
-----BEGIN CERTIFICATE-----
MIIFZjCCA06gAwIBAgIQGHcPvmUGa79M6pM42bGFYjANBgkqhkiG9w0BAQsFADBN
...
-----END CERTIFICATE-----
Removing certConfig.additionalCACertificate from the spec causes the operator to delete the corresponding secret.
IssuerRef for TLS certificates on Domain or ClusterDomainWhen the operator is installed with the cert-manager certificate manager (configured via the CERT_MANAGER environment variable), it creates a cert-manager Certificate resource for each Domain or ClusterDomain. Every Certificate must reference an issuer. By default the operator uses a ClusterIssuer named cluster-ca. Use certConfig.certManager.issuerRef to override this with any issuer available in your cluster.
If certConfig.certManager is not set, the operator uses the following issuer reference:
| Field | Default |
|---|---|
name | cluster-ca |
kind | ClusterIssuer |
group | cert-manager.io |
Set certConfig.certManager.issuerRef on a Domain or ClusterDomain to point to any cert-manager issuer:
apiVersion: sme.sap.com/v1alpha2
kind: Domain # also applies to ClusterDomain
metadata:
namespace: cap-app-01
name: cap-app-01-primary
spec:
domain: my.cluster.shoot.url.k8s.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
certConfig:
certManager:
issuerRef:
name: my-cluster-issuer # name of the issuer
kind: ClusterIssuer # ClusterIssuer or Issuer
group: cert-manager.io # optional; defaults to cert-manager.io
issuerRef fields| Field | Required | Description |
|---|---|---|
name | yes | Name of the cert-manager issuer to use |
kind | no | ClusterIssuer (cluster-scoped) or Issuer (namespace-scoped). Defaults to Issuer if omitted |
group | no | API group of the issuer. Defaults to cert-manager.io if omitted |
When using cert-manager, the Certificate resource is created in the Istio Ingress Gateway namespace. This differs from the Gardener certificate manager, where the certificate’s secretRef uses a cross-namespace reference back to the Domain namespace.
In CAP Operator, a valid tenant for an application is represented by the CAPTenant resource. It references the CAPApplication it belongs to and specifies the details of the SAP BTP subaccount that represents the tenant.
apiVersion: sme.sap.com/v1alpha2
kind: CAPTenant
metadata:
name: cap-app-01-consumer
namespace: cap-app-01
spec:
capApplicationInstance: cap-app-01 # <-- reference to the CAPApplication
subDomain: app-consumer
tenantId: aa2bae55d7b5-1279-456564-a7b0-aa2bae55d7b5
version: "1.0.0" # <-- expected version of the application
versionUpgradeStrategy: always # <-- always / never
Tenant provisioning begins when a consumer subaccount subscribes to the application, either via the SAP BTP cockpit or using the SaaS Provisioning service APIs. This triggers an asynchronous callback from the SaaS Provisioning service into the cluster, which is handled by the subscription server. The subscription server validates the request using credentials from the SubscriptionProvider resource and creates a Subscription resource in the namespace of the identified CAPApplication. The controller, observing the new Subscription, then creates a CAPTenant instance to represent the consumer tenant.
Subscription and CAPTenant resources must not be created or deleted manually. Subscription resources are managed by the subscription server in response to provisioning callbacks, while CAPTenant resources are created and managed by the controller as children of Subscription resources.
The controller, observing the new CAPTenant (created as a child of the Subscription), initiates the provisioning process by creating a CAPTenantOperation resource representing the provisioning operation.
apiVersion: sme.sap.com/v1alpha2
kind: CAPTenantOperation
metadata:
name: cap-app-01-consumer-sgz8b
namespace: cap-app-01
spec:
capApplicationVersionInstance: cav-cap-app-01-1 # <-- latest CAPApplicationVersion in Ready state
subDomain: app-consumer
tenantId: aa2bae55d7b5-1279-456564-a7b0-aa2bae55d7b5
operation: provisioning # <-- valid values are provisioning, deprovisioning and upgrade
steps:
- name: tenant-operation # <-- derived from the workload of type TenantOperation defined in the CAPApplicationVersion
type: TenantOperation
The CAPTenantOperation is reconciled to create Kubernetes Jobs (steps) derived from the latest CAPApplicationVersion in Ready state. The steps include a TenantOperation job and optional CustomTenantOperation steps. The TenantOperation step uses built-in CLI-based tenant operations from @sap/cds-mtxs to execute tenant provisioning.
The CAPTenant reaches a Ready state only after:
CAPTenantOperation steps complete successfully, andVirtualService is created to route HTTP requests on the tenant subdomain to the application.During provisioning, the SaaS Provisioning service calls a getDependencies endpoint to retrieve the list of reuse services that the multitenant application requires. The CAP Operator subscription server exposes this endpoint. The dependency list is pre-computed by the controller at CAPApplication reconciliation time and cached in the SubscriptionProvider resource. The subscription server reads and returns the cached list directly, without re-inspecting CAPApplication service credentials at request time.
The subscription server exposes the following endpoint:
GET /dependencies/{providerSubaccountId}/{appName}/
The providerSubaccountId and appName path parameters identify the corresponding CAPApplication resource. The system authorizes the request using the same mechanism as the provisioning endpoints (Bearer token).
The appName value in the URL must match spec.btpAppName of the CAPApplication resource. Because it is also registered with the SaaS Provisioning service, it should follow the service’s xsappname conventions.
A successful response returns a JSON array of objects. Each object contains the xsappname of a qualifying service:
[
{ "xsappname": "my-destination-service!b42" },
{ "xsappname": "my-auditlog-service!b7" }
]
The controller iterates over all BTP services listed in CAPApplication.spec.btp.services. For each service, it reads the associated Kubernetes secret, parses the credentials, and determines whether to include the service in the pre-computed dependency list.
The xsappname is read from either the top-level xsappname field or the nested uaa.xsappname field in the service credentials. If not found, the service is excluded from the response.
subscriptionDependencyEach entry in spec.btp.services can include an optional subscriptionDependency field that controls whether the service is included:
| Value | Behaviour |
|---|---|
Auto (default) | The operator determines inclusion based on service class and credentials (see below) |
Always | Includes the service regardless of class |
Never | Excludes the service regardless of class or credentials |
spec:
btp:
services:
- name: my-destination
class: destination
secret: my-destination-secret
subscriptionDependency: Always # force inclusion
- name: my-xsuaa
class: xsuaa
secret: my-xsuaa-secret
subscriptionDependency: Never # force exclusion
- name: my-auditlog
class: auditlog
secret: my-auditlog-secret
# subscriptionDependency omitted → Auto
Auto qualification rules
When subscriptionDependency is set to Auto or omitted, the system includes the service if any of the following conditions apply:
"saasregistryenabled": trueclass is destinationclass is connectivityclass is auditlog and the credential plan is oauth2This behavior aligns with the implementation in the @sap/approuter package.
When a tenant unsubscribes from the application, the subscription server receives the request, locates the corresponding Subscription resource, and submits a deletion request to the Kubernetes API server.
The controller processes the deletion by initiating deprovisioning of the owned CAPTenant via a CAPTenantOperation of type deprovisioning. The CAPTenantOperation creates the corresponding Jobs (steps) that execute the tenant deprovisioning. Once deprovisioning completes successfully, the Subscription finalizer is removed, allowing Kubernetes to complete the deletion.
As of version 0.34.0, deleting a CAPApplication does not automatically remove existing tenants. Instead, the CAPApplication enters a Deleting state and its deletion is blocked until all associated CAPTenant resources have been removed.
Before a CAPApplication can be fully deleted:
CAPTenant resource will be automatically deleted.Once all tenants are cleaned up, the operator proceeds to delete the remaining child resources (CAPApplicationVersion instances and other CRs) and completes the CAPApplication deletion.
Prior to version 0.34.0, deleting a CAPApplication automatically triggered deprovisioning of all existing tenants. If you are upgrading from an earlier version, be aware of this change in behavior.
An important lifecycle aspect of operating multi-tenant CAP applications is the tenant upgrade process. With CAP Operator, tenant upgrades can be fully automated by providing a new CAPApplicationVersion custom resource.
As covered in initial deployment, the CAPApplicationVersion resource describes the workloads of an application version, including the container image and services consumed by each component. To upgrade the application, create a new CAPApplicationVersion with updated image values for each component and a higher semantic version in the version field. See API Reference.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-01-2
namespace: cap-app-01
spec:
capApplicationInstance: cap-cap-app-01 # <-- reference to CAPApplication in the same namespace
version: "2.0.1" # <-- semantic version
registrySecrets:
- regcred
workloads:
- name: cap-backend
consumedBTPServices:
- app-uaa
- app-service-manager
- app-saas-registry
deploymentDefinition:
type: CAP # <-- indicates the CAP application server
image: app.some.repo.example.com/srv/server:0.0.2
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: app-router
consumedBTPServices:
- app-uaa
- app-destination
- app-saas-registry
- app-html5-repo-runtime
- app-some-content-service
deploymentDefinition:
type: Router
image: app.some.repo.example.com/approuter/approuter:0.0.2
env:
- name: PORT
value: 4000
- name: TENANT_HOST_PATTERN
value: "^(.*).(my.cluster.shoot.url.k8s.example.com|my.example.com)"
- name: service-content
consumedBTPServices:
- app-uaa
- app-html5-repo-host
- app-some-content-service
jobDefinition:
type: Content
image: app.some.repo.example.com/approuter/content:0.0.2
backoffLimit: 1
- name: tenant-operation
consumedBTPServices:
- app-uaa
- app-service-manager
- app-saas-registry
jobDefinition:
type: TenantOperation
image: app.some.repo.example.com/approuter/content:0.0.2
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: notify-upgrade
consumedBTPServices: []
jobDefinition:
type: CustomTenantOperation
image: app.some.repo.example.com/approuter/content:0.0.2
command: ["npm", "run", "notify:upgrade"]
backoffLimit: 1
env:
- name: TARGET_DL
value: group_xyz@sap.com
tenantOperations:
upgrade:
- workloadName: tenant-operation
- workloadName: notify-upgrade
continueOnFailure: true
Note that compared to version “1” used for initial deployment, new workloads of type TenantOperation and CustomTenantOperation have been added.
The CAP Operator controller reacts to the new CAPApplicationVersion resource by triggering a new Deployment for the application server and router, and running the content deployment Job. Once the new CAPApplicationVersion is Ready, the controller automatically upgrades all relevant tenants by updating the version attribute on the CAPTenant resources.
CAPTenant reconciliation changes the tenant state to Upgrading and creates a CAPTenantOperation resource of type upgrade.
apiVersion: sme.sap.com/v1alpha2
kind: CAPTenantOperation
metadata:
name: cap-app-01-provider-fgdfg
namespace: cap-app-01
spec:
capApplicationVersionInstance: cav-cap-app-01-2
subDomain: cap-provider
tenantId: aa2bae55d7b5-1279-456564-a7b0-aa2bae55d7b5
operation: upgrade # possible values are provisioning / upgrade / deprovisioning
steps:
- name: "tenant-operation"
type: TenantOperation
- name: "notify-upgrade"
type: CustomTenantOperation
continueOnFailure: true # <-- indicates that the overall operation may proceed even if this step fails
The CAPTenantOperation creates Jobs for each step and executes them sequentially until all Jobs complete or one fails. The CAPTenant is notified of the result and updates its state accordingly.
When the CAPTenantOperation completes successfully, the VirtualService managed by the CAPTenant is updated to route HTTP traffic to the Deployments of the newer CAPApplicationVersion. Once all tenants are upgraded, the outdated CAPApplicationVersion can be deleted.
You can optionally enable Version Affinity for multi-tenant applications by adding the annotation sme.sap.com/enable-version-affinity: "true" to the CAPApplication resource. With this experimental feature, users remain on their currently active CAPApplicationVersion during an upgrade until their session expires or they log out.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: test-ca-01
namespace: default
annotations:
sme.sap.com/enable-version-affinity: "true" # <-- enable version affinity
spec:
btp:
services:
- class: xsuaa
name: cap-uaa
secret: cap-cap-01-uaa-bind-cf
....
....
By default, CAP Operator recognizes logout and logoff as logout endpoints. If your application uses a different endpoint, specify it using the sme.sap.com/logout-endpoint annotation on your CAPApplicationVersion resource (without a leading slash).
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-01-2
namespace: cap-app-01
annotations:
sme.sap.com/logout-endpoint: "custom-logout" # <-- specify custom logout endpoint
spec:
capApplicationInstance: cap-cap-app-01
version: "2.0.1"
registrySecrets:
- regcred
This guide explains how to deploy applications with tenant-agnostic service workloads. These workloads can be part of multi-tenant applications or standalone applications that are entirely tenant-agnostic.
The serviceExposures section in the CAPApplicationVersion configuration is used to expose workloads. Each entry in the serviceExposures array specifies a subdomain under which workloads are accessible, with support for multiple routes per subdomain.
For details on configuring routes, see the Route API reference.
spec:
workloads:
- name: cap-backend-service
consumedBTPServices:
- cap-uaa
- cap-saas-reg
deploymentDefinition:
type: CAP # <-- possible values are CAP / Router / Additional / Service
image: some.repo.example.com/cap-app/server:3.22.11
env:
- name: HOME
value: "SAP"
replicas: 3
ports:
- name: app-port
port: 4004
- name: tech-port
port: 4005
- name: api
port: 8000
- name: api-v2
port: 8001
appProtocol: http
- name: router
consumedBTPServices:
- cap-uaa
- cap-apps-repo
deploymentDefinition:
type: Router
image: some.repo.example.com/cap-app/app-router:1.0.1
ports:
- name: router-port
port: 5000
- name: app
consumedBTPServices:
- cap-uaa
- cap-db
deploymentDefinition:
type: Service
image: some.repo.example.com/cap-app/app:4.0.1
ports:
- name: app-port
port: 5000
- name: service-content
consumedBTPServices:
- app-uaa
- app-html5-repo-host
- app-some-content-service
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/content:0.0.1
backoffLimit: 1
serviceExposures:
- subDomain: service
routes:
- workloadName: cap-backend-service
port: 4004
- subDomain: api
routes:
- workloadName: cap-backend-service
port: 8001
path: /api/v2
- workloadName: cap-backend-service
port: 8000
path: /api
- subDomain: app
routes:
- workloadName: app
port: 5000
For a cluster domain like my.cluster.shoot.url.k8s.example.com, the configuration generates URLs like:
service.my.cluster.shoot.url.k8s.example.com for cap-backend-service on port 4004.api.my.cluster.shoot.url.k8s.example.com/api/v2 for cap-backend-service on port 8001.api.my.cluster.shoot.url.k8s.example.com/api for cap-backend-service on port 8000app.my.cluster.shoot.url.k8s.example.com for app on port 5000.In the example above, the router workload is not exposed through serviceExposures. However, in multi-tenant scenarios, it may be exposed per tenant subdomain as usual.
Ensure routes are ordered correctly to prevent routing errors. When multiple routes are defined for a subdomain, more specific paths must come before more general ones. For example, in the configuration above, the api subdomain requires /api/v2 to be defined before /api.
Services-only applications do not require tenant-specific configurations. Therefore, the provider section is omitted from the CAPApplication resource. The CAPApplicationVersion may include only Content jobs and no tenant-related jobs. The rest of the configuration for your services-only application remains the same.
Create a CAPApplication resource without a provider section:
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: test-ca-01
namespace: default
spec:
btp:
services:
- class: xsuaa
name: cap-uaa
secret: cap-cap-01-uaa-bind-cf
- class: xsuaa
name: cap-uaa2
secret: cap-cap-01-uaa2-bind-cf
- class: service-manager
name: cap-service-manager
secret: cap-cap-01-svc-man-bind-cf
btpAppName: test-cap-01
domainRefs:
- kind: Domain
name: cap-app-01-primary
- kind: ClusterDomain
name: common-external-domain
providerSubaccountId: provider-subaccount-id
Create a CAPApplicationVersion in the same namespace as the CAPApplication with service workloads and any content jobs.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
name: cav-ca-app-01-1
namespace: default # Same namespace as CAPApplication
spec:
capApplicationInstance: test-ca-01 # Reference to the CAPApplication
version: "0.0.1"
registrySecrets:
- regcred
workloads:
- name: cap-backend-service
consumedBTPServices: # Services used by this workload
- app-uaa
- app-db
- app-saas-registry
deploymentDefinition:
type: CAP
image: app.some.repo.example.com/srv/server:0.0.1
env:
- name: CDS_ENV
value: production
ports:
- name: server
port: 4004
appProtocol: http
- name: api
port: 8000
appProtocol: http
- name: metrics
port: 4005
appProtocol: http
- name: api
consumedBTPServices: # Services used by this workload
- app-uaa
- app-db
deploymentDefinition:
type: Service
image: app.some.repo.example.com/srv/api:0.0.1
env:
- name: CDS_ENV
value: production
ports:
- name: apiv2
port: 8000
appProtocol: http
- name: api
port: 8001
appProtocol: http
- name: service-content # Example content job
consumedBTPServices:
- app-uaa
- app-html5-repo-host
- app-some-content-service
jobDefinition:
type: Content
image: app.some.repo.example.com/approuter/content:0.0.1
backoffLimit: 1
serviceExposures:
- subDomain: service
routes:
- workloadName: cap-backend-service
port: 4004
- subDomain: api
routes:
- workloadName: api
port: 8000
path: /api/v2
- workloadName: api
port: 8001
path: /api
CAPApplicationVersion causes any service-related VirtualService resources to route HTTP traffic to the workloads of that CAPApplicationVersion.When SAP BTP service credentials are rotated — for example, by a credential rotation tool or by re-binding a service instance — the Kubernetes Secrets holding those credentials are updated. By default, running application workloads are not restarted and continue to use the old credentials until the next deployment or a manual rollout.
Enabling rolloutOnCredentialUpdate on a CAPApplication resource instructs CAP Operator to watch the referenced BTP service credential Secrets and automatically trigger a rolling restart of affected Deployments whenever their credentials change.
| Benefit | Description |
|---|---|
| No stale credentials in running pods | Pods pick up fresh credentials without a manual rollout or a new CAPApplicationVersion. |
| Selective restarts | Only Deployments that actually consume the updated service are restarted; unaffected workloads are left untouched. |
| Resilient to operator restarts | On startup, CAP Operator re-checks all relevant Secrets so that credential changes that occurred while the operator was down are not missed. |
| Batched processing | Multiple Secret updates arriving within the batching window are accumulated and processed in a single pass, avoiding redundant rollouts. |
Set rolloutOnCredentialUpdate: true in the CAPApplication spec:
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: cap-app-01
namespace: cap-app-01
spec:
rolloutOnCredentialUpdate: true # opt-in to automatic rollout on credential rotation
btpAppName: cap-app-01
btp:
services:
- class: xsuaa
name: app-uaa
secret: cap-app-01-uaa-bind-cf
- class: saas-registry
name: app-saas-registry
secret: cap-app-01-saas-bind-cf
- class: service-manager
name: app-service-manager
secret: cap-app-01-svc-man-bind-cf
domainRefs:
- kind: ClusterDomain
name: common-external-domain
providerSubaccountId: provider-subaccount-id
The field is optional and defaults to false. See the API Reference for the full spec.
Once enabled, the operator follows this flow whenever a watched Secret changes:
Secret watch — CAP Operator watches all Kubernetes Secrets in the namespace of any CAPApplication that has rolloutOnCredentialUpdate: true. When a Secret is updated, the namespace is scheduled for processing after a configurable batching window (see Operator Configuration).
Batching — any additional Secret changes arriving in the same namespace within the batching window are accumulated. When the window expires, all collected changes are processed together in a single pass, preventing redundant rollouts when multiple services are rotated at once.
Affected workload detection — for each CAPApplicationVersion currently in use (the latest ready version, plus any version still serving active tenants), the operator checks which Deployments declare the rotated service in their consumedBTPServices list.
VCAP secret comparison — the operator rebuilds the VCAP_SERVICES data for each affected Deployment using the new credential data. If the payload is identical to the existing one, the Deployment is left untouched and no restart is triggered.
Rolling restart — when the data has changed, a new VCAP_SERVICES secret is created and the Deployment’s envFrom reference is updated to point to it. Kubernetes detects the change and performs a rolling restart of the pods, ensuring zero downtime.
Note: Only Deployments are restarted. Job workloads (content deployers, tenant operation jobs) are not affected by this feature.
Note: The rollout covers all ready
CAPApplicationVersionresources currently serving tenants, not only the latest version. This ensures credentials are refreshed consistently across all active versions during an upgrade transition.
The batching window duration is configurable via an environment variable on the CAP Operator deployment.
| Environment Variable | Description | Default | Minimum |
|---|---|---|---|
ROLLOUT_DELAY | How long the operator waits after a credential Secret is updated before processing the rollout. Secret changes arriving within this window for the same namespace are batched into a single pass. Accepts any Go duration string (e.g. 30m, 2h). | 1h | 30s |
If the configured value cannot be parsed, the operator logs an error and falls back to the default (1h). If the parsed value is below the minimum (30s), the operator logs an error and clamps it to 30s.
When rotating credentials, do not invalidate the old Secret immediately. CAP Operator needs time to:
ROLLOUT_DELAY),VCAP_SERVICES payload, andOnly once all pods are running with the new credentials is it safe to revoke the old ones.
As a rule of thumb, keep the old credentials valid for at least 24 hours after issuing the new ones. This provides a generous buffer that covers the batching delay, the rollout duration, and any transient failures or retries in the operator’s reconciliation loop.
Revoking credentials too soon risks pods being restarted mid-rollout with no valid credentials available, which causes application downtime.
In a continuous delivery environment where new application versions are deployed frequently, monitoring and cleaning up older unused versions is important for conserving cluster resources (compute, memory, storage) and keeping the system manageable. CAP Operator allows application developers and operations teams to define how an application version is monitored for usage.
Prometheus is the industry standard for monitoring application metrics and provides a wide variety of tools for managing and reporting metrics. The CAP Operator controller can be connected to a Prometheus server by setting the PROMETHEUS_ADDRESS environment variable (see Configuration). The controller then queries application-related metrics based on the workload specification of CAPApplicationVersion resources. Prometheus is only required to evaluate workloads that declare deletionRules. When PROMETHEUS_ADDRESS is not set, or the configured server is unreachable, the cleanup loop still runs. Versions whose deployment workloads declare no deletionRules can still be cleaned up in that case. Versions that do declare deletionRules are skipped — they are neither deleted nor surfaced as errors — and will be re-evaluated on the next cycle once Prometheus becomes available again.
CAPApplicationVersion cleanup monitoring must be explicitly enabled for a CAP application using the annotation sme.sap.com/enable-cleanup-monitoring. The annotation accepts the following values:
| Value | Behavior |
|---|---|
dry-run | When a CAPApplicationVersion is evaluated as eligible for cleanup, a ReadyForDeletion event is emitted without deleting the version. |
true | When a CAPApplicationVersion is evaluated as eligible for cleanup, the version is deleted and a ReadyForDeletion event is emitted. |
CAPApplicationVersionFor each deployment workload in a CAPApplicationVersion, you can define:
The following example shows a workload named backend configured with deletion rules based on multiple metrics.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
namespace: demo
name: cav-demo-app-1
spec:
workloads:
- name: backend
deploymentDefinition:
monitoring:
deletionRules:
metrics:
- calculationPeriod: 90m
name: current_sessions
thresholdValue: "0"
type: Gauge
- calculationPeriod: 2h
name: total_http_requests
thresholdValue: "0.00005"
type: Counter
This tells CAP Operator that workload backend provides two metrics that can be monitored for usage.
Metric current_sessions is of type Gauge, representing an absolute value at any point in time. CAP Operator queries Prometheus with a PromQL expression that calculates the average value over the specified calculation period. The average values from each time series are summed to get the evaluated value, which is then compared against the threshold to determine eligibility for cleanup.
Evaluation steps for metric type Gauge |
|---|
Execute PromQL expression sum(avg_over_time(current_sessions{job="cav-demo-app-1-backend-svc",namespace="demo"}[90m])) to get the evaluated value |
Check whether evaluated value <= 0 (the specified thresholdValue) |
Metric total_http_requests is of type Counter, representing a cumulative value that can only increase. CAP Operator queries Prometheus with a PromQL expression that calculates the rate of increase over the specified period. The rates from each time series are summed to get the evaluated value, which is compared against the threshold.
Evaluation steps for metric type Counter |
|---|
Execute PromQL expression sum(rate(total_http_requests{job="cav-demo-app-1-backend-svc",namespace="demo"}[2h])) to get the evaluated value |
Check whether evaluated value <= 0.00005 (the specified thresholdValue) |
job label represents the metric source and (within Kubernetes) corresponds to the service representing the workload.Gauge and Counter Prometheus metric types. Learn more about metric types here.All specified metrics of a workload must satisfy the evaluation criteria for the workload to be eligible for cleanup.
You can also specify deletion criteria for a workload by providing a PromQL expression that returns a boolean scalar.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
namespace: demo
name: cav-demo-app-1
spec:
workloads:
- name: backend
deploymentDefinition:
monitoring:
deletionRules:
expression: scalar(sum(avg_over_time(current_sessions{job="cav-demo-app-1-backend-svc",namespace="demo"}[2h]))) <= bool 5
The PromQL expression is executed as a Prometheus query. The expected result is a scalar boolean (0 or 1). Use comparison binary operators with the bool modifier to produce the expected result. If the evaluation result is true (1), the workload is eligible for removal.
This variant is useful when:
job label in the collected time series data does not match the name of the Kubernetes Service created for the workload.Prometheus Operator is a popular Kubernetes operator for managing Prometheus and related monitoring components. A common way to set up scrape targets is by creating the ServiceMonitor resource, which specifies which services (and ports) to scrape for application metrics.
The scrapeConfig feature is available only when the ServiceMonitor custom resource is available on the Kubernetes cluster.
CAP Operator can automatically create ServiceMonitor resources targeting the services created for version workloads. The following sample shows how to configure this.
kind: CAPApplicationVersion
metadata:
namespace: demo
name: cav-demo-app-1
spec:
workloads:
- name: backend
deploymentDefinition:
ports:
- appProtocol: http
name: metrics-port
networkPolicy: Cluster
port: 9000
monitoring:
deletionRules:
expression: scalar(sum(avg_over_time(current_sessions{job="cav-demo-app-1-backend-svc",namespace="demo"}[2h]))) <= bool 5
scrapeConfig:
interval: 15s
path: /metrics
port: metrics-port
With this configuration, CAP Operator creates a ServiceMonitor targeting the workload service. The scrapeConfig.port must match the name of one of the ports specified on the workload.
The scrapeConfig feature is designed for a minimal configuration that covers the most common use case (scraping the workload service via a defined port). For more complex ServiceMonitor configurations, create them separately. If scrapeConfig is empty, CAP Operator will not create the related ServiceMonitor.
CAPApplicationVersion Resources for CleanupAt specified intervals (controlled by the controller environment variable METRICS_EVAL_INTERVAL), CAP Operator selects versions as candidates for evaluation.
CAPApplication resources with the annotation sme.sap.com/enable-cleanup-monitoring are considered.spec.version higher than the highest Ready version are excluded from evaluation. If no version has Ready status, no versions are evaluated.CAPTenant are excluded. This includes versions referenced by the following CAPTenant fields:status.currentCAPApplicationVersionInstance — the tenant’s current version.spec.version — the version a tenant is upgrading to.Workloads from the identified versions are then evaluated against their deletionRules. Workloads without deletionRules are automatically eligible for cleanup regardless of whether Prometheus is configured or reachable. All deployment workloads of a version must satisfy the evaluation criteria for the version to be deleted.
When a workload declares deletionRules and the Prometheus client is currently unavailable — either because no PROMETHEUS_ADDRESS has been configured, or because the Runtimeinfo probe against the configured server is failing — that workload is treated as not eligible and the version is left untouched until the next evaluation cycle. Reachability is re-checked at most once per PROM_ACQUIRE_CLIENT_RETRY_DELAY interval, so a recovered Prometheus server will be detected and used on the next cycle after that delay elapses.
CAP Operator includes built-in Prometheus metrics that enable you to effectively monitor and analyze the operator’s performance. These metrics provide insights into resource usage, potential issues, and overall operator health. The metrics are accessible at the /metrics endpoint on port 9090 of both the Controller and the Subscription Server.
The Controller emits several types of metrics, including:
cap_op_reconcile_errors, e.g.:cap_op_reconcile_errors{kind="CAPApplication",name="my-app",namespace="app"} 11
CAPApplication.cap_op_tenant_operations, e.g.cap_op_tenant_operations{app="<hash>",operation="provisioning"} 83
To gain deeper insights, you can enable more granular metrics by setting the environment variable DETAILED_OPERATIONAL_METRICS to "true".
cap_op_tenant_operation_failures, e.g.:cap_op_tenant_operation_failures{app="<hash>",operation="upgrade",tenant_id="<guid>",namespace="app",name="my-app-tenant-op-xxyyz"} 2
cap_op_last_tenant_operation_duration_seconds, e.g.:cap_op_last_tenant_operation_duration_seconds{app="<hash>",tenant_id="<guid>"} 17
The Subscription Server emits the following metrics:
cap_op_subscription_requests_total, e.g.:cap_op_subscription_requests_total{code="202",method="POST"} 2024
cap_op_subscription_requests_inflight, e.g.:cap_op_subscription_requests_inflight{} 4
CAP Operator provides a rich set of metrics to facilitate monitoring and operational insights. By leveraging these metrics, you can monitor and ensure the reliability and performance of your applications. For further details, explore the Prometheus documentation and integrate these metrics into your monitoring systems.
We strongly recommend that applications implement the necessary authentication and authorization mechanisms to safeguard exposed workloads. This includes implicitly exposed tenant workloads and explicitly exposed service workloads.
When using SAP Authorization and Trust Management Service in the application, this can be done as explained in this guide.
You may also consider using Istio’s security features, for instance using specific workload selectors to secure exposed workloads.
CAPApplication resourceHere’s an example of a fully configured CAPApplication:
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplication
metadata:
name: cap-app
namespace: cap-ns
spec:
btp:
services:
- class: xsuaa
name: cap-uaa
secret: cap-uaa-bind
- class: saas-registry
name: cap-saas-reg
secret: cap-saas-reg-bind
- class: service-manager
name: cap-service-manager
secret: cap-svc-man-bind
- class: destination
name: cap-destination
secret: cap-bem-02-dest-bind
- class: html5-apps-repo
name: cap-html5-repo-host
secret: cap-html5-repo-bind
- class: html5-apps-repo
name: cap-html5-repo-runtime
secret: cap-html5-rt-bind
- class: some-content-service
name: cap-some-content-service
secret: cap-some-content-service-bind
- class: business-logging
name: cap-business-logging
secret: cap-business-logging-bind
btpAppName: cap-app
domainRefs:
- kind: Domain
name: cap-app-01-primary
- kind: ClusterDomain
name: common-external-domain
providerSubaccountId: 7a49218f-c750-4e1f-a248-7f1cefa13010
The btp.services array specifies all SAP BTP service instances and their corresponding Kubernetes Secrets (containing credentials) required by the application. These service instances are assumed to exist in the provider subaccount. You can use operators such as cf-service-operator or sap-btp-service-operator to declaratively create these service instances and their credentials as Kubernetes resources.
The providerSubaccountId identifies the provider subaccount linked to the application. The combination of providerSubaccountId and btpAppName (equivalent to XSAPPNAME) must be unique, as it is used in various SAP BTP service and application constructs.
The provider section is deprecated and may be completely ommited as of version 0.31.0 even for multi-tenant applications, this also skips the creation of a provider tenant.
The domainRefs section references one or more Domain or ClusterDomain resources.
NOTE: While the same secondary domain can technically be shared across applications using
ClusterDomain, tenant subdomains must be unique across all applications sharing that domain.
NOTE: The
providersection must always be omitted for services-only applications.
The optional rolloutOnCredentialUpdate field enables automatic rolling restarts of affected Deployments when the referenced BTP service credential Secrets are updated. See Rollout on Credential Update for details.
CAPApplicationVersion resourceThe CAPApplicationVersion has the following high-level structure:
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-v1
namespace: cap-ns
spec:
version: 3.2.1 # <-- semantic version (must be unique within the versions of a CAP application)
capApplicationInstance: cap-app
registrySecrets: # <-- image pull secrets to be used in the workloads
- regcred
workloads: # <-- define deployments and jobs used for this application version
- name: "cap-backend"
deploymentDefinition: # ...
consumedBTPServices: # ...
- name: "app-router"
deploymentDefinition: # ...
consumedBTPServices: # ...
- name: "service-content"
jobDefinition: # ...
consumedBTPServices: # ...
- name: "tenant-operation"
jobDefinition: # ...
consumedBTPServices: # ...
tenantOperations: # ... <-- (optional)
CAPApplicationVersion is always associated with a CAPApplication in the same namespace, referenced via the capApplicationInstance attribute.workloads array defines the software components of the application. Examples include a deployment for the CAP application server or a job for tenant operations. Each workload must have either a deploymentDefinition or a jobDefinition. See the next section for details.tenantOperations attribute defines a sequence of steps (jobs) to execute during tenant operations (provisioning, upgrade, or deprovisioning).The
CAPApplicationVersionresource is immutable — its spec must not be modified after deployment. This is enforced by webhooks, which we recommend keeping active (the default).
deploymentDefinitionname: cap-backend
consumedBTPServices: # <-- an array of service instance names referencing the SAP BTP services defined in the CAPApplication resource
- cap-uaa
- cap-saas-reg
deploymentDefinition:
type: CAP # <-- possible values are CAP / Router / Additional / Service
image: some.repo.example.com/cap-app/server:3.22.11 # <-- container image
env: # <-- (optional) same as in core v1 pod.spec.containers.env
- name: SAY
value: "I'm GROOT"
replicas: 3 # <-- (optional) replicas for scaling
ports:
- name: app-port
port: 4004
routerDestinationName: cap-server-url
- name: tech-port
port: 4005
monitoring:
scrapeConfig:
port: tech-port
deletionRules:
expression: scalar(sum(avg_over_time(current_sessions{job="cav-cap-app-v1-cap-backend-svc",namespace="cap-ns"}[2h]))) <= bool 5
The type of the deployment indicates how the operator handles this workload (for example, injection of destinations used by the Approuter). Valid values are:
CAP to indicate a CAP application server. Only one workload of this type is allowed.Router to indicate a version of the Approuter. Only one workload of this type is allowed.Additional to indicate supporting components deployed alongside the CAP application server.Service to indicate workloads that are tenant-agnostic.You can define optional attributes such as replicas, env, resources, probes, securityContext, initContainers, and ports to configure the deployment.
You can define which ports (and how many) exposed by a deployment container are made available inside the cluster (via Services of type ClusterIP). The port definition includes a name in addition to the port number being exposed.
For deploymentDefinition types other than Router, you can specify a routerDestinationName that is used as a named destination injected into the Approuter.
The port configurations are not mandatory and can be omitted. When omitted, the operator applies the following defaults:
CAP, the default port 4004 is added to the Service, and a destination named srv-api is added to the Approuter referencing this service port (any existing destinations environment configuration for this workload is preserved, with only the URL overwritten).Router, port 5000 is exposed in the Service. This Service is used as the target for HTTP traffic reaching the application domain (domains are specified in the CAPApplication resource).NOTE: If multiple ports are configured for a workload of type
Router, the first port is used to target external traffic to the application domain.
For each deployment workload in a CAPApplicationVersion, you can define:
Details of how to configure workload monitoring can be found here.
jobDefinitionworkloads:
# ... deployment workloads have been omitted in this example
- name: "content-deployer"
consumedBTPServices: # ...
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/content:1.0.1
- name: "tenant-operation"
consumedBTPServices: # ...
jobDefinition:
type: TenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
backoffLimit: 2 # <-- determines retry attempts for the job on failure (default is 6)
ttlSecondsAfterFinished: 300 # <-- the job will be cleaned up after this duration
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: "notify-upgrade"
consumedBTPServices: # ...
jobDefinition:
type: CustomTenantOperation
image: # ...
command: ["npm", "run", "notify:upgrade"] # <-- custom entry point for the container allows reuse of a container image with multiple entry points
backoffLimit: 1
- name: "create-test-data"
consumedBTPServices: # ...
jobDefinition:
type: CustomTenantOperation
image: # ...
command: ["npm", "run", "deploy:testdata"]
Workloads with a jobDefinition represent a job that executes at a particular point in the lifecycle of the application or tenant. The following values are allowed for type in such workloads:
Content: A content deployer job that deploys SAP BTP service-specific content from the application version. This job runs as soon as a new CAPApplicationVersion resource is created in the cluster. Multiple workloads of this type may be defined, and the order in which they run can be specified via ContentJobs.TenantOperation: A job executed during provisioning, upgrade, or deprovisioning of a tenant (CAPTenant). These jobs are controlled by the operator and use the cds/mtxs APIs to perform HDI content deployment by default. A workload of type TenantOperation must always be defined in the CAPApplicationVersion for multi-tenant applications. If cds/mtxs APIs are used, command can be specified to trigger tenant operations with a custom command.CustomTenantOperation: An optional job that runs before or after the TenantOperation, allowing the application to perform tenant-specific tasks (for example, creating test data).A tenant operation refers to provisioning, upgrade, or deprovisioning, which are executed in the context of a CAP application for individual tenants (using the cds/mtxs or similar modules provided by CAP). Within the workloads, two types of jobs are valid for such operations: TenantOperation and CustomTenantOperation.
The TenantOperation is mandatory for all tenant operations.
In addition, you can choose which CustomTenantOperation jobs run for a specific operation and in which order. For example, a CustomTenantOperation that deploys test data to the tenant database schema should run during provisioning but must not run during deprovisioning.
The field tenantOperations specifies which jobs run during the different tenant operations and their execution order.
spec:
workloads: # ...
tenantOperations:
provisioning:
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
upgrade:
- workloadName: "notify-upgrade"
continueOnFailure: true # <-- indicates the overall operation may proceed even if this step fails
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
# <-- as the deprovisioning steps are not specified, only the `TenantOperation` workload (first available) will be executed
In the example above, for each tenant operation, the valid jobs (steps) and their execution order are specified. Each step in an operation is defined with:
workloadName refers to the job workload executed in this operation step.continueOnFailure is valid only for CustomTenantOperation steps and indicates whether the overall tenant operation can proceed when this step fails.NOTE:
tenantOperationsis only required ifCustomTenantOperations are used. If not specified, each operation consists only of theTenantOperationstep (the first one found inworkloads).- A workload of type
TenantOperationmust always be present in theCAPApplicationVersion. The previous behaviour of falling back to theCAPdeployment workload when noTenantOperationjob was defined is no longer supported.- The
tenantOperationssequencing applies only to tenants provisioned (or deprovisioned) on thisCAPApplicationVersionand to tenants being upgraded to it.
When you create a CAPApplicationVersion, you can define multiple content jobs. The order in which these jobs run is important, as some jobs may depend on the output of others. The ContentJobs property specifies the execution order of content jobs.
spec:
workloads: # ...
tenantOperations: # ...
contentJobs:
- content-deployer-service
- content-deployer-ui
See Service Exposure page for details.
Other attributes can be configured as documented.
You can define which ports (and how many) exposed by a deployment container are made available inside the cluster (via Services of type ClusterIP). The port definition includes a name in addition to the port number being exposed.
For service-only workloads, the routerDestinationName is not relevant.
The port configurations are mandatory and cannot be omitted.
apiVersion: sme.sap.com/v1alpha2
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-v1
namespace: cap-ns
spec:
version: 3.2.1
capApplicationInstance: cap-app
registrySecrets:
- regcred
workloads:
- name: cap-backend
consumedBTPServices:
- cap-uaa
- cap-service-manager
- cap-saas-reg
deploymentDefinition:
type: CAP
image: some.repo.example.com/cap-app/server:3.22.11
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
replicas: 3
ports:
- name: app-port
port: 4004
routerDestinationName: cap-server-url
- name: tech-port
port: 4005
appProtocol: grpc
monitoring:
scrapeConfig:
port: tech-port
deletionRules:
expression: scalar(sum(avg_over_time(current_sessions{job="cav-cap-app-v1-cap-backend-svc",namespace="cap-ns"}[2h]))) <= bool 5
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4005
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4005
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 20m
memory: 50Mi
securityContext:
runAsUser: 1000
runAsGroup: 2000
- name: "app-router"
consumedBTPServices:
- cap-uaa
- cap-saas-reg
- cap-html5-repo-rt
deploymentDefinition:
type: Router
image: some.repo.example.com/cap-app/router:4.0.1
env:
- name: PORT
value: "3000"
ports:
- name: router-port
port: 3000
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 3000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 3000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 20m
memory: 50Mi
podSecurityContext:
runAsUser: 2000
fsGroup: 2000
- name: "service-content"
consumedBTPServices:
- cap-uaa
- cap-some-content-service
- cap-html5-repo-host
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/content:1.0.1
securityContext:
runAsUser: 1000
runAsGroup: 2000
- name: "ui-content"
consumedBTPServices:
- cap-uaa
- cap-some-content-service
- cap-html5-repo-host
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/ui-content:1.0.1
securityContext:
runAsUser: 1000
runAsGroup: 2000
- name: "tenant-operation"
consumedBTPServices: # ...
jobDefinition:
type: TenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
backoffLimit: 2
ttlSecondsAfterFinished: 300
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: "notify-upgrade"
consumedBTPServices: []
jobDefinition:
type: CustomTenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
command: ["npm", "run", "notify:upgrade"]
backoffLimit: 1
- name: "create-test-data"
consumedBTPServices:
- cap-service-manager
jobDefinition:
type: CustomTenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
command: ["npm", "run", "deploy:testdata"]
tenantOperations:
provisioning:
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
upgrade:
- workloadName: "notify-upgrade"
continueOnFailure: true
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
contentJobs:
- service-content
- ui-content
NOTE: The CAP Operator workloads support several configurations (drawn from the Kubernetes API), which can be found in the API reference:
- Common API reference for generic container configuration
- Deployment API reference for deployment-specific configuration
- Job API reference for job-specific configuration
The supported configurations are intentionally kept minimal to keep the overall API simple, covering only the most commonly used options.
Note:
initContainershave access to nearly the same environment variables as the main container, including theVCAP_SERVICESenvironment variable.
SubscriptionProvider resources are fully managed by CAP Operator. They are automatically created and kept in sync by the controller whenever a CAPApplication is reconciled. Do not create, modify, or delete them manually.
A SubscriptionProvider is created by the controller in the same namespace as its owning CAPApplication, with the same name. It stores pre-computed subscription credentials and dependency information derived from the CAPApplication spec. The subscription server uses it to:
getDependencies endpoint of the SaaS Provisioning serviceBecause all subscription-related lookups happen at CAPApplication reconciliation time rather than at HTTP request time, the subscription server can serve requests efficiently without directly parsing the CAPApplication spec.
apiVersion: sme.sap.com/v1alpha2
kind: SubscriptionProvider
metadata:
name: cap-app-01
namespace: cap-app-01
spec:
appName: cap-app-01
providerSubaccountId: aa2bae55d7b5-1279-456564-a7b0-aa2bae55d7b5
subscriptionInfo:
type: saas-registry
subscriptionSecret: my-saas-registry-secret
authSecret: my-xsuaa-secret
dependencies: '[{"xsappname":"my-destination-service!b42"},{"xsappname":"my-auditlog-service!b7"}]'
| Field | Description |
|---|---|
appName | Name of the CAP application. Derived from CAPApplication.spec.btpAppName. |
providerSubaccountId | Provider subaccount ID. Derived from CAPApplication.spec.providerSubaccountId. |
subscriptionInfo.type | Type of subscription service: saas-registry or subscription-manager, depending on which BTP service is configured in the CAPApplication. |
subscriptionInfo.subscriptionSecret | Name of the Kubernetes Secret containing the BTP subscription service credentials (used for request authorization). |
subscriptionInfo.authSecret | (Optional) Name of the Kubernetes Secret containing the XSUAA credentials. Only set for saas-registry type. |
dependencies | Pre-computed JSON array of subscription dependencies (for example, [{"xsappname":"..."}]). Computed from BTP service secrets at CAPApplication reconciliation time and returned verbatim by the subscription server’s getDependencies endpoint. See Service Qualification for how dependencies are determined. |
Subscription resources are fully managed by CAP Operator. They are created and deleted exclusively by the subscription server in response to callbacks from the SAP Software-as-a-Service Provisioning service or SMS. Do not create, modify, or delete them manually.
A Subscription represents an active subscription of a consumer subaccount to a CAP application. When a consumer subscribes via the SAP BTP cockpit or the SaaS Provisioning service API, the subscription server creates a Subscription resource in the namespace of the corresponding CAPApplication. The controller then creates a CAPTenant as a child of the Subscription and drives it through the provisioning flow.
apiVersion: sme.sap.com/v1alpha2
kind: Subscription
metadata:
name: cap-app-01-consumer-sgz8b
namespace: cap-app-01
spec:
appName: cap-app-01
providerSubaccountId: aa2bae55d7b5-1279-456564-a7b0-aa2bae55d7b5
tenantId: bb3cbf66e8c6-2380-567675-b8c1-bb3cbf66e8c6
subdomain: consumer-subdomain
subscriptionGuid: cc4dcg77f9d7-3491-678786-c9d2-cc4dcg77f9d7
subscriptionDomain: app.example.com
subscriptionRequestPayload: '{"subscriptionParams":{}}'
status:
state: Ready
url: https://consumer-subdomain.app.example.com
| Field | Description |
|---|---|
appName | Name of the CAP application being subscribed to. Used together with providerSubaccountId to identify the owning CAPApplication. |
providerSubaccountId | Provider subaccount ID. Used together with appName to identify the owning CAPApplication. |
tenantId | Tenant ID of the consumer subaccount. |
subdomain | Subdomain of the consumer subaccount. |
subscriptionGuid | Unique GUID of the subscription, as assigned by the SaaS Provisioning service. |
subscriptionDomain | Domain used to construct the tenant-specific subscription URL. If not provided, falls back to the annotation sme.sap.com/subscription-domain on the CAPApplication, or the first DomainRef in the CAPApplication spec. |
subscriptionRequestPayload | Full JSON payload of the subscription request. Injected into tenant operation jobs as the CAPOP_SUBSCRIPTION_PAYLOAD environment variable. |
The subscription server polls Subscription.status after creating the resource and sends an asynchronous callback to the SaaS Provisioning service once the subscription reaches a terminal state (Ready or Error).
| Field | Description |
|---|---|
state | Current state of the subscription. See States below. |
url | Tenant-specific application URL, populated by the controller once the owned CAPTenant is Ready. Returned to the SaaS Provisioning service as the subscription URL. |
| State | Description |
|---|---|
Processing | The controller is creating the CAPTenant and waiting for provisioning to complete. |
ProcessingError | A retryable error occurred during processing; the controller will retry. |
Error | A terminal error occurred (for example, the owned CAPTenant reached ProvisioningError). The SaaS Provisioning service is notified of the failure via the async callback. |
Deleting | Deletion has been triggered; the controller is waiting for the owned CAPTenant to complete deprovisioning. |
Ready | Provisioning is complete. The url field contains the tenant-specific application URL. |
CAPTenant resourceThe CAPTenant resource is completely managed by CAP Operator and must not be created or modified manually. For details of how CAPTenant is created, see tenant subscription.
The CAPTenant resource indicates the existence of a tenant in the related application (or one that is currently being provisioned). The resource starts with a Provisioning state and moves to Ready when successfully provisioned. Managing tenants as Kubernetes resources allows you to control not only the lifecycle of the entity, but also other requirements that must be fulfilled for the application to serve tenant-specific requests (for example, creating networking resources).
apiVersion: sme.sap.com/v1alpha2
kind: CAPTenant
metadata:
name: cap-app-consumer-ge455
namespace: cap-ns
spec:
capApplicationInstance: cap-app
subDomain: consumer-x
tenantId: cb46733-1279-48be-fdf434-aa2bae55d7b5
version: "1"
versionUpgradeStrategy: always
The specification contains attributes relevant to SAP BTP that identify a tenant, such as tenantId and subDomain.
The version field corresponds to the CAPApplicationVersion on which the tenant is provisioned or to which it was upgraded. When a newer CAPApplicationVersion is available, the operator automatically increments the tenant version, which triggers the upgrade process. The versionUpgradeStrategy defaults to always, but can be set to never in exceptional cases to prevent automatic upgrades of the tenant.
CAPTenantOperation resourceThe CAPTenantOperation resource is managed by CAP Operator and must not be created or modified manually. It is created by the CAPTenant to execute provisioning, deprovisioning, or upgrade operations.
apiVersion: sme.sap.com/v1alpha2
kind: CAPTenantOperation
metadata:
name: cap-app-consumer-ge455-77kb9
namespace: cap-ns
spec:
capApplicationVersionInstance: cav-cap-app-v2
operation: upgrade
steps:
- continueOnFailure: true
name: tenant-operation
type: CustomTenantOperation
- name: tenant-operation
type: TenantOperation
- name: create-test-data
type: CustomTenantOperation
subDomain: consumer-x
tenantId: cb46733-1279-48be-fdf434-aa2bae55d7b5
The example above shows a CAPTenantOperation for an upgrade operation. In addition to tenant details, it specifies the CAPApplicationVersion to use. For upgrade and provisioning operations, this is the target version; for deprovisioning, it is the tenant’s current version.
The operation executes a series of steps (jobs) specified in or derived from the CAPApplicationVersion. Each step refers to a workload of type TenantOperation or CustomTenantOperation. When CAP Operator creates a CAPTenantOperation, at least one step of type TenantOperation must be present (this is the job that performs the database schema update using CAP-provided modules).
CustomTenantOperation jobs are hooks that the application can execute before or after the TenantOperation. To help applications identify the execution context, each job receives the following environment variables:
CAPOP_APP_VERSION: The semantic version from the relevant CAPApplicationVersionCAPOP_TENANT_ID: The tenant identifierCAPOP_TENANT_OPERATION: The operation type — provisioning, deprovisioning, or upgradeCAPOP_TENANT_SUBDOMAIN: The subdomain (from the subaccount) of the tenantCAPOP_TENANT_TYPE: The tenant type — provider or consumerCAPOP_APP_NAME: The BTP app name from the corresponding CAPApplicationCAPOP_PROVIDER_SUBACCOUNT_ID: The provider subaccount identifier from the corresponding CAPApplicationCAPOP_PROVIDER_TENANT_ID: The provider tenant identifier (if it exists) from the corresponding CAPApplication (Deprecated: Will be removed soon).CAPOP_PROVIDER_SUBDOMAIN: The provider tenant subdomain (if it exists) from the corresponding CAPApplication (Deprecated: Will be removed soon).All of the above environment variables are also available on the corresponding initContainers, along with relevant VCAP_SERVICES credentials.
CAPTenantOutput resourceCAPTenantOutput can be used to add additional data to the asynchronous callback parameters sent by the SaaS Provisioning service during tenant onboarding. The resource is not reconciled; it is consumed by the subscription server to generate additional callback data. It has the following structure:
apiVersion: sme.sap.com/v1alpha2
kind: CAPTenantOutput
metadata:
name: cap-app-consumer-output
namespace: cap-ns
labels:
sme.sap.com/btp-tenant-id: cb46733-1279-48be-fdf434-aa2bae55d7b5
spec:
subscriptionCallbackData: '{foo: bar}'
The example above shows a resource associated with a tenant via the sme.sap.com/btp-tenant-id label, which must be set by consumers.
This resource is intended to be created or updated during tenant operations, such as those triggered during tenant onboarding. Its primary purpose is to enhance the parameters of the subscription callback during tenant onboarding, though it may be used for additional scenarios in the future.
Any RBAC changes required to create or modify this resource (for example, in a custom tenant operation) must be handled by consumers and assigned to the relevant job via the serviceAccountName configuration for that workload.
All instances of this resource for a given tenant are cleaned up before any CAPTenantOperation is created.
Domain resourceA Domain resource is namespace-scoped. All sub-resources — Gateway, DNSEntry, and (with Gardener certificate manager) the Certificate — are created in the same namespace as the Domain.
apiVersion: sme.sap.com/v1alpha2
kind: Domain
metadata:
namespace: cap-app-01
name: cap-app-01-primary
spec:
domain: my.cluster.shoot.url.k8s.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Simple # Simple (default), Mutual, or OptionalMutual
dnsMode: Wildcard # None (default), Wildcard, Subdomain, or Custom
dnsTarget: public-ingress.cluster.domain # Optional
certConfig: # Optional; only relevant when tlsMode is Mutual or OptionalMutual
additionalCACertificate: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
domain — the DNS domain name. The TLS certificate is issued for the wildcard *.domain.
ingressSelector — label selector used to locate the Istio Ingress Gateway pods. The operator discovers the gateway’s namespace and load balancer service from these pods, and applies the selector to the Istio Gateway resource.
tlsMode — TLS mode for the Istio Gateway:
Simple (default) — server-side TLS only.Mutual — mutual TLS; client certificate required.OptionalMutual — mutual TLS; client certificate optional.dnsMode — controls DNS entry creation (Gardener external-dns-management only; ignored otherwise):
None (default) — no DNS entries created.Wildcard — creates a single *.domain entry pointing to dnsTarget.Subdomain — creates <subdomain>.domain entries for each subdomain observed across referencing applications.Custom — creates entries defined by dnsTemplates; each template has a name and target field rendered as Go templates. Available variables: {{.domain}}, {{.dnsTarget}}, {{.subDomain}}. See Custom DNS Templates for details.dnsTarget (optional) — the load balancer hostname or IP address to use as the DNS target. Resolved in order: explicit dnsTarget field → DNS_TARGET environment variable → load balancer service annotation on the Istio Ingress Gateway service.
certConfig.additionalCACertificate (optional) — PEM-encoded CA certificate Istio uses to verify client certificates when tlsMode is Mutual or OptionalMutual. See Configuring Additional CA Certificates for details.
certConfig.certManager.issuerRef (optional, cert-manager only) — overrides the cert-manager issuer used to sign the TLS certificate. Defaults to a ClusterIssuer named cluster-ca. See Configuring cert-manager Certificates for details.
Sub-resources are mainly created in the Domain namespace:
Gateway — always created.DNSEntry — Gardener DNS manager only.Certificate (Gardener cert-manager) — the certificate’s secretRef points to the Istio Ingress Gateway namespace, which supports cross-namespace secret references.Certificate (cert-manager) — created in the Istio Ingress Gateway namespace; cert-manager does not support cross-namespace secret references.Secret — created in the Istio Ingress Gateway namespace; only when certConfig.additionalCACertificate is set.ClusterDomain resourceA ClusterDomain resource is cluster-scoped and intended for domains shared across multiple applications or namespaces. All sub-resources — Gateway, DNSEntry, and (with Gardener certificate manager) the Certificate — are created in the namespace where CAP Operator is installed.
apiVersion: sme.sap.com/v1alpha2
kind: ClusterDomain
metadata:
name: common-external-domain
spec:
domain: my.example.com
ingressSelector:
app: istio-ingressgateway
istio: ingressgateway
tlsMode: Simple # Simple (default), Mutual, or OptionalMutual
dnsMode: Subdomain # None (default), Wildcard, Subdomain, or Custom
dnsTarget: public-ingress.cluster.domain # Optional
certConfig: # Optional; only relevant when tlsMode is Mutual or OptionalMutual
additionalCACertificate: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
domain — the DNS domain name. The TLS certificate is issued for the wildcard *.domain.
ingressSelector — label selector used to locate the Istio Ingress Gateway pods. The operator discovers the gateway’s namespace and load balancer service from these pods, and applies the selector to the Istio Gateway resource.
tlsMode — TLS mode for the Istio Gateway:
Simple (default) — server-side TLS only.Mutual — mutual TLS; client certificate required.OptionalMutual — mutual TLS; client certificate optional.dnsMode — controls DNS entry creation (Gardener external-dns-management only; ignored otherwise):
None (default) — no DNS entries created.Wildcard — creates a single *.domain entry pointing to dnsTarget.Subdomain — creates <subdomain>.domain entries for each subdomain observed across referencing applications.Custom — creates entries defined by dnsTemplates; each template has a name and target field rendered as Go templates. Available variables: {{.domain}}, {{.dnsTarget}}, {{.subDomain}}. See Custom DNS Templates for details.dnsTarget (optional) — the load balancer hostname or IP address to use as the DNS target. Resolved in order: explicit dnsTarget field → DNS_TARGET environment variable → load balancer service annotation on the Istio Ingress Gateway service.
certConfig.additionalCACertificate (optional) — PEM-encoded CA certificate Istio uses to verify client certificates when tlsMode is Mutual or OptionalMutual. See Configuring Additional CA Certificates for details.
certConfig.certManager.issuerRef (optional, cert-manager only) — overrides the cert-manager issuer used to sign the TLS certificate. Defaults to a ClusterIssuer named cluster-ca. See Configuring cert-manager Certificates for details.
Sub-resources are mainly created in the CAP Operator namespace:
Gateway — always created.DNSEntry — Gardener DNS manager only.Certificate (Gardener cert-manager) — the certificate’s secretRef points to the Istio Ingress Gateway namespace, which supports cross-namespace secret references.Certificate (cert-manager) — created in the Istio Ingress Gateway namespace; cert-manager does not support cross-namespace secret references.Secret — created in the Istio Ingress Gateway namespace; only when certConfig.additionalCACertificate is set.CAP Operator uses the
@sap/cds-mtxslibrary. Prior to version 0.7.0, you could disable this by setting theIS_MTXS_ENABLEDenvironment variable to"false"in theTenantOperationworkload, which used the older@sap/cds-mtxlibrary-based wrapper job instead. This is no longer supported and has been removed, as support for CDS v6 has ended.
CAP Operator uses @sap/cds-mtxs (which replaces the former @sap/cds-mtx library) by default. This enables built-in CLI-based handling for tenant provisioning, deprovisioning, and upgrade operations.
Depending on your Kubernetes cluster hardening setup, you may need to add a securityContext to the TenantOperation and CAP workloads as shown below.
- name: tenant-job
consumedBTPServices:
- "{{ include "xsuaaInstance" . }}"
- "{{ include "serviceManagerInstance" . }}"
- "{{ include "saasRegistryInstance" . }}"
jobDefinition:
type: TenantOperation
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
image: "some.repo.example.com/cap-app/server"
securityContext: # needed until CAP resolves issue with folder creation in the root dir of the app container at runtime
runAsUser: 1000
Libraries like xsenv/cds (CAP) handle credentials differently across environments (Cloud Foundry vs. Kubernetes). On Kubernetes, when credential data is read directly from Secrets, JSON data type information may be lost, leading to inconsistencies.
This is addressed by the SAP Service Binding Specification, which requires metadata to be added to Secrets. Both btp-service-operator and cf-service-operator support this metadata addition. If this feature is not used in your cluster, CAP Operator avoids inconsistencies by creating a VCAP_SERVICES environment variable across all workloads and expects all SAP BTP service credentials to be stored in Kubernetes Secrets under a credentials key.
You can achieve this using the secretKey property when creating a ServiceBinding with btp-service-operator or cf-service-operator:
apiVersion: cf.cs.sap.com/v1alpha1
kind: ServiceBinding
metadata:
name: uaa
namespace: demo
spec:
serviceInstanceName: uaa
name: app-uaa
secretKey: credentials
We recommend using
secretKeyeven when credential metadata is available, to reduce the overhead of parsing multiple JSON attributes.
The Approuter maps incoming requests to configured destinations. If you use an xs-app.json file to specify route mappings to various destinations, ensure that the destinationName property for the CAP back end is specified in the corresponding CAPApplicationVersion configuration. CAP Operator injects this destination into the Approuter pods via environment variables.
If your back-end service takes a long time to respond, configure the destinations environment variable on the Approuter to set the desired timeout for that destination (destinationName). CAP Operator overwrites only the URL part of the destination to point to the correct workload; all other settings are preserved as configured.
Use @sap/approuter version 14.x.x or higher.
All custom resources (CRs) created by CAP Operator are protected with finalizers to ensure proper cleanup.
The provider CAPTenant resource can also be manually deleted after removing the provider section from the CAPApplication specification.
As of version 0.34.0, when a CAPApplication is deleted, it enters a Deleting state and waits until all existing CAPTenant resources are removed before proceeding. Consumer tenants must be cleaned up by unsubscribing from the application (via the SAP BTP cockpit or SaaS Provisioning service APIs); the provider tenant is automatically deleted. Once all tenants are removed, the deletion of the CAPApplication and its remaining child resources proceeds automatically.
Prior to version 0.34.0, deleting a CAPApplication automatically triggered deprovisioning of all existing tenants.
Important: CAP Operator requires the Secrets from service instances and bindings to exist for the entire lifecycle of the application. Removing service instances, bindings, or their Secrets from the cluster while CAP application CRs still exist will leave orphaned resources (and potentially orphaned database data), and recovery from such inconsistent states may not be possible.
This situation can easily occur when using
helm uninstall, since the deletion order of resources is not configurable. Ensure that Secrets from service instances and bindings are not deleted before all CAP application resources that depend on them are fully removed.
A CAPApplication resource in WaitingForSecrets state indicates that one or more Secrets referenced under spec.btp.services are not present in the cluster. CAP Operator itself cannot resolve this condition — the Secrets are owned and created by an external operator (for instance, the SAP BTP Service Operator).
To investigate, inspect the custom resources responsible for creating the missing Secrets — typically ServiceInstance and ServiceBinding resources of the BTP service operator (or whichever operator manages service bindings in your cluster) — and check their status for errors or failed conditions that may explain why the Secret has not been created.
If CAPTenantOperation jobs or other pods fail with errors indicating connection problems with SAP HANA, the issue is outside the scope of CAP Operator. Check the following on the consumer side:
CAP Operator relies on a global informer cache that watches Secrets across the entire cluster. It does not currently support namespace-scoped caching or excluding namespaces to limit the set of Secrets held in memory. On clusters with a large number of Secrets, the controller pod may consume significant memory.
If the controller pod is being OOM-killed or is showing high memory usage, increase the memory limit of the CAP Operator controller workload in your Helm values to accommodate the full set of cluster Secrets cached at runtime.
To report a bug, create an issue.
Something missing? Let us know or raise a PR.
Reach out to the project team and community via the following channels:
Packages:
Package v1alpha2 is the v1alpha2 version of the API.
CAPApplication is the schema for capapplications API
| Field | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||||||||
kindstring | CAPApplication | ||||||||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||||||||
specCAPApplicationSpec | CAPApplication spec
| ||||||||||||||
statusCAPApplicationStatus | CAPApplication status |
CAPApplicationVersion defines the schema for capapplicationversions API
| Field | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||||||||
kindstring | CAPApplicationVersion | ||||||||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||||||||
specCAPApplicationVersionSpec | CAPApplicationVersion spec
| ||||||||||||||
statusCAPApplicationVersionStatus | CAPApplicationVersion status |
CAPTenant defines the schema for captenants API
| Field | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||
kindstring | CAPTenant | ||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||
specCAPTenantSpec | CAPTenant spec
| ||||||||
statusCAPTenantStatus | CAPTenant status |
CAPTenantOperation defines the schema for captenantoperations API
| Field | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||
kindstring | CAPTenantOperation | ||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||
specCAPTenantOperationSpec | CAPTenantOperation spec
| ||||||||
statusCAPTenantOperationStatus | CAPTenantOperation status |
CAPTenantOutput is the schema for captenantoutputs API
| Field | Description | ||
|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||
kindstring | CAPTenantOutput | ||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||
specCAPTenantOutputSpec | CAPTenantOutput spec
|
ClusterDomain is the schema for clusterdomains API
| Field | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||||||||
kindstring | ClusterDomain | ||||||||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||||||||
specDomainSpec | ClusterDomains spec
| ||||||||||||||
statusDomainStatus | ClusterDomain status |
Domain is the schema for domains API
| Field | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||||||||
kindstring | Domain | ||||||||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||||||||
specDomainSpec | Domains spec
| ||||||||||||||
statusDomainStatus | Domain status |
Subscription is the schema for subscriptions API
| Field | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||||||||
kindstring | Subscription | ||||||||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||||||||
specSubscriptionSpec | Subscription spec
| ||||||||||||||
statusSubscriptionStatus | Subscription status |
SubscriptionProvider is the schema for subscriptionproviders API
| Field | Description | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
apiVersionstring | sme.sap.com/v1alpha2 | ||||||||||
kindstring | SubscriptionProvider | ||||||||||
metadataKubernetes meta/v1.ObjectMeta | Refer to the Kubernetes API documentation for the fields of the
metadata field. | ||||||||||
specSubscriptionProviderSpec | SubscriptionProvider spec
|
(Appears on: CAPApplicationSpec)
| Field | Description |
|---|---|
services[]ServiceInfo | Details of BTP Services |
(Appears on: CAPApplicationSpec, CAPTenantOperationSpec, CAPTenantSpec)
Identifies an SAP BTP subaccount (tenant)
| Field | Description |
|---|---|
subDomainstring | BTP subaccount subdomain |
tenantIdstring | BTP subaccount Tenant ID |
(Appears on: CAPApplication)
CAPApplicationSpec defines the desired state of CAPApplication
| Field | Description |
|---|---|
domainRefs[]DomainRef | Reference to |
providerSubaccountIdstring | The subaccount ID in which the application is provided |
btpAppNamestring | Short name for the application (BTP XSAPPNAME) |
providerBTPTenantIdentification | Deprecated: Provider subaccount where application services are created Will be removed, consider automating this via BTP / subscription instead! |
btpBTP | SAP BTP Services consumed by the application |
rolloutOnCredentialUpdatebool | Rollout on Credentials Update may be used to rollout deployments when dependent service credentials are updated |
maxSubscriptionsint32 | (Optional) Defines the upper bound on the number of subscriptions allowed for this application. When set, subscription requests that would exceed this limit are rejected. If unset, no limit is enforced. |
string alias)(Appears on: CAPApplicationStatus)
| Value | Description |
|---|---|
"Consistent" | CAPApplication has been reconciled and is now consistent |
"Deleting" | Deletion has been triggered |
"Error" | An error occurred during reconciliation |
"Processing" | CAPApplication is being reconciled |
(Appears on: CAPApplication)
Status of the CAPApplication
| Field | Description |
|---|---|
GenericStatusGenericStatus | (Members of |
stateCAPApplicationState | State of CAPApplication |
servicesOnlybool | Represents whether this is a services only scenario |
domainSpecHashstring | Hash representing last known application domains |
lastFullReconciliationTimeKubernetes meta/v1.Time | The last time a full reconciliation was completed |
observedSubdomains[]string | Last known application subdomains |
string alias)| Value | Description |
|---|---|
"AllTenantsReady" | |
"LatestVersionReady" |
(Appears on: CAPApplicationVersion)
CAPApplicationVersionSpec specifies the desired state of CAPApplicationVersion
| Field | Description |
|---|---|
capApplicationInstancestring | Denotes to which CAPApplication the current version belongs |
versionstring | Semantic version |
registrySecrets[]string | Registry secrets used to pull images of the application components |
workloads[]WorkloadDetails | Information about the Workloads |
tenantOperationsTenantOperations | Tenant Operations may be used to specify how jobs are sequenced for the different tenant operations |
contentJobs[]string | Content Jobs may be used to specify the sequence of content jobs when several jobs exist |
serviceExposures[]ServiceExposure | Configuration for the service(s) to be exposed (relevant only for ‘Service’ type deployment workloads) |
string alias)(Appears on: CAPApplicationVersionStatus)
| Value | Description |
|---|---|
"Deleting" | Deletion has been triggered |
"Error" | An error occurred during reconciliation |
"Processing" | CAPApplicationVersion is being processed |
"Ready" | CAPApplicationVersion is now ready for use (dependent resources have been created) |
(Appears on: CAPApplicationVersion)
Status of the CAPApplicationVersion
| Field | Description |
|---|---|
GenericStatusGenericStatus | (Members of |
stateCAPApplicationVersionState | State of CAPApplicationVersion |
finishedJobs[]string | List of finished Content Jobs |
(Appears on: CAPTenantOperation)
Spec of the CAPTenantOperation
| Field | Description |
|---|---|
operationCAPTenantOperationType | Scope of the tenant lifecycle operation. One of ‘provisioning’, ‘deprovisioning’ or ‘upgrade’ |
BTPTenantIdentificationBTPTenantIdentification | (Members of BTP sub-account (tenant) for which request is created |
capApplicationVersionInstancestring | Reference to CAPApplicationVersion for executing the operation |
steps[]CAPTenantOperationStep | Steps (jobs) to be executed for the operation to complete |
string alias)(Appears on: CAPTenantOperationStatus)
| Value | Description |
|---|---|
"Completed" | CAPTenantOperation steps completed |
"Deleting" | CAPTenantOperation deletion has been triggered |
"Failed" | CAPTenantOperation steps have failed |
"Processing" | CAPTenantOperation is being processed |
(Appears on: CAPTenantOperation)
Status of the CAPTenantOperation
| Field | Description |
|---|---|
GenericStatusGenericStatus | (Members of |
stateCAPTenantOperationState | State of CAPTenantOperation |
currentStepuint32 | Current step being processed from the sequence of specified steps |
activeJobstring | Name of the job being executed for the current step |
(Appears on: CAPTenantOperationSpec)
| Field | Description |
|---|---|
namestring | Name of the workload from the referenced CAPApplicationVersion |
typeJobType | Type of job. One of ‘TenantOperation’ or ‘CustomTenantOperation’ |
continueOnFailurebool | Indicates whether the operation can continue in case of step failure. Relevant only for type ‘CustomTenantOperation’ |
string alias)(Appears on: CAPTenantOperationSpec)
| Value | Description |
|---|---|
"deprovisioning" | Deprovision tenant |
"provisioning" | Provision tenant |
"upgrade" | Upgrade tenant |
(Appears on: CAPTenantOutput)
Spec of CAPTenantOutput
| Field | Description |
|---|---|
subscriptionCallbackDatastring |
(Appears on: CAPTenant)
CAPTenantSpec defines the desired state of the CAPTenant
| Field | Description |
|---|---|
capApplicationInstancestring | Denotes to which CAPApplication the current tenant belongs |
BTPTenantIdentificationBTPTenantIdentification | (Members of Details of consumer sub-account subscribing to the application |
versionstring | Semver that is used to determine the relevant CAPApplicationVersion that a CAPTenant can be upgraded to (i.e. if it is not already on that version) |
versionUpgradeStrategyVersionUpgradeStrategyType | Denotes whether a CAPTenant can be upgraded. One of (‘always’, ‘never’) |
string alias)(Appears on: CAPTenantStatus)
| Value | Description |
|---|---|
"Deleting" | Deletion has been triggered |
"Provisioning" | Tenant is being provisioned |
"ProvisioningError" | Tenant provisioning ended in error |
"Ready" | Tenant has been provisioned/upgraded and is now ready for use |
"UpgradeError" | Tenant upgrade failed |
"Upgrading" | Tenant is being upgraded |
(Appears on: CAPTenant)
Status of the CAPTenant
| Field | Description |
|---|---|
GenericStatusGenericStatus | (Members of |
stateCAPTenantState | State of CAPTenant |
currentCAPApplicationVersionInstancestring | Specifies the current version of the tenant after provisioning or upgrade |
previousCAPApplicationVersions[]string | Previous versions of the tenant (first to last) |
lastFullReconciliationTimeKubernetes meta/v1.Time | The last time a full reconciliation was completed |
(Appears on: DomainSpec)
| Field | Description |
|---|---|
additionalCACertificatestring | Used to specify additional CA certificate that may be used for verifying client certificates in Mutual TLS mode |
certManagerCertManager | CertManager specific configuration for the certificate to be created for the domain |
(Appears on: CertConfig)
| Field | Description |
|---|---|
issuerRefgithub.com/cert-manager/cert-manager/pkg/apis/meta/v1.IssuerReference | Issuer configuration for the certificate |
(Appears on: DeploymentDetails, JobDetails)
CommonDetails specifies the common details of the Container/Pod that may be relevant for both Deployments and Jobs
| Field | Description |
|---|---|
imagestring | Image info for the container |
imagePullPolicyKubernetes core/v1.PullPolicy | Pull policy for the container image |
command[]string | Entrypoint array for the container |
args[]string | Arguments to the entrypoint |
env[]Kubernetes core/v1.EnvVar | Environment Config for the Container |
volumes[]Kubernetes core/v1.Volume | Volume Configuration for the Pod |
volumeMounts[]Kubernetes core/v1.VolumeMount | Volume Mount Configuration for the Container |
serviceAccountNamestring | Name of the ServiceAccount to use to run the Pod |
resourcesKubernetes core/v1.ResourceRequirements | Resources |
securityContextKubernetes core/v1.SecurityContext | SecurityContext for the Container |
podSecurityContextKubernetes core/v1.PodSecurityContext | SecurityContext for the Pod |
nodeNamestring | The name of the node to which the Pod should be assigned to. See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodename |
nodeSelectormap[string]string | The label selectors using which node for the Pod would be determined. See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector |
priorityClassNamestring | Priority class name mapping used to prioritize and schedule the Pod. See: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass |
affinityKubernetes core/v1.Affinity | Affinity/anti-affinity used to provide more constraints for node selection. See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity |
tolerations[]Kubernetes core/v1.Toleration | Tolerations used to schedule the Pod. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ |
topologySpreadConstraints[]Kubernetes core/v1.TopologySpreadConstraint | The Topology spread constraints used to control how Pods are spread across regions, zones, nodes etc. See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#pod-topology-spread-constraints Note: As of now, this field only makes sense for Deployment workloads. If/once we support parallel Job workloads, this field may be relevant for Jobs as well. |
initContainers[]Kubernetes core/v1.Container | List of containers executed before the main container is started |
restartPolicyKubernetes core/v1.RestartPolicy | Restart policy for the Pod. See: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy |
terminationGracePeriodSecondsint64 | Optional duration in seconds the pod needs to terminate gracefully. See: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination-flow |
lifecycleKubernetes core/v1.Lifecycle | Optional actions that the management system should take in response to container lifecycle events. See: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination |
string alias)(Appears on: DomainSpec)
| Value | Description |
|---|---|
"Custom" | A DNS entry will be created according to configuration in |
"None" | No DNS entries will be created (Default) |
"Subdomain" | A DNS entry will be created for each subdomain specified by the applications using this domain |
"Wildcard" | Wildcard DNS entry will be created |
(Appears on: DomainSpec)
DNSTemplate supports the creation of DNS entries using go templates See: https://pkg.go.dev/text/template
| Field | Description |
|---|---|
namestring | Domain name for which a DNS record will be created |
targetstring | Target of the DNS record |
(Appears on: WorkloadMonitoring)
| Field | Description |
|---|---|
metrics[]MetricRule | |
expressionstring | A promQL expression that evaluates to a scalar boolean (1 or 0). Example: scalar(sum(avg_over_time(demo_metric{job=“cav-demo-app-4-srv-svc”,namespace=“demo”}[2m]))) <= bool 0.1 |
(Appears on: WorkloadDetails)
DeploymentDetails specifies the details of the Deployment
| Field | Description |
|---|---|
CommonDetailsCommonDetails | (Members of |
typeDeploymentType | Type of the Deployment |
replicasint32 | Number of replicas |
ports[]Ports | Port configuration |
livenessProbeKubernetes core/v1.Probe | Liveness probe |
readinessProbeKubernetes core/v1.Probe | Readiness probe |
startupProbeKubernetes core/v1.Probe | Startup Probe |
monitoringWorkloadMonitoring | Workload monitoring specification |
podDisruptionBudgetKubernetes policy/v1.PodDisruptionBudgetSpec | Pod Disruption Budget may be used to specify the minimum number of available pods for this workload |
horizontalPodAutoscalerHorizontalPodAutoscalerSpec | Horizontal Pod Autoscaler may be used to specify the scaling behavior for this workload |
stickinessStickiness | Stickiness configuration based on istio consistent hashing for the workload. When present, this is used to create a DestinationRule for the workload. |
string alias)(Appears on: DeploymentDetails)
Type of deployment
| Value | Description |
|---|---|
"Additional" | Additional deployment type |
"CAP" | CAP backend server deployment type |
"Router" | Application router deployment type |
"Service" | Service deployment type |
(Appears on: CAPApplicationSpec)
Domain references
| Field | Description |
|---|---|
kindstring | |
namestring |
(Appears on: ClusterDomain, Domain)
Spec of the Domain/ClusterDomain
| Field | Description |
|---|---|
domainstring | Domain used by an application |
ingressSelectormap[string]string | Selector is the set of labels used to select the ingress pods handling the domain |
tlsModeTLSMode | TLS mode for the generated (Istio) Gateway resource. Set this to Mutual when using mTLS with an external gateway. |
dnsModeDNSMode | DNS mode controls the creation of DNS entries related to the domain |
dnsTemplates[]DNSTemplate | DNS templates allow usage of Go templates for generating DNS entries when [DNSMode] is set to |
dnsTargetstring | DNS Target for traffic to this domain |
certConfigCertConfig | Certificate configuration |
string alias)(Appears on: DomainStatus)
| Value | Description |
|---|---|
"Deleting" | |
"Error" | |
"Processing" | |
"Ready" |
(Appears on: ClusterDomain, Domain)
Status of the Domain/ClusterDomain
| Field | Description |
|---|---|
GenericStatusGenericStatus | (Members of |
stateDomainState | State of the Domain |
dnsTargetstring | Effective DNS Target identified for this domain |
gatewayNamestring | Gateway name used for the domain |
observedDomainstring | domain observed during last reconciliation |
string alias)(Appears on: MetricRule, MonitoringConfig)
Duration is a valid time duration that can be parsed by Prometheus
Supported units: y, w, d, h, m, s, ms
Examples: 30s, 1m, 1h20m15s, 15d
(Appears on: CAPApplicationStatus, CAPApplicationVersionStatus, CAPTenantOperationStatus, CAPTenantStatus, DomainStatus, SubscriptionStatus)
Custom resource status
| Field | Description |
|---|---|
observedGenerationint64 | Observed generation of the resource where this status was identified |
conditions[]Kubernetes meta/v1.Condition | State expressed as conditions |
(Appears on: StickinessHash)
| Field | Description |
|---|---|
namestring | Name of the cookie. |
pathstring | Path to set for the cookie. |
ttlKubernetes meta/v1.Duration | Lifetime of the cookie. If specified, a cookie with the TTL will be generated if the cookie is not present. If the TTL is present and zero, the generated cookie will be a session cookie. |
attributes[]NameValue | Additional attributes for the cookie. They will be used when generating a new cookie. |
(Appears on: DeploymentDetails)
HorizontalPodAutoscalerSpec wraps autoscalingv2.HorizontalPodAutoscalerSpec but gets rid of scaleTargetRef, as the operator always sets it to the deployment created for the workload.
| Field | Description |
|---|---|
minReplicasint32 | (Optional) minReplicas is the lower limit for the number of replicas to which the autoscaler can scale down. |
maxReplicasint32 | maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up. |
metrics[]Kubernetes autoscaling/v2.MetricSpec | (Optional) metrics contains the specifications for which to use to calculate the desired replica count. |
behaviorKubernetes autoscaling/v2.HorizontalPodAutoscalerBehavior | (Optional) behavior configures the scaling behavior of the target in both Up and Down directions. |
(Appears on: WorkloadDetails)
JobDetails specifies the details of the Job
| Field | Description |
|---|---|
CommonDetailsCommonDetails | (Members of |
typeJobType | Type of Job |
backoffLimitint32 | Specifies the number of retries before marking this job failed. |
ttlSecondsAfterFinishedint32 | Specifies the time after which the job may be cleaned up. |
activeDeadlineSecondsint64 | Specifies the duration in seconds for which the job may be continuously active. |
string alias)(Appears on: CAPTenantOperationStep, JobDetails)
Type of Job
| Value | Description |
|---|---|
"Content" | job for deploying content or configuration to (BTP) services |
"CustomTenantOperation" | job for custom tenant operation e.g. pre/post hooks for a tenant operation |
"TenantOperation" | job for tenant operation e.g. deploying relevant data to a tenant |
(Appears on: DeletionRules)
MetricRule specifies a Prometheus metric and rule which represents a cleanup condition. Metrics of type Gauge and Counter are supported.
Rule evaluation for Gauge type metric: The time series data of the metric (restricted to the current workload by setting job label as workload service name) is calculated as an average over the specified period.
A sum of the calculated average from different time series is then compared to the provided threshold value to determine whether the rule has been satisfied.
Evaluation: sum(avg_over_time(<gauge-metric>{job=<workload-service-name>}[<lookback-duration>])) <= <lower-threshold-value>
Rule evaluation for Counter type metric: The time series data of the metric (restricted to the current workload by setting job label as workload service name) is calculated as rate of increase over the specified period.
The sum of the calculated rates from different time series is then compared to the provided threshold value to determine whether the rule has been satisfied.
Evaluation: sum(rate(<counter-metric>{job=<workload-service-name>}[<lookback-duration>])) <= <lower-threshold-value>
| Field | Description |
|---|---|
namestring | Prometheus metric. For example |
typeMetricType | Type of Prometheus metric which can be either |
calculationPeriodDuration | Duration of time series data used for the rule evaluation |
thresholdValuestring | The threshold value which is compared against the calculated value. If calculated value is less than or equal to the threshold the rule condition is fulfilled. |
string alias)(Appears on: MetricRule)
Type of Prometheus metric
| Value | Description |
|---|---|
"Counter" | Prometheus Metric type Counter |
"Gauge" | Prometheus Metric type Gauge |
(Appears on: WorkloadMonitoring)
| Field | Description |
|---|---|
intervalDuration | Interval at which Prometheus scrapes the metrics from the target. |
portstring | Name of the port (specified on the workload) which will be used by Prometheus server to scrape metrics |
pathstring | HTTP path from which to scrape for metrics. |
scrapeTimeoutDuration | Timeout after which Prometheus considers the scrape to be failed. |
(Appears on: HTTPCookie)
Generic Name/Value configuration
| Field | Description |
|---|---|
namestring | |
valuestring |
string alias)(Appears on: Ports)
Type of NetworkPolicy for the port
| Value | Description |
|---|---|
"Application" | Expose the port for the current application versions pod(s) scope |
"Cluster" | Expose the port for any pod(s) in the overall cluster scope |
(Appears on: DeploymentDetails)
Configuration of Service Ports for the deployment
| Field | Description |
|---|---|
appProtocolstring | App protocol used by the service port |
namestring | Name of the service port |
networkPolicyPortNetworkPolicyType | Network Policy of the service port |
portint32 | The port number used for container and the corresponding service (if any) |
routerDestinationNamestring | Destination name which may be used by the Router deployment to reach this backend service |
(Appears on: ServiceExposure)
Routing configuration (http match) for the exposed service
| Field | Description |
|---|---|
workloadNamestring | Name of the workload (eventually a service to route requests to); must be a valid workload name (Deployment) |
portint32 | Port number used for the service (must be present in the workload/service) |
pathstring | A unique routing path used (as a match/prefix) to route requests to the workload (when omitted, “/” would be used) |
(Appears on: CAPApplicationVersionSpec)
ServiceExposure specifies the details of the VirtualService to be exposed for Service type workload(s)
| Field | Description |
|---|---|
subDomainstring | Subdomain under which the service is exposed (used as the Key for identifying the VirtualService) |
routes[]Route | Routes specifies the routing configuration (http match) for the exposed service |
(Appears on: BTP)
Service information
| Field | Description |
|---|---|
namestring | A unique name of service based on usage in the app (this may be the name of the instance or binding) |
secretstring | Secret containing service access credentials |
classstring | Type of service |
subscriptionDependencySubscriptionDependency | SubscriptionDependency may be used to specify whether this service should be part of getDependencies call from subscription service (e.g. saas-registry) |
string alias)| Value | Description |
|---|---|
"Ready" |
(Appears on: DeploymentDetails)
| Field | Description |
|---|---|
hashStickinessHash | Hash based stickiness configuration. |
(Appears on: Stickiness)
Loosely based on the options available for consistent hash load balancer in istio (https://istio.io/latest/docs/reference/config/networking/destination-rule/#ConsistentHashLB), but only include the options that make sense for our use case.
| Field | Description |
|---|---|
httpHeaderNamestring | Hash based on a specific HTTP header. |
httpCookieHTTPCookie | Hash based on HTTP cookie. |
useSourceIpbool | Hash based on the source IP address. This is applicable for both TCP and HTTP connections. |
httpQueryParameterNamestring | Hash based on a specific HTTP query parameter. |
string alias)(Appears on: ServiceInfo)
| Value | Description |
|---|---|
"Always" | Always return the service in getDependencies call |
"Auto" | Automatically determine if the service needs to be returned in getDependencies call |
"Never" | Never return the service in getDependencies call |
(Appears on: SubscriptionProviderSpec)
| Field | Description |
|---|---|
typestring | Type of Subscription (subscription-manager / saas-registry) |
subscriptionSecretstring | Name of the Subscription Credential |
authSecretstring | Name of the Auth Credential (Optional) |
(Appears on: SubscriptionProvider)
| Field | Description |
|---|---|
appNamestring | Name of the application that is being subscribed to |
providerSubaccountIdstring | Provider subaccount ID for the application that is being subscribed to |
subscriptionInfoSubscriptionInfo | The secret(s) containing the subscription credentials that are necessary to create a subscription for the application (Fetched from the same namespace as this resource). |
dependenciesstring | List of subscription dependencies discovered for the services specified in the corresponding app |
maxSubscriptionsint32 | (Optional) Defines the upper bound on the number of subscriptions allowed for this application. When set, subscription requests that would exceed this limit are rejected. If unset, no limit is enforced. |
(Appears on: Subscription)
| Field | Description |
|---|---|
appNamestring | Name of the application that is being subscribed to |
providerSubaccountIdstring | Provider subaccount ID of the application that is being subscribed to (used to identify the owning CAPApplication) |
tenantIdstring | TenantId of the consumer subaccount subscribing to the application |
subdomainstring | Subdomain of the consumer subaccount subscribing to the app |
subscriptionGuidstring | SubscriptionGuid of the subscription |
subscriptionDomainstring | Subscription domain of the consumer subaccount subscribing to the app |
subscriptionRequestPayloadstring | Payload of the subscription request (JSON string). |
string alias)(Appears on: SubscriptionStatus)
| Value | Description |
|---|---|
"Deleting" | |
"Error" | |
"Processing" | |
"ProcessingError" | |
"Ready" |
(Appears on: Subscription)
| Field | Description |
|---|---|
GenericStatusGenericStatus | (Members of |
stateSubscriptionState | State of the Subscription |
urlstring | Tenant specific URL of the subscribed application |
string alias)(Appears on: DomainSpec)
| Value | Description |
|---|---|
"Mutual" | Mutual TLS Mode |
"OptionalMutual" | Optional Mutual TLS Mode |
"Simple" | Simple TLS Mode (Default) |
(Appears on: TenantOperations)
| Field | Description |
|---|---|
workloadNamestring | Reference to a specified workload of type ‘TenantOperation’ or ‘CustomTenantOperation’ |
continueOnFailurebool | Indicates whether to proceed with remaining operation steps in case of failure. Relevant only for ‘CustomTenantOperation’ |
(Appears on: CAPApplicationVersionSpec)
Configuration used to sequence tenant related jobs for a given tenant operation
| Field | Description |
|---|---|
provisioning[]TenantOperationWorkloadReference | Tenant provisioning steps |
upgrade[]TenantOperationWorkloadReference | Tenant upgrade steps |
deprovisioning[]TenantOperationWorkloadReference | Tenant deprovisioning steps |
string alias)(Appears on: CAPTenantSpec)
| Value | Description |
|---|---|
"always" | Always (default) |
"never" | Never |
(Appears on: CAPApplicationVersionSpec)
WorkloadDetails specifies the details of the Workload
| Field | Description |
|---|---|
namestring | Name of the workload |
consumedBTPServices[]string | List of BTP services consumed by the current application component workload. These services must be defined in the corresponding CAPApplication. |
labelsmap[string]string | Custom labels for the current workload |
annotationsmap[string]string | Annotations for the current workload, in case of |
deploymentDefinitionDeploymentDetails | Definition of a deployment |
jobDefinitionJobDetails | Definition of a job |
(Appears on: DeploymentDetails)
WorkloadMonitoring specifies the metrics related to the workload
| Field | Description |
|---|---|
deletionRulesDeletionRules | DeletionRules specify the metrics conditions that need to be satisfied for the version to be deleted automatically. Either a set of metrics based rules can be specified, or a PromQL expression which evaluates to a boolean scalar. |
scrapeConfigMonitoringConfig | Configuration to be used to create ServiceMonitor for the workload service. If not specified, CAP Operator will not attempt to create a ServiceMonitor for the workload |
Generated with gen-crd-api-reference-docs
on git commit 458123b.