github.com/oam-dev/kubevela@v1.9.11/design/vela-cli/def.md (about)

     1  ---
     2  title: Writing X-Definitions with Vela CLI
     3  ---
     4  
     5  ## Introduction
     6  
     7  `vela def` is a group of commands designed for helping users managing definitions in KubeVela.
     8  
     9  ## Background
    10  
    11  In KubeVela, the main capability of definition is defined by the cue-format template. However, as a JSON-based language, cue-format template is not capatible with the original Kubernetes YAML format, which means we need to transform cue-format template into raw string while embedding it into the Kubernetes YAML objects. This made it relatively difficult to view or edit KubeVela definitions through native **kubectl** tool. For example, when we access a trait definition that attach labels to components, we can run `kubectl get trait labels -n vela-system -o yaml`, the result is as below
    12  
    13  ```yaml
    14  apiVersion: core.oam.dev/v1beta1
    15  kind: TraitDefinition
    16  metadata:
    17    annotations:
    18      definition.oam.dev/description: Add labels for your Workload.
    19      meta.helm.sh/release-name: kubevela
    20      meta.helm.sh/release-namespace: vela-system
    21    creationTimestamp: "2021-08-05T07:06:58Z"
    22    generation: 1
    23    labels:
    24      app.kubernetes.io/managed-by: Helm
    25    name: labels
    26    namespace: vela-system
    27    resourceVersion: "8423"
    28    uid: 51a7f8b1-f14d-4776-b538-02ac54a55661
    29  spec:
    30    appliesToWorkloads:
    31    - deployments.apps
    32    podDisruptive: true
    33    schematic:
    34      cue:
    35        template: "patch: spec: template: metadata: labels: {\n\tfor k, v in parameter
    36          {\n\t\t\"\\(k)\": v\n\t}\n}\nparameter: [string]: string\n"
    37  status:
    38    configMapRef: schema-labels
    39    latestRevision:
    40      name: labels-v1
    41      revision: 1
    42      revisionHash: fe7fa9da440dc9d3
    43  ```
    44  
    45  We can see that the core ability of the *labels* definition locates at `spec.schematic.cue.template` and is escaped into raw string. It is hard to identify and manipulate.
    46  
    47  On the other hand, although cuelang has very strong expression capabilities, it is still relatively new to many Kubernetes developers who might takes some extra time to learn when leveraging the power of cuelang.
    48  
    49  Therefore, KubeVela team introduce a series of functions in the `vela` CLI tool, aiming to help developers design all kinds of definitions conveniently.
    50  
    51  ## Design
    52  
    53  As mentioned above, the CUE-YAML-mixed-style KubeVela definition, is represented by a single cue-format definition file in v1.1, which expresses the content and description of defintiion more clearly and briefly. The `labels` definition above can be represented by the following file
    54  
    55  ```json
    56  // labels.cue
    57  labels: {
    58          annotations: {}
    59          attributes: {
    60                  appliesToWorkloads: ["deployments.apps"]
    61                  podDisruptive: true
    62          }
    63          description: "Add labels for your Workload."
    64          labels: {}
    65          type: "trait"
    66  }
    67  template: {
    68          patch: spec: template: metadata: labels: {
    69                  for k, v in parameter {
    70                          "\(k)": v
    71                  }
    72          }
    73          parameter: [string]: string
    74  }
    75  ```
    76  
    77  The first part `labels: {...}` expresses the basic information of the definition, including its type, description, labels, annotations and attributes. The second part `template: {...}` describes the capability of the definition. With the `vela def` command group,KubeVela users can directly interact with the CUE-format file instead of facing the complex YAML file.
    78  
    79  ## Details
    80  
    81  ### init
    82  
    83  `vela def init` is a command that helps users bootstrap new definitions. To create an empty trait definition, run `vela def init my-trait -t trait --desc "My trait description."`
    84  
    85  ```json
    86  "my-trait": {
    87          annotations: {}
    88          attributes: {
    89                  appliesToWorkloads: []
    90                  conflictsWith: []
    91                  definitionRef:   ""
    92                  podDisruptive:   false
    93                  workloadRefPath: ""
    94          }
    95          description: "My trait description."
    96          labels: {}
    97          type: "trait"
    98  }
    99  template: {
   100          patch: {}
   101          parameter: {}
   102  }
   103  ```
   104  
   105  Or you can use `vela def init my-comp --interactive` to initiate definitions interactively.
   106  
   107  ```bash
   108  $ vela def init my-comp --interactive
   109  Please choose one definition type from the following values: component, trait, policy, workload, scope, workflow-step
   110  > Definition type: component
   111  > Definition description: My component definition.
   112  Please enter the location the template YAML file to build definition. Leave it empty to generate default template.
   113  > Definition template filename: 
   114  Please enter the output location of the generated definition. Leave it empty to print definition to stdout.
   115  > Definition output filename: my-component.cue
   116  Definition written to my-component.cue
   117  ```
   118  
   119  In addition, users can create definitions from existing YAML files. For example, if a user want to create a ComponentDefinition which is designed to generate a deployment, and this deployment has already been created elsewhere, he/she can use the `--template-yaml` flag to complete the transformation. The YAML file is as below
   120  
   121  ```yaml
   122  apiVersion: apps/v1
   123  kind: Deployment
   124  metadata:
   125    name: hello-world
   126  spec:
   127    replicas: 1
   128    selector:
   129      matchLabels:
   130        app.kubernetes.io/name: hello-world
   131    template:
   132      metadata:
   133        labels:
   134          app.kubernetes.io/name: hello-world
   135      spec:
   136        containers:
   137        - name: hello-world
   138          image: somefive/hello-world
   139          ports: 
   140          - name: http
   141            containerPort: 80
   142            protocol: TCP
   143  ---
   144  apiVersion: v1
   145  kind: Service
   146  metadata:
   147    name: hello-world-service
   148  spec:
   149    selector:
   150      app: hello-world
   151    ports:
   152    - name: http
   153      protocol: TCP
   154      port: 80
   155      targetPort: 8080
   156    type: LoadBalancer
   157  ```
   158  
   159  Running `vela def init my-comp -t component --desc "My component." --template-yaml ./my-deployment.yaml` to get the CUE-format ComponentDefinition
   160  
   161  ```json
   162  "my-comp": {
   163          annotations: {}
   164          attributes: workload: definition: {
   165                  apiVersion: "<change me> apps/v1"
   166                  kind:       "<change me> Deployment"
   167          }
   168          description: "My component."
   169          labels: {}
   170          type: "component"
   171  }
   172  template: {
   173          output: {
   174                  metadata: name: "hello-world"
   175                  spec: {
   176                          replicas: 1
   177                          selector: matchLabels: "app.kubernetes.io/name": "hello-world"
   178                          template: {
   179                                  metadata: labels: "app.kubernetes.io/name": "hello-world"
   180                                  spec: containers: [{
   181                                          name:  "hello-world"
   182                                          image: "somefive/hello-world"
   183                                          ports: [{
   184                                                  name:          "http"
   185                                                  containerPort: 80
   186                                                  protocol:      "TCP"
   187                                          }]
   188                                  }]
   189                          }
   190                  }
   191                  apiVersion: "apps/v1"
   192                  kind:       "Deployment"
   193          }
   194          outputs: "hello-world-service": {
   195                  metadata: name: "hello-world-service"
   196                  spec: {
   197                          ports: [{
   198                                  name:       "http"
   199                                  protocol:   "TCP"
   200                                  port:       80
   201                                  targetPort: 8080
   202                          }]
   203                          selector: app: "hello-world"
   204                          type: "LoadBalancer"
   205                  }
   206                  apiVersion: "v1"
   207                  kind:       "Service"
   208          }
   209          parameter: {}
   210  
   211  }
   212  ```
   213  
   214  Then the user can make further modifications based on the definition file above, like removing *\<change me\>* in **workload.definition**。
   215  
   216  ### vet
   217  
   218  After initializing definition files, run `vela def vet my-comp.cue` to validate if there are any syntax error in the definition file. It can be used to detect some simple errors such as missing brackets.
   219  
   220  ```bash
   221  $ vela def vet my-comp.cue
   222  Validation succeed.
   223  ```
   224  
   225  ### render / apply
   226  
   227  After confirming the definition file has correct syntax. users can run  `vela def apply my-comp.cue --namespace my-namespace` to apply this definition in the `my-namespace` namespace。If you want to check the transformed Kubernetes YAML file, `vela def apply my-comp.cue --dry-run` or `vela def render my-comp.cue -o my-comp.yaml` can achieve that.
   228  
   229  ```yaml
   230  apiVersion: core.oam.dev/v1beta1
   231  kind: ComponentDefinition
   232  metadata:
   233    annotations:
   234      definition.oam.dev/description: My component.
   235    labels: {}
   236    name: my-comp
   237    namespace: vela-system
   238  spec:
   239    schematic:
   240      cue:
   241        template: |
   242          output: {
   243                  metadata: name: "hello-world"
   244                  spec: {
   245                          replicas: 1
   246                          selector: matchLabels: "app.kubernetes.io/name": "hello-world"
   247                          template: {
   248                                  metadata: labels: "app.kubernetes.io/name": "hello-world"
   249                                  spec: containers: [{
   250                                          name:  "hello-world"
   251                                          image: "somefive/hello-world"
   252                                          ports: [{
   253                                                  name:          "http"
   254                                                  containerPort: 80
   255                                                  protocol:      "TCP"
   256                                          }]
   257                                  }]
   258                          }
   259                  }
   260                  apiVersion: "apps/v11"
   261                  kind:       "Deployment"
   262          }
   263          outputs: "hello-world-service": {
   264                  metadata: name: "hello-world-service"
   265                  spec: {
   266                          ports: [{
   267                                  name:       "http"
   268                                  protocol:   "TCP"
   269                                  port:       80
   270                                  targetPort: 8080
   271                          }]
   272                          selector: app: "hello-world"
   273                          type: "LoadBalancer"
   274                  }
   275                  apiVersion: "v1"
   276                  kind:       "Service"
   277          }
   278          parameter: {}
   279    workload:
   280      definition:
   281        apiVersion: apps/v1
   282        kind: Deployment
   283  ```
   284  
   285  ```bash
   286  $ vela def apply my-comp.cue -n my-namespace
   287  ComponentDefinition my-comp created in namespace my-namespace.
   288  ```
   289  
   290  ### get / list / edit / del
   291  
   292  While you can use native kubectl tools to confirm the results of the apply command, as mentioned above, the YAML object mixed with raw CUE template string is complex. Using `vela def get` will automatically convert the YAML object into the CUE-format definition.
   293  
   294  ```bash
   295  $ vela def get my-comp -t component
   296  ```
   297  
   298  Or you can list all defintions installed through `vela def list`
   299  
   300  ```bash
   301  $ vela def list -n my-namespace -t component
   302  NAME                    TYPE                    NAMESPACE       DESCRIPTION  
   303  my-comp                 ComponentDefinition     my-namespace    My component.
   304  ```
   305  
   306  Similarly, using `vela def edit` to edit definitions in pure CUE-format. The transformation between CUE-format definition and YAML object is done by the command. Besides, you can specify the `EDITOR` environment variable to use your favourate editor.
   307  
   308  ```bash
   309  $ EDITOR=vim vela def edit my-comp
   310  ```
   311  
   312  Finally, `vela def del` can be utilized to delete existing definitions.
   313  
   314  ```bash
   315  $ vela def del my-comp -n my-namespace  
   316  Are you sure to delete the following definition in namespace my-namespace?
   317  ComponentDefinition my-comp: My component.
   318  [yes|no] > yes
   319  ComponentDefinition my-comp in namespace my-namespace deleted.
   320  ```
   321