Commodore Component Developer Guidelines
This page defines the various conventions and best practices for writing a Commodore component for OpenShift 4.
See the Writing a Commodore Component guide for a more general introduction and technical details of Commodore components. |
Conventions Used in These Guidelines
The requirement level keywords must, must not, required, shall, shall not, should, shouldn’t, recommended, may, and optional used in this document are to be interpreted as described in RFC 2119.
Component Naming
The name of a component which configures something OpenShift 4 specific must be prefixed with openshift4-
.
When using the
|
Operator Lifecycle Manager (OLM)
We recommend to avoid using the OLM to install operators on a cluster. This is mainly due to the added complexity the OLM introduces and us not using any of it’s features. This might change in the future.
Exceptions to this rule include cases where the Red Hat documentation explicitly requires the OLM.
Any operators we do install with the OLM should be restricted to single namespaces and must not be installed using the AllNamespaces
InstallMode.
We don’t provide any support for operators installed by customers via the OLM.
CustomResource (CR) Specs
Components which configure one or multiple CRs should do so by exposing its .spec
field as a parameter.
This enables the configuration of all possible fields via the inventory and provides maximum flexibility.
Default values may either be set in the defaults.yml
file of the component or in Jsonnet code.
It should always be possible to override default values in the inventory.
Lists in the inventory get extended by reclass when being merged together. This means that the items of each list are added together in a new list. It can lead to undesired behavior if not accounted for. |
When creating multiple CRs, a dict should be used where its keys map to the names used for the CRs. Iterating over the keys of this dict in Jsonnet enables the enrichment of possible default values. This allows to omit default values within the inventory.
Due to the way reclass handels null
overrides, the component must handle null
values in dicts and lists gracefully.
local ingressControllers =
if params.ingressControllers != null
then std.objectFields(params.ingressControllers)
else [];
{
[name]:
[kube._Object('operator.openshift.io/v1', 'IngressController', name) {
metadata+: {
namespace: params.namespace,
},
spec: {
defaultCertificate: {
name: acmeCertName,
},
} + params.ingressControllers[name],
}]
for name in ingressControllers
} + {
[if std.length(ingressControllers) == 0 then '.gitkeep']: {},
}
Inventory Parameters
A component may define various parameters in the inventory (defaults.yml
).
These must be namespaced in a dict with the component’s name (hyphens replaced with underscores).
A group of components may agree upon a common prefix to share parameters between each other.
parameters:
openshift4_ingress:
namespace: openshift-ingress
cloud:
provider: ${cloud:provider}
ingressControllers:
default:
replicas: 2
If the component requires additional information like the cloud provider, cluster version or infrastructure ID, these may also be accessed via parameters of the inventory (usually in the form of facts). In the future this information will be automatically collected on the cluster and exposed in the inventory as facts. For information which isn’t yet collected automatically, a manual entry in the cluster’s class is required.
parameters:
openshift:
infraID: c-mist-x7bvn
clusterID: ce7e78b4-dead-beef-9367-7c2223d2506b
appsDomain: apps.example.com
To avoid a high coupling of components, parameters of other components must not be referenced directly. There must always be a "glue-layer" to provide such parameters. In other words: a component must only reference parameters in its own inventory namespace (dict).
The following example shows how the hostname
field of the openshift4-registry
component is set in the inventory using the openshift:appsDomain
fact, instead of using the fact in the component directly:
parameters:
openshift4_registry:
config:
routes:
- name: registry-route
hostname: registry.${openshift:appsDomain}
Security Contexts
You should always explicitly set Security Contexts and request the minimum permission necessary to run the application.
OpenShift Security Context Constraints come with a modifying webhook that will provide defaults for Security Contexts. However, on OpenShift 4.11, relying on these defaults clashes with the Pod Security Admission and will result in warnings. Please consult the explanation on Pod Security for more details on how SCCs and PSA interact.