Crossplane Compositions
Every Hiroba application includes a crossplane/ directory for hosting app-specific Crossplane Composite Resource Definitions (XRDs) and Compositions.
What Goes Here?
This directory is for compositions that your application provides to the platform. Not every app will need this — it's for applications that expose infrastructure capabilities to other apps.
Example: Keycloak
Say you have a Keycloak application created from the Hiroba template. The crossplane/ directory starts empty. You then add:
xrd-realm.yaml— Defines aKeycloakRealmClaimAPIcomposition-realm.yaml— Maps the claim to Keycloak API resources
Now other applications can provision Keycloak realms by creating Claims against your XRD in their platform Helm charts.
keycloak/
└── crossplane/
├── xrd-realm.yaml
├── composition-realm.yaml
└── examples/
└── claim-realm.yaml
The Flow
App A (Keycloak) App B (Web App)
┌─────────────────────┐ ┌──────────────────────┐
│ crossplane/ │ │ helm/platform/ │
│ xrd-realm.yaml │◄────────── │ keycloak-realm.yaml│
│ composition.yaml │ Claims │ (KeycloakRealmClaim)│
└─────────────────────┘ └──────────────────────┘
- App A (e.g., Keycloak) publishes XRDs and Compositions in its
crossplane/directory - Platform admins install them on the cluster:
kubectl apply -f crossplane/ - App B creates Claims in its platform Helm chart to provision resources from App A
Writing a Composition
1. Define the XRD
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xkeycloakrealms.identity.example.com
spec:
group: identity.example.com
names:
kind: XKeycloakRealm
plural: xkeycloakrealms
claimNames:
kind: KeycloakRealmClaim
plural: keycloakrealmclaims
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
realmName:
type: string
required: [realmName]
2. Create the Composition
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: keycloak-realm
spec:
compositeTypeRef:
apiVersion: identity.example.com/v1alpha1
kind: XKeycloakRealm
resources:
- name: realm
base:
apiVersion: keycloak.crossplane.io/v1alpha1
kind: Realm
spec:
forProvider:
enabled: true
providerConfigRef:
name: keycloak-provider
patches:
- fromFieldPath: spec.realmName
toFieldPath: spec.forProvider.realm
3. Add an example Claim
apiVersion: identity.example.com/v1alpha1
kind: KeycloakRealmClaim
metadata:
name: my-realm
spec:
realmName: my-app
Installing on the Cluster
kubectl apply -f crossplane/
This makes the XRDs and Compositions available cluster-wide for other apps to consume.