Using custom definitions
The platform supports adding your own OAM extensions to create new Components, Traits, Policies, and Workflow Steps that better adapt to your needs. This capability is able to substitute the approach of using custom Kubernetes operators in a multitude of use cases. By creating your own definition you will be able to configure which low-level entities are rendered in Kubernetes so this feature is oriented to experienced users that are already familiar with the Kubernetes tooling. The following sections describe how to create a custom definition and use it in an application.
- Using CUE templates
- Creating your own ComponentDefinition
- Launching an application that uses custom ComponentDefinitions
- FAQ
Using CUE templates
The preferred and simplest method to include a new custom entity is by using a CUE template. The CUE language offers a programmatic approach to static templates so it is possible to operate on the properties provided by the user when launching an Application to determine how those are applied internally. The objective of the CUE template is to render one or more entities after its evaluation. For example, to create a new TraitDefinition, you will need to define the new entity and include the CUE template.
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: This is the trait description
name: example-trait
spec:
schematic:
cue:
template: |
// Define the outputs of this trait
outputs: output1: {
apiVersion: "<api_version>"
kind: "<kind>"
metadata: name: context.name
spec: {
...
}
}
parameter: {
// +usage=Port to launch the service.
port: int
// +usage=Path to be loaded
path: string
}
In this entity you will define the rendered objects making use of the CUE language. The following section will describe how to create a custom component definition.
Creating your own ComponentDefinition
Creating a custom definition can be useful in situations where we would like to standarize operations, create custom extensions, or any other aspect that can benefit from such customization. In this example, we would consider a use case where an organization would like to create a custom ComponentDefinition for an elements that should be reused among all applications. This can be easily done by means of adding a component such as the following one:
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
annotations:
definition.oam.dev/description: Deploy the default nginx server.
name: org-webserver
spec:
schematic:
cue:
template: |
output: {
apiVersion: "apps/v1"
kind: "Deployment"
spec: {
selector: matchLabels: "app.oam.dev/component": context.name
template: {
metadata: labels: {
"app.oam.dev/name": context.appName
"app.oam.dev/component": context.name
}
spec: {
containers: [{
name: context.name
image: "nginx:1.23.0"
if parameter["cpu"] != _|_ {
resources: {
limits: cpu: parameter.cpu
requests: cpu: parameter.cpu
}
}
if parameter["memory"] != _|_ {
resources: {
limits: memory: parameter.memory
requests: memory: parameter.memory
}
}
}
]
}
}
}
}
parameter: {
// +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)
cpu?: string
// +usage=Specifies the attributes of the memory resource required for the container.
memory?: string
}
workload:
definition:
apiVersion: apps/v1
kind: Deployment
type: deployments.apps
In this case the component will automatically launch a Kubernetes Deployment with the nginx image already set. The component offers a set of parameters such as the cpu
, or memory
so that the application can customize those. While this is a minimal example, it also illustrates an approach to reduce the number of potential parameters on the existing components.
Launching an application that uses custom ComponentDefinitions
To launch an application using the previous org-webserver component type, let’s use the following application:
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: example-app-custom-def
spec:
components:
- name: my-server
type: org-webserver
and proceed to launch it with the CLI.
-
First create the component so that it can be used by the applications in the same environment.
$ playground def component create components/custom.server.component.yaml Target environment: <account>/<env_name> STATUS INFO SUCCESS Component [org-webserver] added
-
Create the application
$ playground apps create example-app-custom-def.yaml STATUS INFO SUCCESS application [example-app-custom-def] deployed CREATED core.oam.dev/v1beta1, Kind=Application "example-app-custom-def" created
Removing a custom definition
Before removing a custom definition make sure that no active applications are using it. The removal process can be done with the web UI after selecting the definition to be removed, or with the CLI with:
playground def <type> remove <name>
FAQ
Cannot create application
The platform may refuse creating an application with the following error:
playground apps create my-custom-component.yaml
[Internal] error creating entity caused by admission webhook "validating.core.oam.dev.v1beta1.applications" denied the request: field "schematic": Invalid value error encountered, cannot create the validation process context of app=<application_name> in namespace=<namespace>: evaluate base template app=<application_name> in namespace=<namespace>: invalid cue template of workload my-server: expected 'EOF', found '}'.
Which could indicate a mismatch between open and closed brackets.
Cannot create object when creating the application
If the application is created, but contains an error when applying the component as:
Dispatch: Found 1 errors. [(cannot create object: Deployment in version "v1" cannot be handled as a ...: []v1.Container: decode slice: expect [ or n, but found {, error found in #10 byte of ...|tainers":{"container|..., bigger context ...|:"<application_name>"}},...]
The error could be caused by an incorrect schematic inside the CUE template. For example, labels are not being included inside the proper metadata section, or declaring a section that does not expect that type such as using a single element when a list is expected.
What’s next
- Review the Application and Environments core concepts.
- Follow the tutorial to deploying a custom application