PluginRegistration¶
A PluginRegistration is one option that a plugin offers in one or more PluginSections, for example "New S3 bucket" in the section backup-storage. It says what the option reads from other sections, what it writes, what a claim can change, and which permissions it asks for. A plugin controller writes its registration from its chart values. The operator writes the built-in registrations.
PluginRegistration is cluster-scoped. It is an alpha API in the group plugins.camunda.io/v1alpha1, and its fields can change in a later release.
The smallest registration:
apiVersion: plugins.camunda.io/v1alpha1
kind: PluginRegistration
metadata:
name: s3-backup-bucket
spec:
sections:
- backup-storage
label: New S3 bucket
mode: Optional
serviceAccount:
namespace: camunda-plugins
name: s3-backup-bucket-controller
deletionPolicies:
- Delete
graph LR
PR[PluginRegistration] -.->|"sections, inputs"| PS[PluginSection]
Built-in registrations¶
The operator writes six built-in registrations:
| Name | Section | Mode | Parameters | Claim-editable | Inputs | Outputs |
|---|---|---|---|---|---|---|
elasticsearch |
secondary-storage |
Default |
preset (required), releaseRef (required, the claim sets it), overrides: replicas, resources, storageSize, scheduling, podLabels |
overrides |
volume-encryption/storageClassName, backup-storage/objectStorageConfig, cloud-identity/serviceAccountAnnotations |
secondaryStorageConfig |
database-server |
secondary-storage |
Optional |
preset (required), releaseRef (required, the claim sets it), overrides: instances, resources, storageSize, scheduling, podLabels |
overrides |
volume-encryption/storageClassName, backup-storage/objectStorageConfig, cloud-identity/serviceAccountAnnotations |
secondaryStorageConfig |
existing-secondary-storage |
secondary-storage |
Optional |
name (required): a SecondaryStorageConfig in the namespace of the claim |
none | none | secondaryStorageConfig |
existing-object-storage |
backup-storage |
Optional |
name (required): an ObjectStorageConfig in the namespace of the claim |
none | none | objectStorageConfig |
management-database-server |
management-database |
Default |
preset (required), version (the PostgreSQL major version, default 17), databases |
none | volume-encryption/storageClassName |
keycloakDatabaseConfig, identityDatabaseConfig, webModelerDatabaseConfig |
existing-database-configs |
management-database |
Optional |
keycloak, identity, webModeler: DatabaseConfig names |
none | none | keycloakDatabaseConfig, identityDatabaseConfig, webModelerDatabaseConfig |
Without an Environment, a new cluster claim selects elasticsearch for its secondary storage, and a new management plane claim selects management-database-server for its databases. A claim selects the other options only when you pick them.
Every input of a built-in registration is optional. Every built-in registration supports the deletion policies Delete and Orphan. The registrations of existing resources write nothing, so both policies keep everything in place.
On elasticsearch, the input backup-storage/objectStorageConfig or cloud-identity/serviceAccountAnnotations fixes the ServiceAccount of the Elasticsearch pods to <claim>-es-es, which the cloud identity trusts. It then replaces the ServiceAccount settings of the preset. Without both inputs, the preset decides the ServiceAccount.
The operator serves the requests of all six built-in registrations. See Built-in requests.
The operator is the plugin controller of these six registrations. It sets their Ready condition to True, as in this status of existing-object-storage:
status:
observedGeneration: 1
conditions:
- type: Accepted
status: "True"
reason: Healthy
message: All checks passed
- type: Ready
status: "True"
reason: Healthy
message: The operator serves the requests of this registration
Each built-in registration has controller.name: camunda-operator, and controller.version is the version of the operator. serviceAccount names the ServiceAccount of the operator. operatorVersions is empty, because the operator serves these options itself.
The operator writes the built-in registrations each time the manager starts:
- A built-in registration that you delete comes back at the next start.
- A field of a built-in registration that you change goes back to its value at the next start.
- A field that the operator does not write stays, for example
docsUrlor a label that you add tometadata.labels. - The operator never deletes a registration, also when a later release no longer writes it.
The operator writes these fields with the field manager camunda-operator-builtins. A GitOps tool that writes the same fields shows this name in its conflict message.
Mode¶
mode says what a new claim selects when no Environment applies to its namespace:
Default: a new claim selects the option. A section has at most oneDefaultoption.Optional: the fleet manager offers the option, and a new claim does not select it.
Inputs and outputs¶
An input reads one output of another section, in the form <section>/<output>, for example encryption-key/keyRef. The claim gives the value of the output to the request of this option. With required: true, a claim cannot select the option while the input has no value. formats lists the formats of the value that the option accepts, for example aws-kms-arn. An empty list accepts every format.
outputs lists the values that the plugin writes to the status of a request. It includes the outputs of each section that the option serves.
Parameters¶
parameters is the OpenAPI v3 schema of the parameters of a request for the option. parameterValues are the values that the admin set in the plugin chart. claimEditable lists the parameters that a claim can change. An Environment can override parameterValues and claimEditable. Without one, these two fields apply.
choices are the presets or existing resources that a claim can pick for a parameter, with the facts that the fleet manager shows for each.
Grant templates¶
Each entry of grantTemplates is one permission statement that the option asks for. The plugin writes one Grant for each template. The template is a JSON object with Go template placeholders:
| Placeholder | Value |
|---|---|
{{ .namespace }} |
The namespace of the request. |
{{ .claim }} |
The name of the claim. |
{{ .request }} |
The name of the PluginRequest. |
{{ .serviceAccount }} |
spec.target.serviceAccountName of the request. |
{{ .parameters.<name> }} |
A parameter of the request. |
{{ .outputs.<key> }} |
An output of the request. |
requiresInputs names the inputs that must have a value before the plugin writes the grant. A metric query in metricQueries uses the same placeholders, and also {{ .pods }}, a regular expression of the pod names of the request.
Acceptance¶
The operator checks each registration and reports the result in the Accepted condition. The fleet manager offers the option only when Accepted and Ready are both True. The operator sets Accepted. The plugin controller sets Ready. On the built-in registrations, the operator sets Ready too.
The operator accepts a registration when all of these are true:
- Each name in
spec.sectionsnames aPluginSection. - The version of the operator is inside
spec.operatorVersions. - In each section, no other registration has
mode: Defaultwhen this one has it.
apiVersion: plugins.camunda.io/v1alpha1
kind: PluginRegistration
metadata:
name: s3-backup-bucket
spec:
sections:
- backup-storage
mode: Optional
operatorVersions: ">=0.3.0 <1.0.0"
# ... the rest of your registration
A registration without operatorVersions works with every operator version. A prerelease of the operator, such as 0.3.0-rc.1, is outside a range like >=0.3.0 <1.0.0. To include the prereleases, write >=0.3.0-0 <1.0.0.
When a check fails, Accepted is False. The message names the missing sections, the version and the range, or the other Default registrations. The checks run in the order of the list above, and the message names the first failure only. The operator checks the registration again when one of its sections, or another registration of one of its sections, is created, changed, or deleted.
status:
conditions:
- type: Accepted
status: "False"
reason: DefaultConflict
message: "In section backup-storage, these registrations also have mode Default: rustfs-bucket"
When two registrations of one section both have mode: Default, both report DefaultConflict. Set mode: Optional on one of them, and both become Accepted again.
A plugin controller that writes the status of its registration must keep the Accepted condition that it finds there. For example, when it updates the whole status, it sends the Accepted condition back unchanged.
Status¶
| Type | Reason | Meaning | What to do |
|---|---|---|---|
Accepted |
Healthy |
The operator accepts the registration. | Nothing. |
Accepted |
SectionMissing |
A section in spec.sections does not exist. The message names it. |
Install the plugin chart that brings the section, or fix the name. |
Accepted |
OperatorVersionUnsupported |
The version of the operator is outside spec.operatorVersions, or the range is not valid. The message names the version and the range. |
Install a plugin version that supports this operator, or upgrade the operator. |
Accepted |
DefaultConflict |
Another registration of the same section also has mode Default. The message names it. |
Set mode: Optional on all but one of them. |
Ready |
Healthy |
The operator serves the requests of this built-in registration. | Nothing. |
Ready |
set by the plugin | The plugin controller reports its health and its credentials. | Read the message, and the logs of the plugin controller. |
status.observedGeneration is the last generation that a controller of the registration processed.
Fields¶
The API reference lists every field of PluginRegistration, with its type, whether it is required, its default, and its validation. The label, description, docsUrl, controller, choices, limits, and metricQueries fields change only what the fleet manager shows.
Validation rules¶
The API server refuses a registration when:
sectionsis empty:sections must list at least one section.deletionPoliciesdoes not containDelete:deletionPolicies must contain Delete.- A
requiresInputsitem of a grant template names no input of the registration:each requiresInputs item of a grant template must name an input of the registration. - An
inputs[].fromis not in the form<section>/<output>. - Two inputs have the same
name, two outputs have the samekey, or two grant templates have the samename. inputsorgrantTemplateshas more than 32 items, ordeletionPolicieshas more than 2.- The name is longer than 63 characters:
metadata.name must be at most 63 characters, because it is used as a label value.
A registration with inputs and grant templates¶
This option creates one S3 bucket for the backups of each cluster. It reads the key of the section encryption-key and asks for access to the bucket:
apiVersion: plugins.camunda.io/v1alpha1
kind: PluginRegistration
metadata:
name: s3-backup-bucket
spec:
sections:
- backup-storage
label: New S3 bucket
description: Creates one S3 bucket for the backups of each cluster.
docsUrl: https://example.com/docs/s3-backup-bucket
mode: Optional
controller:
name: s3-backup-bucket-controller
version: 0.1.0
serviceAccount:
namespace: camunda-plugins
name: s3-backup-bucket-controller
operatorVersions: ">=0.3.0 <1.0.0"
parameters:
type: object
properties:
retentionDays:
type: integer
minimum: 1
parameterValues:
retentionDays: 30
claimEditable:
- retentionDays
choices:
- name: standard
specs:
- label: Retention
value: 30 days
inputs:
- name: kmsKey
from: encryption-key/keyRef
required: false
formats:
- aws-kms-arn
outputs:
- key: objectStorageConfig
description: The name of the ObjectStorageConfig that points at the bucket.
limits:
- label: Region
value: eu-west-1
description: The chart creates every bucket in this region.
grantTemplates:
- name: bucket-access
format: aws-iam-statement
description: Lets the cluster read and write its backups.
requiresInputs:
- kmsKey
template:
Effect: Allow
Action: ["s3:GetObject", "s3:PutObject", "s3:ListBucket"]
Resource: ["arn:aws:s3:::{{ .request }}", "arn:aws:s3:::{{ .request }}/*"]
deletionPolicies:
- Delete
- Orphan
metricQueries:
- label: Bucket size
query: 'sum(aws_s3_bucket_size_bytes{bucket="{{ .request }}"})'
unit: bytes
Related¶
- PluginSection: the sections that a registration serves.
- PluginRequest: the request that a claim writes when it selects the option.
- Grant: the permissions that the plugin writes from the grant templates.
- API reference: every field of the kind.