๐๐๐ From 0.6.x โ W'xOps is the open source and open for contribution process. ๐๐๐
This is unreleased documentation for W'xOps Next version.
For up-to-date documentation, see the latest version (0.5.x).
Version: Next
XTenantApp
Tenant application scaffold โ provisions a Deployment + Service +
optional IngressRoute + optional ServiceAccount for an application workload,
following app.kubernetes.io/* label conventions.
tenant-app deliberately stops at the application workload. Vault-backed secrets
and databases (XTenantDatabase) are provisioned separately
and referenced via secretsFrom.
Application name. Used as Deployment/Service/IngressRoute name and app.kubernetes.io/name label.
namespace
string
yes
Target namespace for all composed resources.
cluster
string
"default"
provider-kubernetesProviderConfig to compose resources through. default (the hub cluster) is the only one wired up today โ leaving this unset is behavior-neutral. Multi-cluster targeting is not yet functional; no spoke ProviderConfig exists yet.
environment
string
"dev"
One of dev, staging, prod. Applied as wxops.cloud/environment label โ metadata for dashboards and Kyverno policies; does not affect composed resource behavior.
appFlavor
string
"webapp"
One of webapp, ai, ai-webapp, geo-webapp, search-webapp. Applied as wxops.cloud/app-flavor label for platform automation (e.g. selecting pgvector/postgis extensions). Does not affect this XR's composed resources.
templateId
string
Scaffold template identifier. Applied as wxops.cloud/template-id annotation for catalog linking.
repository.url
string
Source repository URL. Applied as wxops.cloud/repo-url annotation.
Container image reference (repository:tag). Use the single-string form so ArgoCD Image Updater can target it via Kustomize image-transformer.
imagePullPolicy
string
"IfNotPresent"
One of Always, IfNotPresent, Never.
imagePullSecrets
array<string>
[]
Names of existing kubernetes.io/dockerconfigjson Secrets in the target namespace.
replicas
integer
1
containerPort
integer
8080
terminationGracePeriodSeconds
integer
30
Seconds between SIGTERM and SIGKILL. Increase for apps with long-running requests or connection draining.
resources
object
requests/limits ร cpu/memory, passed through verbatim.
env
array<{name, value}>
[]
Plain (non-secret) environment variables.
envFrom
array<{secretRef|configMapRef: {name}}>
[]
Additional envFrom sources, merged after secretsFrom-managed refs.
podAnnotations
object
{}
Annotations on the pod template. Not how Prometheus scraping is configured โ use monitoring below; this platform's Prometheus doesn't watch prometheus.io/* annotations.
deploymentAnnotations
object
{}
Extra annotations on the Deployment metadata.
labels
object
{}
Extra labels on all composed resources. Standard app.kubernetes.io/* and wxops.cloud/* labels always win โ selectors depend on them.
If true, compose a new ServiceAccount in the target namespace.
serviceAccount.name
string
appName
SA name. When create: false, must reference an existing SA.
serviceAccount.annotations
object
{}
Annotations on the created SA. Use for workload identity bindings (eks.amazonaws.com/role-arn, iam.gke.io/gcp-service-account). Ignored when create: false.
Wires envFrom.secretRef entries by name. This XR only adds the reference โ it
does not provision or wait for the Secret. The Deployment will fail to start
(CreateContainerConfigError) until referenced Secrets exist.
Adds reloader.stakater.com/auto: "true" to the Deployment. Triggers a rolling restart when referenced ConfigMaps/Secrets change. Requires Stakater Reloader in-cluster.
HTTP GET probes against containerPort. liveness and readiness default to enabled when service.enabled is true โ implementing GET /healthz and GET /readyz on containerPort is a golden-path contract for all scaffolded services.
Field
Type
Default
Description
probes.liveness.enabled
boolean
service.enabled
probes.liveness.path
string
"/healthz"
probes.liveness.initialDelaySeconds
integer
10
probes.liveness.periodSeconds
integer
10
probes.liveness.timeoutSeconds
integer
1
probes.liveness.failureThreshold
integer
3
probes.readiness.enabled
boolean
service.enabled
probes.readiness.path
string
"/readyz"
probes.readiness.initialDelaySeconds
integer
5
probes.readiness.periodSeconds
integer
10
probes.readiness.timeoutSeconds
integer
1
probes.readiness.failureThreshold
integer
3
probes.startup.enabled
boolean
false
Gates liveness/readiness until the first successful check. Useful for slow-starting apps.
ingress.enabled: true always emits a Traefik IngressRoute โ never a standard Ingress. This is required for darlane.trafficWeight to switch between a plain Service and a TraefikService weighted split with zero downtime.
Field
Type
Default
Description
ingress.enabled
boolean
false
Emits a Traefik IngressRoute.
ingress.host
string
Required when enabled: true. Used as the hostname in the Traefik Host(...) match rule on the IngressRoute.
ingress.path
string
"/"
URL path prefix used in the Traefik PathPrefix(...) match rule.
ingress.annotations
object
{}
Merged onto IngressRoute metadata.
ingress.tls.enabled
boolean
false
Sets entryPoints: [websecure] and spec.tls.secretName.
ingress.tls.secretName
string
"{appName}-tls"
TLS Secret name. When clusterIssuer is set, cert-manager writes into this name.
ingress.tls.clusterIssuer
string
If set (and tls.enabled), emits a cert-manager Certificate CR. cert-manager auto-provisions the Secret. Requires cert-manager and the named ClusterIssuer in-cluster.
ingress.auth.enabled
boolean
false
Adds auth-errors and forward-auth-redirect Traefik Middleware references โ SSO via oauth2-proxy ForwardAuth. Both Middleware CRDs must exist in kube-system.
Emits a real Prometheus ServiceMonitor or PodMonitor โ the scaffold wizard's Monitoring
toggle writes only enabled and, optionally, path; every other field defaults sensibly and
is exposed here for direct XR authors.
Field
Type
Default
Description
monitoring.enabled
boolean
false
Master toggle. When false, no monitor is emitted.
monitoring.kind
string
"auto"
auto (ServiceMonitor when service.enabled, else PodMonitor), or an explicit ServiceMonitor/PodMonitor override. Setting ServiceMonitor without a Service is a hard render-time failure, not a silent no-op.
monitoring.port
integer
containerPort
Port to scrape.
monitoring.path
string
"/metrics"
HTTP path exposing the metrics.
monitoring.interval
string
"30s"
Scrape interval.
monitoring.scrapeTimeout
string
"10s"
Per-scrape timeout. Must be <= interval.
monitoring.sampleLimit
integer
5000
Max samples accepted per scrape.
monitoring.honorLabels
boolean
false
When true, labels from the scraped metrics win over Prometheus's own target labels on conflict.
monitoring.metricRelabelings
array
[]
Prometheus metric_relabel_configs, applied at ingest.
Per-cluster provider RBAC required
Creating a ServiceMonitor/PodMonitor needs monitoring.coreos.com permissions on
Crossplane's provider-kubernetes ServiceAccount โ a manual, per-spoke-cluster
kubectl apply of providers/rbac-provider-kubernetes.yaml, not carried by any package
bump. Until it's applied, monitoring.enabled: true fails forbidden at reconcile โ
visible in this XR's own status/events. See
Runtime Observability for the full picture.
When enabled, a second <appName>-dev Deployment is created alongside the main one โ
same image/env/secrets, scaled to 0 by default, with no Service/IngressRoute of
its own. Scale it on-demand, route real traffic via trafficWeight for A/B testing,
or use mirrord CLI directly against the pod for local development with real cluster
env and secrets.
Same discriminator pattern as main volumes[] โ set exactly one of claimName, configMapName, or secretName. PVC creation (create: true) is not supported in darlane volumes; reference existing claims only.
Written back by the composition โ read these fields directly rather than polling
Crossplane's own composite Ready condition, which can lag due to WatchCircuitOpen
throttling. All are derived from observed composed-resource state on each reconcile.
Field
Type
Description
status.created
boolean
True once the Deployment, Service, and Ingress have been observed in the cluster at least once. Distinguishes "provisioning in progress" (created: false) from "exists but not yet healthy" (created: true, ready: false).
status.ready
boolean
True when the core workload (Deployment, Service, Ingress) reports Ready. Scoped to the core workload on purpose โ check dependenciesReady too before calling the app fully healthy.
status.dependenciesReady
boolean
True when resources that gate the app being usable end-to-end, but don't gate the workload itself, report Ready โ today, the cert-manager Certificate when ingress.tls is enabled. Split from ready so a consumer can render "app is up, TLS still issuing" instead of a blanket "not ready." Does not cover database provisioning โ secretsFrom.database only wires in an existing Secret by name and is never waited on.
status.namespace
string
Kubernetes namespace where the app is deployed.
status.image
string
Container image currently configured for the deployment.
status.url
string
Application URL derived from ingress.host (https:// when tls.enabled, http:// otherwise). Empty when ingress is disabled.
status.darlane
object
Observed state of the Darlane debug twin. Absent entirely when darlane.enabled: false โ not present-and-empty.
status.darlane.ready
boolean
True when the <appName>-darlane Deployment reports Ready.
status.darlane.replicas
integer
Observed ready replica count, read from the Deployment provider-kubernetes writes back โ not the desired count from spec.
status.darlane.trafficMode
string
Resolved routing for the twin: none, weighted (TraefikService split), header (header-matched IngressRoute), or both.
status.darlane.ttl
string
The configured darlane.ttl duration (e.g. "4h"), echoed as-is โ not an expiry timestamp. The composition has no clock; combine with the Deployment's creationTimestamp to compute one. Empty when unset.
status.darlane.serviceAccountName
string
Name of the ServiceAccount the twin runs as, published so RBAC can be bound to it from the GitOps repo โ this repo's compositions never emit Role/RoleBinding themselves. Empty when no ServiceAccount is configured.