The Operator Lifecycle Manager allows adding descriptors to Custom Resource Definitions, which are used to describe different fields on the object.
There are three types of descriptors:
Type | Directory | Description |
---|---|---|
Spec | spec/ |
References fields in the spec block of an object |
Status | status/ |
References fields in the status block of an object |
The schema for a descriptor is the same, regardless of type:
type Descriptor = {
path: string; // Dot-delimited path of the field on the object that this descriptor
displayName: string;
description: string;
'x-descriptors': SpecCapability[] | StatusCapability[]; // Used to determine which "capabilities" this descriptor has, and which React component to use
value?: any; /* Optional field (type: object).
If present, the value of this spec is the same for all instances of the CRD
and can be found here instead of on the CR. */
}
The x-descriptors
field can be thought of as "capabilities" (and is referenced in the code using this term). Capabilities are defined in types.ts
provide a mapping between descriptors and different UI components (implemented as React components) using URN format.
The value
field is an optional field. If present, the value of this spec is the same for all instances of the CRD and can be found here instead of on the CR. This should not be used to apply a default value to a given custom resource for consumption by the console.
You can assign the default value of the field on CRD in OpenAPI v3 validation schema (see Defaulting for CRD in apiextensions.k8s.io/v1
). Alternatively, you can specify the value of a field in CRD Templates in the ClusterServiceVersion
to set (or override) the default value on the CRD.
From the ClusterServiceVersion
for etcd-operator:
- name: etcdclusters.etcd.database.coreos.com
version: v1beta2
kind: EtcdCluster
displayName: etcd Cluster
description: Represents a cluster of etcd nodes.
resources:
- kind: Service
version: v1
- kind: Pod
version: v1
specDescriptors:
- description: The desired number of member Pods for the etcd cluster.
displayName: Size
path: size
x-descriptors:
- 'urn:alm:descriptor:com.tectonic.ui:podCount'
- description: Limits describes the minimum/maximum amount of compute resources required/allowed
displayName: Resource Requirements
path: pod.resources
x-descriptors:
- 'urn:alm:descriptor:com.tectonic.ui:resourceRequirements'
statusDescriptors:
- description: The status of each of the member Pods for the etcd cluster.
displayName: Member Status
path: members
x-descriptors:
- 'urn:alm:descriptor:com.tectonic.ui:podStatuses'
Which yields this UI:
In Kubernetes 1.8, CRDs gained the ability to define an optional OpenAPI v3 based validation schema. This is important for data consistency, security, and can also be used to auto-generate forms for creating CRD instances (or "Operands").
With a structural schema (mandatory for CRD in apiextensions.k8s.io/v1
), OpenShift Console can automatically generate creation forms for operands. Schema properties are mapped to appropriate form field UI components using react-jsonschema-form. These mappings are primarily based on schema types (e.g. boolean
, text
, integer
, string
, string
with enum
, object
, and array
).
The auto-generated creation form is already powerful, but you may want to customize how the form is rendered. For example, you may want a more user-friendly displayName
, a more concise description
, to change form field ordering, or to exclude some non-user facing fields. This is where "specDescriptors" come in.
Check out the x-descriptors
reference guide which provides more detailed descriptions and examples of how to use them in specDescriptors and statusDescriptors.
The ordering of form fields depends on whether a field has a specDescriptor, is "required" (a required:
property in the schema), "optional", or "advanced" (assigned with an advanced specDecriptor). In general, fields with specDescriptors will be sorted higher than those without and required fields will be sorted higher than optional fields. The full set of sorting rules are as follows:
- "required" fields with specDescriptors other than advanced
- "required" fields without specDescriptors
- "optional" fields with specDescriptors other than advanced
- "optional" fields without specDescriptors
- Fields with advanced specDescriptors wrapped in the 'Advanced Configuration' group
To add a new React component associated with a spec/status descriptor, make a pull request against this repo that satisfies the following requirements:
- Make a React component that accepts props of type
DescriptorProps
and renders the spec/status value.
- Place component in its own module in either the
spec
orstatus
directory - Ensure that empty values and errors are properly handled
- Add a new "capability" URN to the
SpecCapability
/StatusCapability
enum intypes.ts
- Update the
capabilityComponents
map with the capability/component key-value pair.
All new descriptor components must have both unit and end-to-end tests. Frameworks and idiomatic examples of both exist in the codebase already and should be followed.
Located at frontend/__tests__/components/operator-lifecycle-manager/descriptors
.
Add a corresponding unit test file (named <module>.spec.tsx
) that imports your component and provides sufficient coverage.
$ yarn test