How-to

    In this section, it will introduce how to use CUE to declare app components via ComponentDefinition.

    Here is a CUE based ComponentDefinition example which provides a abstraction for stateless workload type:

    In detail:

    • .spec.workload is required to indicate the workload type of this component.
    • .spec.schematic.cue.template is a CUE template, specifically:
      • The output filed defines the template for the abstraction.
      • The parameter filed defines the template parameters, i.e. the configurable properties exposed in the Applicationabstraction (and JSON schema will be automatically generated based on them).

    Let’s declare another component named task, i.e. an abstraction for run-to-completion workload.

    1. apiVersion: core.oam.dev/v1beta1
    2. kind: ComponentDefinition
    3. metadata:
    4. name: task
    5. annotations:
    6. definition.oam.dev/description: "Describes jobs that run code or a script to completion."
    7. spec:
    8. workload:
    9. definition:
    10. apiVersion: batch/v1
    11. kind: Job
    12. schematic:
    13. cue:
    14. template: |
    15. output: {
    16. apiVersion: "batch/v1"
    17. kind: "Job"
    18. spec: {
    19. parallelism: parameter.count
    20. completions: parameter.count
    21. template: spec: {
    22. restartPolicy: parameter.restart
    23. containers: [{
    24. image: parameter.image
    25. if parameter["cmd"] != _|_ {
    26. command: parameter.cmd
    27. }
    28. }]
    29. }
    30. }
    31. }
    32. parameter: {
    33. count: *1 | int
    34. image: string
    35. restart: *"Never" | string
    36. cmd?: [...string]
    37. }

    Save above ComponentDefinition objects to files and install them to your Kubernetes cluster by $ kubectl apply -f stateless-def.yaml task-def.yaml

    Declare an Application

    1. apiVersion: core.oam.dev/v1alpha2
    2. kind: Application
    3. metadata:
    4. name: website
    5. spec:
    6. components:
    7. - name: hello
    8. type: stateless
    9. properties:
    10. image: crccheck/hello-world
    11. name: mysvc
    12. - name: countdown
    13. type: task
    14. properties:
    15. image: centos:7
    16. cmd:
    17. - "-c"
    18. - "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"

    Above application resource will generate and manage following Kubernetes resources in your target cluster based on the output in CUE template and user input in Application properties.

    KubeVela allows you to reference the runtime information of your application via context keyword.

    The most widely used context is application name(context.appName) component name(context.name).

    1. context: {
    2. appName: string
    3. name: string
    4. }

    For example, let’s say you want to use the component name filled in by users as the container name in the workload instance:

    1. parameter: {
    2. image: string
    3. }
    4. output: {
    5. ...
    6. spec: {
    7. containers: [{
    8. name: context.name
    9. image: parameter.image
    10. }]
    11. }
    12. ...
    13. }

    Full available information in CUE context

    Composition

    It’s common that a component definition is composed by multiple API resources, for example, a webserver component that is composed by a Deployment and a Service. CUE is a great solution to achieve this in simplified primitives.

    KubeVela requires you to define the template of workload type in output section, and leave all the other resource templates in outputs section with format as below:

    Below is the example for webserver definition:

    1. apiVersion: core.oam.dev/v1beta1
    2. kind: ComponentDefinition
    3. metadata:
    4. name: webserver
    5. annotations:
    6. definition.oam.dev/description: "webserver is a combo of Deployment + Service"
    7. spec:
    8. workload:
    9. definition:
    10. apiVersion: apps/v1
    11. kind: Deployment
    12. schematic:
    13. cue:
    14. template: |
    15. output: {
    16. apiVersion: "apps/v1"
    17. kind: "Deployment"
    18. spec: {
    19. selector: matchLabels: {
    20. "app.oam.dev/component": context.name
    21. }
    22. template: {
    23. metadata: labels: {
    24. "app.oam.dev/component": context.name
    25. }
    26. spec: {
    27. containers: [{
    28. name: context.name
    29. image: parameter.image
    30. if parameter["cmd"] != _|_ {
    31. command: parameter.cmd
    32. }
    33. if parameter["env"] != _|_ {
    34. }
    35. if context["config"] != _|_ {
    36. env: context.config
    37. }
    38. containerPort: parameter.port
    39. }]
    40. if parameter["cpu"] != _|_ {
    41. resources: {
    42. limits:
    43. cpu: parameter.cpu
    44. requests:
    45. cpu: parameter.cpu
    46. }
    47. }
    48. }]
    49. }
    50. }
    51. }
    52. }
    53. // an extra template
    54. outputs: service: {
    55. apiVersion: "v1"
    56. kind: "Service"
    57. spec: {
    58. selector: {
    59. "app.oam.dev/component": context.name
    60. }
    61. ports: [
    62. {
    63. port: parameter.port
    64. targetPort: parameter.port
    65. },
    66. ]
    67. }
    68. }
    69. parameter: {
    70. image: string
    71. cmd?: [...string]
    72. port: *80 | int
    73. env?: [...{
    74. name: string
    75. value?: string
    76. valueFrom?: {
    77. secretKeyRef: {
    78. name: string
    79. key: string
    80. }
    81. }
    82. }]
    83. cpu?: string
    84. }

    The user could now declare an Application with it:

    1. apiVersion: core.oam.dev/v1beta1
    2. kind: Application
    3. metadata:
    4. name: webserver-demo
    5. namespace: default
    6. spec:
    7. components:
    8. - name: hello-world
    9. type: webserver
    10. properties:
    11. image: crccheck/hello-world
    12. port: 8000
    13. env:
    14. - name: "foo"
    15. value: "bar"
    16. cpu: "100m"

    It will generate and manage below API resources in target cluster:

    What’s Next

    Please check the documentation about why we support CUE as first-class templating solution and more details about using CUE efficiently.