Version: v1.2

更多用法

CUE 作为一种配置语言,可以让你在定义对象的时候使用更多进阶用法。

一次渲染多个资源

你可以在 outputs 里定义 For 循环。

注意在 For 循环里的 parameter 字段必须是 map 类型。

看看如下这个例子,在一个 TraitDefinition 对象里渲染多个 Service

  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. }

这个运维特征可以这样使用:

  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

自定义运维特征里执行 HTTP Request

TraitDefinition 对象可以发送 HTTP 请求并获取应答,让你可以通过关键字 processing 来渲染资源。

你可以在 processing.http 里定义 HTTP 请求的 method, url, body, headertrailer,然后返回的数据将被存储在 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. }

在上面这个例子中,TraitDefinition 对象发送请求来获取 token 的数据,然后将这些数据补丁给组件实例。

数据传递

TraitDefinition 对象可以读取特定 ComponentDefinition 对象生成的 API 资源(渲染自 outputoutputs)。

KubeVela 保证了 ComponentDefinition 一定会在 TraitDefinition 之前渲染

具体来说,context.output 字段包含了所有渲染后的工作负载 API 资源,然后 context.outputs.<xx> 则包含渲染后的其它类型 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. 渲染的 Deployment 资源放在 context.output 中。
  2. 其它类型资源则放进 context.outputs.<xx> 中,同时 <xx> 是在特指 template.outputs 的唯一名字

因而,TraitDefinition 对象可以从 context 里读取渲染后的 API 资源(比如 context.outputs.gameconfig.data.enemies 这个字段)。