Version: v1.0

高级功能

作为数据配置语言,CUE 对于自定义结构体支持一些黑魔法。

循环渲染多个资源

你可以在 outputs 定义 for 循环。

⚠️注意,本示例中 parameter 必须是字典类型。

如下所示,该示例将展示如何在 trait 中渲染多个 Kubernetes Services:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: TraitDefinition
  3. metadata:
  4. name: expose
  5. spec:
  6. schematic:
  7. cue:
  8. template: |
  9. parameter: {
  10. http: [string]: int
  11. }
  12. outputs: {
  13. for k, v in parameter.http {
  14. "\(k)": {
  15. apiVersion: "v1"
  16. kind: "Service"
  17. spec: {
  18. selector:
  19. app: context.name
  20. ports: [{
  21. port: v
  22. targetPort: v
  23. }]
  24. }
  25. }
  26. }
  27. }

上面 trait 对象可以在以下 Application 被使用:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: testapp
  5. spec:
  6. components:
  7. - name: express-server
  8. type: webservice
  9. properties:
  10. ...
  11. traits:
  12. - type: expose
  13. properties:
  14. http:
  15. myservice1: 8080
  16. myservice2: 8081

Trait Definition 中请求 HTTP 接口

Trait Definition 中可以发送 HTTP 请求并借助字段 processing 将响应结果用于渲染资源。

你可以在 processing.http 字段下定义 HTTP 请求所需的字段,包括:methodurlbodyheadertrailer ,响应将会被存储在 processing.output 字段中。

此处需要确认目标 HTTP 服务返回数据格式为 JSON

随后你可以在 patch 或者 output/outputs 字段中引用 processing.output 自动中的返回数据。

如下所示:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: TraitDefinition
  3. metadata:
  4. name: auth-service
  5. spec:
  6. schematic:
  7. cue:
  8. template: |
  9. parameter: {
  10. serviceURL: string
  11. }
  12. processing: {
  13. output: {
  14. token?: string
  15. }
  16. // The target server will return a JSON data with `token` as key.
  17. http: {
  18. method: *"GET" | string
  19. url: parameter.serviceURL
  20. request: {
  21. body?: bytes
  22. header: {}
  23. trailer: {}
  24. }
  25. }
  26. }
  27. patch: {
  28. data: token: processing.output.token
  29. }

以上示例,该 Trait Definition 将发送请求获取 token 信息,并将数据插入到给定到 component 实例中。

数据传递

TraitDefinition 可以从给定的 ComponentDefinition 中读取已经被生成的 API 资源(从 output and outputs 中被渲染)。

KubeVela 会确保 ComponentDefinition 会先于 TraitDefinition 被渲染出来。

具体来说,context.output 字段中会包含已经被渲染的 workload API 资源(特指 GVK 已经在 ComponentDefinition 中 spec.workload 字段定义的资源),同时 context.outputs.<xx> 字段中会包含其他已经被渲染的非 workload API 资源。

下面是数据传递的示例:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: ComponentDefinition
  3. metadata:
  4. name: worker
  5. spec:
  6. workload:
  7. definition:
  8. apiVersion: apps/v1
  9. kind: Deployment
  10. schematic:
  11. cue:
  12. template: |
  13. output: {
  14. apiVersion: "apps/v1"
  15. kind: "Deployment"
  16. spec: {
  17. selector: matchLabels: {
  18. "app.oam.dev/component": context.name
  19. }
  20. template: {
  21. metadata: labels: {
  22. "app.oam.dev/component": context.name
  23. }
  24. spec: {
  25. containers: [{
  26. name: context.name
  27. image: parameter.image
  28. ports: [{containerPort: parameter.port}]
  29. envFrom: [{
  30. configMapRef: name: context.name + "game-config"
  31. }]
  32. if parameter["cmd"] != _|_ {
  33. command: parameter.cmd
  34. }
  35. }]
  36. }
  37. }
  38. }
  39. }
  40. outputs: gameconfig: {
  41. apiVersion: "v1"
  42. kind: "ConfigMap"
  43. metadata: {
  44. name: context.name + "game-config"
  45. }
  46. data: {
  47. enemies: parameter.enemies
  48. lives: parameter.lives
  49. }
  50. }
  51. parameter: {
  52. // +usage=Which image would you like to use for your service
  53. // +short=i
  54. image: string
  55. // +usage=Commands to run in the container
  56. cmd?: [...string]
  57. lives: string
  58. enemies: string
  59. port: int
  60. }
  61. ---
  62. apiVersion: core.oam.dev/v1beta1
  63. kind: TraitDefinition
  64. metadata:
  65. name: ingress
  66. spec:
  67. schematic:
  68. cue:
  69. template: |
  70. parameter: {
  71. domain: string
  72. path: string
  73. exposePort: int
  74. }
  75. // trait template can have multiple outputs in one trait
  76. outputs: service: {
  77. apiVersion: "v1"
  78. kind: "Service"
  79. spec: {
  80. selector:
  81. app: context.name
  82. ports: [{
  83. port: parameter.exposePort
  84. targetPort: context.output.spec.template.spec.containers[0].ports[0].containerPort
  85. }]
  86. }
  87. }
  88. outputs: ingress: {
  89. apiVersion: "networking.k8s.io/v1beta1"
  90. kind: "Ingress"
  91. metadata:
  92. name: context.name
  93. labels: config: context.outputs.gameconfig.data.enemies
  94. spec: {
  95. rules: [{
  96. host: parameter.domain
  97. http: {
  98. paths: [{
  99. path: parameter.path
  100. backend: {
  101. serviceName: context.name
  102. servicePort: parameter.exposePort
  103. }
  104. }]
  105. }
  106. }]
  107. }
  108. }

关于 worker ComponentDefinition 渲染期间的一些细节:

  1. workload,渲染完成的 Kubernetes Deployment 资源将存储在 context.output 字段中。
  2. 非 workload,其他渲染完成的资源将存储在 context.outputs.<xx> 字段中,其中 <xx> 在每个 template.outputs 字段中名字都是唯一的。

综上,TraitDefinition 可以从 context 字段读取完成渲染的 API 资源(比如:context.outputs.gameconfig.data.enemies)。