From 4f8bf44684f2998c76afb5a4ca804f10e466c5d7 Mon Sep 17 00:00:00 2001 From: Tianxin Dong Date: Sat, 27 Jul 2024 17:44:20 +0800 Subject: [PATCH] Refactor: use cuex engine (#6575) * refactor: use cuex engine Signed-off-by: FogDong * fix: fix lint Signed-off-by: FogDong * fix: fix unit test Signed-off-by: FogDong * fix: fix static check and sdk tests Signed-off-by: FogDong * fix: fix testdata Signed-off-by: FogDong * fix: fix velaql unit test Signed-off-by: FogDong * fix: fix docgen parser Signed-off-by: FogDong * fix: fix cuegen Signed-off-by: FogDong * fix: fix velaql Signed-off-by: FogDong * fix: delete useless print Signed-off-by: FogDong * fix: set client for ql Signed-off-by: FogDong * fix: fix mt tests Signed-off-by: FogDong * fix: set kubeclient in generator Signed-off-by: FogDong * fix: use pass kube client Signed-off-by: FogDong * fix: simplify ql Signed-off-by: FogDong * fix: fix lint Signed-off-by: FogDong * fix: add wf debug back Signed-off-by: FogDong * fix: add loader Signed-off-by: FogDong --------- Signed-off-by: FogDong --- .gitignore | 1 + Makefile | 3 +- .../v1beta1/resourcetracker_types_test.go | 2 +- .../collect-service-endpoints.yaml | 14 +- .../templates/defwithtemplate/command.yaml | 8 +- .../defwithtemplate/container-image.yaml | 6 +- .../defwithtemplate/container-ports.yaml | 12 +- .../templates/defwithtemplate/cron-task.yaml | 20 +- .../templates/defwithtemplate/daemon.yaml | 8 +- .../defwithtemplate/depends-on-app.yaml | 8 +- .../templates/defwithtemplate/env.yaml | 12 +- .../defwithtemplate/export-data.yaml | 6 +- .../defwithtemplate/export-service.yaml | 6 +- .../templates/defwithtemplate/expose.yaml | 2 +- .../templates/defwithtemplate/gateway.yaml | 6 +- .../generate-jdbc-connection.yaml | 8 +- .../templates/defwithtemplate/nocalhost.yaml | 8 +- .../defwithtemplate/notification.yaml | 10 +- .../defwithtemplate/service-account.yaml | 8 +- .../templates/defwithtemplate/sidecar.yaml | 2 +- .../defwithtemplate/startup-probe.yaml | 6 +- .../templates/defwithtemplate/storage.yaml | 16 +- .../templates/defwithtemplate/task.yaml | 6 +- .../templates/defwithtemplate/webhook.yaml | 16 +- .../templates/defwithtemplate/webservice.yaml | 8 +- .../templates/defwithtemplate/worker.yaml | 6 +- cmd/core/app/server.go | 10 - e2e/plugin/plugin_test.go | 2 +- go.mod | 26 +- go.sum | 52 +-- pkg/addon/addon.go | 52 +-- pkg/addon/addon_suite_test.go | 4 +- pkg/addon/addon_test.go | 4 +- pkg/addon/helper.go | 4 +- pkg/addon/render.go | 64 ++-- pkg/addon/suite_test.go | 6 - pkg/appfile/appfile.go | 11 +- pkg/appfile/appfile_test.go | 6 +- pkg/appfile/dryrun/diff.go | 7 +- pkg/appfile/dryrun/diff_test.go | 4 +- pkg/appfile/dryrun/dryrun.go | 11 +- pkg/appfile/dryrun/suit_test.go | 10 +- pkg/appfile/parser.go | 12 +- pkg/appfile/parser_test.go | 16 +- pkg/appfile/suit_test.go | 6 - pkg/appfile/validate_test.go | 6 +- pkg/cache/informer.go | 6 +- pkg/config/factory.go | 8 +- pkg/config/factory_test.go | 6 +- pkg/config/provider/provider.go | 147 -------- pkg/config/writer/nacos.go | 29 +- pkg/config/writer/nacos_test.go | 8 +- pkg/config/writer/writer.go | 7 +- pkg/config/writer/writter_test.go | 8 +- .../core.oam.dev/oamruntime_controller.go | 5 - .../application/application_controller.go | 7 +- .../core.oam.dev/v1beta1/application/apply.go | 22 +- .../v1beta1/application/apply_test.go | 2 +- .../v1beta1/application/assemble/suit_test.go | 6 +- .../v1beta1/application/dispatcher.go | 6 +- .../v1beta1/application/gc_policy_test.go | 2 +- .../v1beta1/application/generator.go | 114 +++--- .../v1beta1/application/revision_test.go | 8 +- .../v1beta1/application/suite_test.go | 10 +- .../v1beta1/application/workflow_test.go | 8 +- .../workflowstepdefinition/suite_test.go | 2 + pkg/controller/utils/capability.go | 35 +- .../utils/capability_integrate_test.go | 2 +- pkg/controller/utils/capability_suite_test.go | 6 - pkg/controller/utils/capability_test.go | 2 +- pkg/cue/convert.go | 18 +- pkg/cue/convert_test.go | 10 +- pkg/cue/cuex/compiler.go | 4 +- pkg/cue/definition/template.go | 51 +-- pkg/cue/definition/template_test.go | 19 +- pkg/cue/script/template.go | 239 +++++++++---- pkg/cue/script/template_test.go | 59 +--- pkg/definition/definition.go | 24 +- pkg/definition/gen_sdk/gen_sdk.go | 33 +- pkg/definition/gen_sdk/gen_sdk_test.go | 3 +- pkg/resourcetracker/app.go | 4 +- pkg/rollout/suit_test.go | 6 - pkg/{cue/script => schema}/schema.go | 83 ++--- pkg/{cue/script => schema}/schema_test.go | 2 +- .../testdata/arrayWithoutItemsSchema.json | 0 .../arrayWithoutItemsSchemaFixed.json | 0 .../testdata/shortTagSchema.json | 0 .../testdata/shortTagSchemaFixed.json | 0 .../testdata/webservice.json | 0 .../testdata/webserviceFixed.json | 0 pkg/stdlib/op.cue | 93 ----- pkg/stdlib/packages.go | 76 ---- pkg/stdlib/packages_test.go | 55 --- pkg/stdlib/pkgs/oam.cue | 55 --- pkg/stdlib/ql.cue | 81 ----- pkg/utils/apply/apply.go | 16 +- pkg/utils/common/args.go | 23 -- pkg/utils/common/common.go | 41 +-- pkg/utils/common/common_test.go | 25 +- pkg/utils/k8s.go | 2 +- .../query => utils}/types/health_status.go | 0 .../types/type.go => utils/types/ql_type.go} | 36 +- pkg/velaql/context.go | 110 ------ pkg/velaql/parse.go | 16 +- pkg/velaql/providers/query/utils_test.go | 83 ----- pkg/velaql/suite_test.go | 13 +- pkg/velaql/view.go | 125 ++----- pkg/velaql/view_test.go | 8 +- .../v1beta1/application/suite_test.go | 9 +- .../v1beta1/application/validating_handler.go | 7 +- .../v1beta1/application/validation.go | 2 +- pkg/workflow/operation/operation.go | 2 +- pkg/workflow/operation/suit_test.go | 6 - pkg/workflow/providers/compiler.go | 46 +++ .../providers/legacy/config/config.cue | 42 +++ .../providers/legacy/config/config.go | 156 +++++++++ .../providers/legacy/config/config_test.go} | 123 ++++--- pkg/workflow/providers/legacy/legacy.go | 59 ++++ .../{ => legacy}/multicluster/deploy.go | 102 +++--- .../{ => legacy}/multicluster/deploy_test.go | 14 +- .../legacy/multicluster}/multicluster.cue | 156 ++++----- .../legacy/multicluster/multicluster.go | 227 ++++++++++++ .../multicluster/multicluster_test.go | 300 +++++++--------- pkg/workflow/providers/legacy/oam/apply.go | 221 ++++++++++++ .../providers/legacy/oam/apply_test.go | 205 +++++++++++ pkg/workflow/providers/legacy/oam/oam.cue | 128 +++++++ .../providers/legacy}/query/collector.go | 14 +- .../providers/legacy}/query/endpoint.go | 35 +- .../providers/legacy}/query/endpoint_test.go | 47 +-- .../providers/legacy}/query/handler.go | 233 +++++++------ .../providers/legacy}/query/handler_test.go | 329 +++++++----------- .../providers/legacy/query/ql.cue} | 16 +- .../providers/legacy}/query/suite_test.go | 3 +- .../gateway.networking.k8s.io_gateways.yaml | 0 .../gateway.networking.k8s.io_httproutes.yaml | 0 .../query/testdata/gateway/gateway-tls.yaml | 0 .../query/testdata/gateway/gateway.yaml | 0 .../query/testdata/gateway/http-route.yaml | 0 .../query/testdata/gateway/https-route.yaml | 0 .../query/testdata/helm-release-crd.yaml | 0 ...elearning.seldon.io_seldondeployments.yaml | 0 .../providers/legacy}/query/tree.go | 5 +- .../providers/legacy}/query/tree_test.go | 65 ++-- .../providers/legacy}/query/utils.go | 26 +- .../providers/legacy/query/utils_test.go | 17 + .../providers/legacy/terraform}/terraform.cue | 85 +++-- .../providers/legacy/terraform/terraform.go | 125 +++++++ .../{ => legacy}/terraform/terraform_test.go | 111 +++--- pkg/workflow/providers/legacy/types/types.go | 180 ++++++++++ .../providers/multicluster/multicluster.go | 198 ----------- pkg/workflow/providers/oam/apply.go | 257 -------------- pkg/workflow/providers/oam/apply_test.go | 222 ------------ pkg/workflow/providers/terraform/terraform.go | 78 ----- pkg/workflow/providers/time/date.go | 79 ----- pkg/workflow/providers/time/date_test.go | 163 --------- .../static/builtin-apply-component.cue | 3 +- references/appfile/addon.go | 9 +- references/cli/config.go | 2 +- references/cli/debug.go | 103 +++--- references/cli/def.go | 5 +- references/cli/dryrun.go | 6 +- references/cli/exec.go | 2 +- references/cli/kube.go | 9 +- references/cli/livediff.go | 6 +- references/cli/logs.go | 2 +- references/cli/portforward.go | 2 +- references/cli/registry.go | 2 +- references/cli/revision.go | 10 +- references/cli/show.go | 12 +- references/cli/status.go | 22 +- references/cli/suite_test.go | 2 + .../cli/test-data/addon/sample/Chart.yaml | 2 + references/cli/top/component/tree_node.go | 2 +- .../cli/top/component/tree_node_test.go | 2 +- references/cli/top/model/application.go | 6 +- references/cli/top/model/managed_resource.go | 2 +- references/cli/top/model/pod.go | 2 +- references/cli/top/model/resource.go | 16 +- references/cli/top/model/resource_test.go | 6 +- .../cli/top/view/application_topology_view.go | 2 +- .../cli/top/view/managed_resource_view.go | 2 +- references/cli/utils.go | 2 +- references/cli/velaql.go | 32 +- references/cli/workflow.go | 12 +- references/cmd/cli/main.go | 7 - references/common/application.go | 16 +- references/common/metrics.go | 2 +- references/cuegen/testdata/nullable.cue | 2 +- references/docgen/cluster.go | 43 +-- references/docgen/cluster_test.go | 12 +- references/docgen/console.go | 13 +- references/docgen/convert.go | 12 +- references/docgen/markdown.go | 27 +- references/docgen/markdown_test.go | 6 +- references/docgen/parser.go | 39 +-- references/docgen/parser_test.go | 6 +- .../definitions/internal/trait/gateway.cue | 6 +- .../collect-service-endpoints.cue | 4 +- .../internal/workflowstep/depends-on-app.cue | 6 +- .../internal/workflowstep/export-data.cue | 6 +- .../internal/workflowstep/export-service.cue | 6 +- .../internal/workflowstep/webhook.cue | 14 +- 202 files changed, 3150 insertions(+), 3845 deletions(-) delete mode 100644 pkg/config/provider/provider.go rename pkg/{cue/script => schema}/schema.go (65%) rename pkg/{cue/script => schema}/schema_test.go (99%) rename pkg/{cue/script => schema}/testdata/arrayWithoutItemsSchema.json (100%) rename pkg/{cue/script => schema}/testdata/arrayWithoutItemsSchemaFixed.json (100%) rename pkg/{cue/script => schema}/testdata/shortTagSchema.json (100%) rename pkg/{cue/script => schema}/testdata/shortTagSchemaFixed.json (100%) rename pkg/{cue/script => schema}/testdata/webservice.json (100%) rename pkg/{cue/script => schema}/testdata/webserviceFixed.json (100%) delete mode 100644 pkg/stdlib/op.cue delete mode 100644 pkg/stdlib/packages.go delete mode 100644 pkg/stdlib/packages_test.go delete mode 100644 pkg/stdlib/pkgs/oam.cue delete mode 100644 pkg/stdlib/ql.cue rename pkg/{velaql/providers/query => utils}/types/health_status.go (100%) rename pkg/{velaql/providers/query/types/type.go => utils/types/ql_type.go} (81%) delete mode 100644 pkg/velaql/context.go delete mode 100644 pkg/velaql/providers/query/utils_test.go create mode 100644 pkg/workflow/providers/compiler.go create mode 100644 pkg/workflow/providers/legacy/config/config.cue create mode 100644 pkg/workflow/providers/legacy/config/config.go rename pkg/{config/provider/provider_test.go => workflow/providers/legacy/config/config_test.go} (67%) create mode 100644 pkg/workflow/providers/legacy/legacy.go rename pkg/workflow/providers/{ => legacy}/multicluster/deploy.go (82%) rename pkg/workflow/providers/{ => legacy}/multicluster/deploy_test.go (91%) rename pkg/{stdlib/pkgs => workflow/providers/legacy/multicluster}/multicluster.cue (87%) create mode 100644 pkg/workflow/providers/legacy/multicluster/multicluster.go rename pkg/workflow/providers/{ => legacy}/multicluster/multicluster_test.go (57%) create mode 100644 pkg/workflow/providers/legacy/oam/apply.go create mode 100644 pkg/workflow/providers/legacy/oam/apply_test.go create mode 100644 pkg/workflow/providers/legacy/oam/oam.cue rename pkg/{velaql/providers => workflow/providers/legacy}/query/collector.go (97%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/endpoint.go (93%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/endpoint_test.go (92%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/handler.go (50%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/handler_test.go (76%) rename pkg/{stdlib/pkgs/query.cue => workflow/providers/legacy/query/ql.cue} (95%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/suite_test.go (97%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/gateway/crds/gateway.networking.k8s.io_gateways.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/gateway/crds/gateway.networking.k8s.io_httproutes.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/gateway/gateway-tls.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/gateway/gateway.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/gateway/http-route.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/gateway/https-route.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/helm-release-crd.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/testdata/machinelearning.seldon.io_seldondeployments.yaml (100%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/tree.go (99%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/tree_test.go (97%) rename pkg/{velaql/providers => workflow/providers/legacy}/query/utils.go (73%) create mode 100644 pkg/workflow/providers/legacy/query/utils_test.go rename pkg/{stdlib/pkgs => workflow/providers/legacy/terraform}/terraform.cue (81%) create mode 100644 pkg/workflow/providers/legacy/terraform/terraform.go rename pkg/workflow/providers/{ => legacy}/terraform/terraform_test.go (56%) create mode 100644 pkg/workflow/providers/legacy/types/types.go delete mode 100644 pkg/workflow/providers/multicluster/multicluster.go delete mode 100644 pkg/workflow/providers/oam/apply.go delete mode 100644 pkg/workflow/providers/oam/apply_test.go delete mode 100644 pkg/workflow/providers/terraform/terraform.go delete mode 100644 pkg/workflow/providers/time/date.go delete mode 100644 pkg/workflow/providers/time/date_test.go diff --git a/.gitignore b/.gitignore index fcd7874e1..893138b46 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ _tmp/ references/cmd/cli/fake/source.go references/cmd/cli/fake/chart_source.go +references/vela-sdk-gen/* charts/vela-core/crds/_.yaml .test_vela tmp/ diff --git a/Makefile b/Makefile index 128c48103..c95a954b4 100644 --- a/Makefile +++ b/Makefile @@ -41,9 +41,8 @@ fmt: goimports installcue $(CUE) fmt ./vela-templates/definitions/internal/* $(CUE) fmt ./vela-templates/definitions/deprecated/* $(CUE) fmt ./vela-templates/definitions/registry/* - $(CUE) fmt ./pkg/stdlib/pkgs/* - $(CUE) fmt ./pkg/stdlib/op.cue $(CUE) fmt ./pkg/workflow/template/static/* + $(CUE) fmt ./pkg/workflow/providers/legacy/... ## sdk_fmt: Run go fmt against code sdk_fmt: diff --git a/apis/core.oam.dev/v1beta1/resourcetracker_types_test.go b/apis/core.oam.dev/v1beta1/resourcetracker_types_test.go index 75954b2cc..177067cec 100644 --- a/apis/core.oam.dev/v1beta1/resourcetracker_types_test.go +++ b/apis/core.oam.dev/v1beta1/resourcetracker_types_test.go @@ -203,7 +203,7 @@ func TestResourceTrackerCompression(t *testing.T) { "../../../charts/vela-core/crds/core.oam.dev_componentdefinitions.yaml", "../../../charts/vela-core/templates/kubevela-controller.yaml", "../../../charts/vela-core/README.md", - "../../../pkg/velaql/providers/query/testdata/machinelearning.seldon.io_seldondeployments.yaml", + "../../../pkg/workflow/providers/legacy/query/testdata/machinelearning.seldon.io_seldondeployments.yaml", } for _, p := range paths { b, err := os.ReadFile(p) diff --git a/charts/vela-core/templates/defwithtemplate/collect-service-endpoints.yaml b/charts/vela-core/templates/defwithtemplate/collect-service-endpoints.yaml index 9c7fe22bf..bc0028161 100644 --- a/charts/vela-core/templates/defwithtemplate/collect-service-endpoints.yaml +++ b/charts/vela-core/templates/defwithtemplate/collect-service-endpoints.yaml @@ -34,7 +34,7 @@ spec: } } } - } @step(1) + } outputs: { eps_port_name_filtered: *[] | [...] @@ -42,7 +42,7 @@ spec: eps_port_name_filtered: collect.list } if parameter.portName != _|_ { - eps_port_name_filtered: [ for ep in collect.list if parameter.portName == ep.endpoint.portName {ep}] + eps_port_name_filtered: [for ep in collect.list if parameter.portName == ep.endpoint.portName {ep}] } eps_port_filtered: *[] | [...] @@ -50,12 +50,12 @@ spec: eps_port_filtered: eps_port_name_filtered } if parameter.port != _|_ { - eps_port_filtered: [ for ep in eps_port_name_filtered if parameter.port == ep.endpoint.port {ep}] + eps_port_filtered: [for ep in eps_port_name_filtered if parameter.port == ep.endpoint.port {ep}] } - eps: eps_port_filtered + eps: eps_port_filtered endpoints: *[] | [...] if parameter.outer != _|_ { - tmps: [ for ep in eps { + tmps: [for ep in eps { ep if ep.endpoint.inner == _|_ { outer: true @@ -64,7 +64,7 @@ spec: outer: !ep.endpoint.inner } }] - endpoints: [ for ep in tmps if (!parameter.outer || ep.outer) {ep}] + endpoints: [for ep in tmps if (!parameter.outer || ep.outer) {ep}] } if parameter.outer == _|_ { endpoints: eps_port_filtered @@ -73,7 +73,7 @@ spec: wait: op.#ConditionalWait & { continue: len(outputs.endpoints) > 0 - } @step(2) + } value: { if len(outputs.endpoints) > 0 { diff --git a/charts/vela-core/templates/defwithtemplate/command.yaml b/charts/vela-core/templates/defwithtemplate/command.yaml index 0de99fe54..4b97a22dd 100644 --- a/charts/vela-core/templates/defwithtemplate/command.yaml +++ b/charts/vela-core/templates/defwithtemplate/command.yaml @@ -32,7 +32,7 @@ spec: _params: #PatchParams name: _params.containerName _baseContainers: context.output.spec.template.spec.containers - _matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}] + _matchContainers_: [for _container_ in _baseContainers if _container_.name == name {_container_}] _baseContainer: *_|_ | {...} if len(_matchContainers_) == 0 { err: "container \(name) not found" @@ -73,7 +73,7 @@ spec: } // +patchStrategy=replace - args: [ for a in _args if _delArgs[a] == _|_ {a}] + [ for a in _addArgs if _delArgs[a] == _|_ && _argsMap[a] == _|_ {a}] + args: [for a in _args if _delArgs[a] == _|_ {a}] + [for a in _addArgs if _delArgs[a] == _|_ && _argsMap[a] == _|_ {a}] } } // +patchStrategy=open @@ -97,7 +97,7 @@ spec: } if parameter.containers != _|_ { // +patchKey=name - containers: [ for c in parameter.containers { + containers: [for c in parameter.containers { if c.containerName == "" { err: "container name must be set for containers" } @@ -113,5 +113,5 @@ spec: containers: [...#PatchParams] }) - errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] + errs: [for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] diff --git a/charts/vela-core/templates/defwithtemplate/container-image.yaml b/charts/vela-core/templates/defwithtemplate/container-image.yaml index 0426893c1..ac3f9ef44 100644 --- a/charts/vela-core/templates/defwithtemplate/container-image.yaml +++ b/charts/vela-core/templates/defwithtemplate/container-image.yaml @@ -29,7 +29,7 @@ spec: _params: #PatchParams name: _params.containerName _baseContainers: context.output.spec.template.spec.containers - _matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}] + _matchContainers_: [for _container_ in _baseContainers if _container_.name == name {_container_}] _baseContainer: *_|_ | {...} if len(_matchContainers_) == 0 { err: "container \(name) not found" @@ -62,7 +62,7 @@ spec: } if parameter.containers != _|_ { // +patchKey=name - containers: [ for c in parameter.containers { + containers: [for c in parameter.containers { if c.containerName == "" { err: "containerName must be set for containers" } @@ -78,5 +78,5 @@ spec: containers: [...#PatchParams] }) - errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] + errs: [for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] diff --git a/charts/vela-core/templates/defwithtemplate/container-ports.yaml b/charts/vela-core/templates/defwithtemplate/container-ports.yaml index a7ec614ef..f26ab3402 100644 --- a/charts/vela-core/templates/defwithtemplate/container-ports.yaml +++ b/charts/vela-core/templates/defwithtemplate/container-ports.yaml @@ -42,7 +42,7 @@ spec: _params: #PatchParams name: _params.containerName _baseContainers: context.output.spec.template.spec.containers - _matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}] + _matchContainers_: [for _container_ in _baseContainers if _container_.name == name {_container_}] _baseContainer: *_|_ | {...} if len(_matchContainers_) == 0 { err: "container \(name) not found" @@ -52,7 +52,7 @@ spec: _basePorts: _baseContainer.ports if _basePorts == _|_ { // +patchStrategy=replace - ports: [ for port in _params.ports { + ports: [for port in _params.ports { containerPort: port.containerPort protocol: port.protocol if port.hostPort != _|_ { @@ -67,7 +67,7 @@ spec: _basePortsMap: {for _basePort in _basePorts {(strings.ToLower(_basePort.protocol) + strconv.FormatInt(_basePort.containerPort, 10)): _basePort}} _portsMap: {for port in _params.ports {(strings.ToLower(port.protocol) + strconv.FormatInt(port.containerPort, 10)): port}} // +patchStrategy=replace - ports: [ for portVar in _basePorts { + ports: [for portVar in _basePorts { containerPort: portVar.containerPort protocol: portVar.protocol name: portVar.name @@ -80,7 +80,7 @@ spec: hostIP: _portsMap[_uniqueKey].hostIP } } - }] + [ for port in _params.ports if _basePortsMap[strings.ToLower(port.protocol)+strconv.FormatInt(port.containerPort, 10)] == _|_ { + }] + [for port in _params.ports if _basePortsMap[strings.ToLower(port.protocol)+strconv.FormatInt(port.containerPort, 10)] == _|_ { if port.containerPort != _|_ { containerPort: port.containerPort } @@ -115,7 +115,7 @@ spec: } if parameter.containers != _|_ { // +patchKey=name - containers: [ for c in parameter.containers { + containers: [for c in parameter.containers { if c.containerName == "" { err: "container name must be set for containers" } @@ -131,5 +131,5 @@ spec: containers: [...#PatchParams] }) - errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] + errs: [for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] diff --git a/charts/vela-core/templates/defwithtemplate/cron-task.yaml b/charts/vela-core/templates/defwithtemplate/cron-task.yaml index 08b110154..9cdcc23bb 100644 --- a/charts/vela-core/templates/defwithtemplate/cron-task.yaml +++ b/charts/vela-core/templates/defwithtemplate/cron-task.yaml @@ -25,7 +25,7 @@ spec: ] | [] configMap: *[ - for v in parameter.volumeMounts.configMap { + for v in parameter.volumeMounts.configMap { { mountPath: v.mountPath if v.subPath != _|_ { @@ -49,7 +49,7 @@ spec: ] | [] emptyDir: *[ - for v in parameter.volumeMounts.emptyDir { + for v in parameter.volumeMounts.emptyDir { { mountPath: v.mountPath if v.subPath != _|_ { @@ -61,7 +61,7 @@ spec: ] | [] hostPath: *[ - for v in parameter.volumeMounts.hostPath { + for v in parameter.volumeMounts.hostPath { { mountPath: v.mountPath if v.subPath != _|_ { @@ -83,7 +83,7 @@ spec: ] | [] configMap: *[ - for v in parameter.volumeMounts.configMap { + for v in parameter.volumeMounts.configMap { { name: v.name configMap: { @@ -113,7 +113,7 @@ spec: ] | [] emptyDir: *[ - for v in parameter.volumeMounts.emptyDir { + for v in parameter.volumeMounts.emptyDir { { name: v.name emptyDir: medium: v.medium @@ -122,7 +122,7 @@ spec: ] | [] hostPath: *[ - for v in parameter.volumeMounts.hostPath { + for v in parameter.volumeMounts.hostPath { { name: v.name hostPath: path: v.path @@ -223,7 +223,7 @@ spec: } } if parameter["volumes"] != _|_ if parameter["volumeMounts"] == _|_ { - volumeMounts: [ for v in parameter.volumes { + volumeMounts: [for v in parameter.volumes { { mountPath: v.mountPath name: v.name @@ -234,7 +234,7 @@ spec: } }] if parameter["volumes"] != _|_ if parameter["volumeMounts"] == _|_ { - volumes: [ for v in parameter.volumes { + volumes: [for v in parameter.volumes { { name: v.name if v.type == "pvc" { @@ -267,13 +267,13 @@ spec: volumes: deDupVolumesArray } if parameter["imagePullSecrets"] != _|_ { - imagePullSecrets: [ for v in parameter.imagePullSecrets { + imagePullSecrets: [for v in parameter.imagePullSecrets { name: v }, ] } if parameter.hostAliases != _|_ { - hostAliases: [ for v in parameter.hostAliases { + hostAliases: [for v in parameter.hostAliases { ip: v.ip hostnames: v.hostnames }, diff --git a/charts/vela-core/templates/defwithtemplate/daemon.yaml b/charts/vela-core/templates/defwithtemplate/daemon.yaml index 85c685cf3..75cb38aa5 100644 --- a/charts/vela-core/templates/defwithtemplate/daemon.yaml +++ b/charts/vela-core/templates/defwithtemplate/daemon.yaml @@ -162,7 +162,7 @@ spec: }] } if parameter["ports"] != _|_ { - ports: [ for v in parameter.ports { + ports: [for v in parameter.ports { { containerPort: v.port protocol: v.protocol @@ -206,7 +206,7 @@ spec: } if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ { - volumeMounts: [ for v in parameter.volumes { + volumeMounts: [for v in parameter.volumes { { mountPath: v.mountPath name: v.name @@ -233,14 +233,14 @@ spec: } if parameter["imagePullSecrets"] != _|_ { - imagePullSecrets: [ for v in parameter.imagePullSecrets { + imagePullSecrets: [for v in parameter.imagePullSecrets { name: v }, ] } if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ { - volumes: [ for v in parameter.volumes { + volumes: [for v in parameter.volumes { { name: v.name if v.type == "pvc" { diff --git a/charts/vela-core/templates/defwithtemplate/depends-on-app.yaml b/charts/vela-core/templates/defwithtemplate/depends-on-app.yaml index f02a539dc..cec903751 100644 --- a/charts/vela-core/templates/defwithtemplate/depends-on-app.yaml +++ b/charts/vela-core/templates/defwithtemplate/depends-on-app.yaml @@ -38,14 +38,14 @@ spec: namespace: parameter.namespace } } - } @step(1) + } template: configMap.value.data["application"] - apply: op.#Apply & { + apply: op.#Apply & { value: yaml.Unmarshal(template) - } @step(2) + } wait: op.#ConditionalWait & { continue: apply.value.status.status == "running" - } @step(3) + } } if dependsOn.err == _|_ { diff --git a/charts/vela-core/templates/defwithtemplate/env.yaml b/charts/vela-core/templates/defwithtemplate/env.yaml index 6cf2a696c..8f51afad7 100644 --- a/charts/vela-core/templates/defwithtemplate/env.yaml +++ b/charts/vela-core/templates/defwithtemplate/env.yaml @@ -31,7 +31,7 @@ spec: name: _params.containerName _delKeys: {for k in _params.unset {(k): ""}} _baseContainers: context.output.spec.template.spec.containers - _matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}] + _matchContainers_: [for _container_ in _baseContainers if _container_.name == name {_container_}] _baseContainer: *_|_ | {...} if len(_matchContainers_) == 0 { err: "container \(name) not found" @@ -41,7 +41,7 @@ spec: _baseEnv: _baseContainer.env if _baseEnv == _|_ { // +patchStrategy=replace - env: [ for k, v in _params.env if _delKeys[k] == _|_ { + env: [for k, v in _params.env if _delKeys[k] == _|_ { name: k value: v }] @@ -49,7 +49,7 @@ spec: if _baseEnv != _|_ { _baseEnvMap: {for envVar in _baseEnv {(envVar.name): envVar}} // +patchStrategy=replace - env: [ for envVar in _baseEnv if _delKeys[envVar.name] == _|_ && !_params.replace { + env: [for envVar in _baseEnv if _delKeys[envVar.name] == _|_ && !_params.replace { name: envVar.name if _params.env[envVar.name] != _|_ { value: _params.env[envVar.name] @@ -62,7 +62,7 @@ spec: valueFrom: envVar.valueFrom } } - }] + [ for k, v in _params.env if _delKeys[k] == _|_ && (_params.replace || _baseEnvMap[k] == _|_) { + }] + [for k, v in _params.env if _delKeys[k] == _|_ && (_params.replace || _baseEnvMap[k] == _|_) { name: k value: v }] @@ -88,7 +88,7 @@ spec: } if parameter.containers != _|_ { // +patchKey=name - containers: [ for c in parameter.containers { + containers: [for c in parameter.containers { if c.containerName == "" { err: "containerName must be set for containers" } @@ -104,5 +104,5 @@ spec: containers: [...#PatchParams] }) - errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] + errs: [for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] diff --git a/charts/vela-core/templates/defwithtemplate/export-data.yaml b/charts/vela-core/templates/defwithtemplate/export-data.yaml index d3dc27120..6b7478264 100644 --- a/charts/vela-core/templates/defwithtemplate/export-data.yaml +++ b/charts/vela-core/templates/defwithtemplate/export-data.yaml @@ -37,14 +37,14 @@ spec: if parameter.kind == "Secret" { stringData: parameter.data } - } @step(1) + } getPlacements: op.#GetPlacementsFromTopologyPolicies & { policies: *[] | [...string] if parameter.topology != _|_ { policies: [parameter.topology] } - } @step(2) + } apply: op.#Steps & { for p in getPlacements.placements { @@ -53,7 +53,7 @@ spec: cluster: p.cluster } } - } @step(3) + } parameter: { // +usage=Specify the name of the export destination diff --git a/charts/vela-core/templates/defwithtemplate/export-service.yaml b/charts/vela-core/templates/defwithtemplate/export-service.yaml index c361888af..bdc08bba6 100644 --- a/charts/vela-core/templates/defwithtemplate/export-service.yaml +++ b/charts/vela-core/templates/defwithtemplate/export-service.yaml @@ -48,14 +48,14 @@ spec: addresses: [{ip: parameter.ip}] ports: [{port: parameter.targetPort}] }] - }] @step(1) + }] getPlacements: op.#GetPlacementsFromTopologyPolicies & { policies: *[] | [...string] if parameter.topology != _|_ { policies: [parameter.topology] } - } @step(2) + } apply: op.#Steps & { for p in getPlacements.placements { @@ -66,7 +66,7 @@ spec: } } } - } @step(3) + } parameter: { // +usage=Specify the name of the export destination diff --git a/charts/vela-core/templates/defwithtemplate/expose.yaml b/charts/vela-core/templates/defwithtemplate/expose.yaml index 840001a07..81033a13f 100644 --- a/charts/vela-core/templates/defwithtemplate/expose.yaml +++ b/charts/vela-core/templates/defwithtemplate/expose.yaml @@ -44,7 +44,7 @@ spec: ] } if parameter["ports"] != _|_ { - ports: [ for v in parameter.ports { + ports: [for v in parameter.ports { port: v.port targetPort: v.port if v.name != _|_ { diff --git a/charts/vela-core/templates/defwithtemplate/gateway.yaml b/charts/vela-core/templates/defwithtemplate/gateway.yaml index 16716c0f6..d8370b484 100644 --- a/charts/vela-core/templates/defwithtemplate/gateway.yaml +++ b/charts/vela-core/templates/defwithtemplate/gateway.yaml @@ -161,11 +161,11 @@ spec: } let ingressMetaName = context.name + nameSuffix let ig = [for i in context.outputs if (i.kind == "Ingress") && (i.metadata.name == ingressMetaName) {i}][0] - igs: *null | string + igs: *{} | {} if ig != _|_ if ig.status != _|_ if ig.status.loadbalancer != _|_ { igs: ig.status.loadbalancer.ingress[0] } - igr: *null | string + igr: *{} | {} if ig != _|_ if ig.spec != _|_ { igr: ig.spec.rules[0] } @@ -185,7 +185,7 @@ spec: if igr.host != _|_ { message: "Visiting URL: " + igr.host + "\n" } - if igs.host == _|_ { + if igr.host == _|_ { message: "Host not specified, visit the cluster or load balancer in front of the cluster\n" } } diff --git a/charts/vela-core/templates/defwithtemplate/generate-jdbc-connection.yaml b/charts/vela-core/templates/defwithtemplate/generate-jdbc-connection.yaml index cd9551b4f..ab32e5308 100644 --- a/charts/vela-core/templates/defwithtemplate/generate-jdbc-connection.yaml +++ b/charts/vela-core/templates/defwithtemplate/generate-jdbc-connection.yaml @@ -29,14 +29,14 @@ spec: } } } - dbHost: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_HOST"])} - dbPort: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PORT"])} - dbName: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_NAME"])} + dbHost: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_HOST"])} + dbPort: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PORT"])} + dbName: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_NAME"])} username: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_USER"])} password: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PASSWORD"])} env: [ - {name: "url", value: "jdbc://" + dbHost.str + ":" + dbPort.str + "/" + dbName.str + "?characterEncoding=utf8&useSSL=false"}, + {name: "url", value: "jdbc://" + dbHost.str + ":" + dbPort.str + "/" + dbName.str + "?characterEncoding=utf8&useSSL=false"}, {name: "username", value: username.str}, {name: "password", value: password.str}, ] diff --git a/charts/vela-core/templates/defwithtemplate/nocalhost.yaml b/charts/vela-core/templates/defwithtemplate/nocalhost.yaml index cef31b7cc..1624fd669 100644 --- a/charts/vela-core/templates/defwithtemplate/nocalhost.yaml +++ b/charts/vela-core/templates/defwithtemplate/nocalhost.yaml @@ -42,7 +42,7 @@ spec: patch: metadata: annotations: { "dev.nocalhost/application-name": context.appName "dev.nocalhost/application-namespace": context.namespace - "dev.nocalhost": json.Marshal({ + "dev.nocalhost": json.Marshal({ name: context.name serviceType: parameter.serviceType containers: [ @@ -126,14 +126,14 @@ spec: workDir: *"/home/nocalhost-dev" | string storageClass?: string command: { - run: *["sh", "run.sh"] | [...string] + run: *["sh", "run.sh"] | [...string] debug: *["sh", "debug.sh"] | [...string] } debug?: remoteDebugPort?: int hotReload: *true | bool sync: { - type: *"send" | string - filePattern: *["./"] | [...string] + type: *"send" | string + filePattern: *["./"] | [...string] ignoreFilePattern: *[".git", ".vscode", ".idea", ".gradle", "build"] | [...string] } env?: [...{ diff --git a/charts/vela-core/templates/defwithtemplate/notification.yaml b/charts/vela-core/templates/defwithtemplate/notification.yaml index 9e70c1b51..a94f77e36 100644 --- a/charts/vela-core/templates/defwithtemplate/notification.yaml +++ b/charts/vela-core/templates/defwithtemplate/notification.yaml @@ -69,7 +69,7 @@ spec: picUrl?: string } - link?: #link + link?: #link markdown?: close({ text: string title: string @@ -230,7 +230,7 @@ spec: } stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.dingding.url.secretRef.key])} - ding2: op.#DingTalk & { + ding2: op.#DingTalk & { message: parameter.dingding.message dingUrl: stringValue.str } @@ -259,7 +259,7 @@ spec: } stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key])} - lark2: op.#Lark & { + lark2: op.#Lark & { message: parameter.lark.message larkUrl: stringValue.str } @@ -288,7 +288,7 @@ spec: } stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.slack.url.secretRef.key])} - slack2: op.#Slack & { + slack2: op.#Slack & { message: parameter.slack.message slackUrl: stringValue.str } @@ -327,7 +327,7 @@ spec: } stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.email.from.password.secretRef.key])} - email2: op.#SendEmail & { + email2: op.#SendEmail & { from: { address: parameter.email.from.address if parameter.email.from.alias != _|_ { diff --git a/charts/vela-core/templates/defwithtemplate/service-account.yaml b/charts/vela-core/templates/defwithtemplate/service-account.yaml index 5ccc5adec..c2548e6fc 100644 --- a/charts/vela-core/templates/defwithtemplate/service-account.yaml +++ b/charts/vela-core/templates/defwithtemplate/service-account.yaml @@ -42,8 +42,8 @@ spec: // +patchStrategy=retainKeys patch: spec: template: spec: serviceAccountName: parameter.name - _clusterPrivileges: [ if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "cluster" {p}] - _namespacePrivileges: [ if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "namespace" {p}] + _clusterPrivileges: [if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "cluster" {p}] + _namespacePrivileges: [if parameter.privileges != _|_ for p in parameter.privileges if p.scope == "namespace" {p}] outputs: { if parameter.create { "service-account": { @@ -58,7 +58,7 @@ spec: apiVersion: "rbac.authorization.k8s.io/v1" kind: "ClusterRole" metadata: name: "\(context.namespace):\(parameter.name)" - rules: [ for p in _clusterPrivileges { + rules: [for p in _clusterPrivileges { verbs: p.verbs if p.apiGroups != _|_ { apiGroups: p.apiGroups @@ -95,7 +95,7 @@ spec: apiVersion: "rbac.authorization.k8s.io/v1" kind: "Role" metadata: name: parameter.name - rules: [ for p in _namespacePrivileges { + rules: [for p in _namespacePrivileges { verbs: p.verbs if p.apiGroups != _|_ { apiGroups: p.apiGroups diff --git a/charts/vela-core/templates/defwithtemplate/sidecar.yaml b/charts/vela-core/templates/defwithtemplate/sidecar.yaml index 0fc0f083b..316f21b73 100644 --- a/charts/vela-core/templates/defwithtemplate/sidecar.yaml +++ b/charts/vela-core/templates/defwithtemplate/sidecar.yaml @@ -32,7 +32,7 @@ spec: env: parameter.env } if parameter["volumes"] != _|_ { - volumeMounts: [ for v in parameter.volumes { + volumeMounts: [for v in parameter.volumes { { mountPath: v.path name: v.name diff --git a/charts/vela-core/templates/defwithtemplate/startup-probe.yaml b/charts/vela-core/templates/defwithtemplate/startup-probe.yaml index 64fd4772b..0aafb72ff 100644 --- a/charts/vela-core/templates/defwithtemplate/startup-probe.yaml +++ b/charts/vela-core/templates/defwithtemplate/startup-probe.yaml @@ -74,7 +74,7 @@ spec: _params: #StartupProbeParams name: _params.containerName _baseContainers: context.output.spec.template.spec.containers - _matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}] + _matchContainers_: [for _container_ in _baseContainers if _container_.name == name {_container_}] if len(_matchContainers_) == 0 { err: "container \(name) not found" } @@ -151,7 +151,7 @@ spec: } if parameter.probes != _|_ { // +patchKey=name - containers: [ for c in parameter.probes { + containers: [for c in parameter.probes { if c.name == "" { err: "containerName must be set when specifying startup probe for multiple containers" } @@ -167,5 +167,5 @@ spec: probes: [...#StartupProbeParams] }) - errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] + errs: [for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] diff --git a/charts/vela-core/templates/defwithtemplate/storage.yaml b/charts/vela-core/templates/defwithtemplate/storage.yaml index e68ac72b2..fa3691e37 100644 --- a/charts/vela-core/templates/defwithtemplate/storage.yaml +++ b/charts/vela-core/templates/defwithtemplate/storage.yaml @@ -149,7 +149,7 @@ spec: ] volumeDevicesList: *[ - for v in parameter.pvc if v.volumeMode == "Block" { + for v in parameter.pvc if v.volumeMode == "Block" { { name: "pvc-" + v.name devicePath: v.mountPath @@ -262,13 +262,13 @@ spec: parameter: { // +usage=Declare pvc type storage pvc?: [...{ - name: string - mountOnly: *false | bool - mountPath: string - subPath?: string - volumeMode: *"Filesystem" | string - volumeName?: string - accessModes: *["ReadWriteOnce"] | [...string] + name: string + mountOnly: *false | bool + mountPath: string + subPath?: string + volumeMode: *"Filesystem" | string + volumeName?: string + accessModes: *["ReadWriteOnce"] | [...string] storageClassName?: string resources?: { requests: storage: =~"^([1-9][0-9]{0,63})(E|P|T|G|M|K|Ei|Pi|Ti|Gi|Mi|Ki)$" diff --git a/charts/vela-core/templates/defwithtemplate/task.yaml b/charts/vela-core/templates/defwithtemplate/task.yaml index bc328c86e..9801a1e57 100644 --- a/charts/vela-core/templates/defwithtemplate/task.yaml +++ b/charts/vela-core/templates/defwithtemplate/task.yaml @@ -63,7 +63,7 @@ spec: } if parameter["volumes"] != _|_ { - volumeMounts: [ for v in parameter.volumes { + volumeMounts: [for v in parameter.volumes { { mountPath: v.mountPath name: v.name @@ -72,7 +72,7 @@ spec: }] if parameter["volumes"] != _|_ { - volumes: [ for v in parameter.volumes { + volumes: [for v in parameter.volumes { { name: v.name if v.type == "pvc" { @@ -103,7 +103,7 @@ spec: } if parameter["imagePullSecrets"] != _|_ { - imagePullSecrets: [ for v in parameter.imagePullSecrets { + imagePullSecrets: [for v in parameter.imagePullSecrets { name: v }, ] diff --git a/charts/vela-core/templates/defwithtemplate/webhook.yaml b/charts/vela-core/templates/defwithtemplate/webhook.yaml index f34677d46..04672ce1e 100644 --- a/charts/vela-core/templates/defwithtemplate/webhook.yaml +++ b/charts/vela-core/templates/defwithtemplate/webhook.yaml @@ -29,11 +29,11 @@ spec: namespace: context.namespace } } - } @step(1) - value: json.Marshal(read.value) @step(2) + } + value: json.Marshal(read.value) } if parameter.data != _|_ { - value: json.Marshal(parameter.data) @step(3) + value: json.Marshal(parameter.data) } } webhook: op.#Steps & { @@ -44,7 +44,7 @@ spec: body: data.value header: "Content-Type": "application/json" } - } @step(4) + } } if parameter.url.secretRef != _|_ && parameter.url.value == _|_ { read: op.#Read & { @@ -56,16 +56,16 @@ spec: namespace: context.namespace } } - } @step(5) + } - stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} @step(6) - http: op.#HTTPPost & { + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} + http: op.#HTTPPost & { url: stringValue.str request: { body: data.value header: "Content-Type": "application/json" } - } @step(7) + } } } diff --git a/charts/vela-core/templates/defwithtemplate/webservice.yaml b/charts/vela-core/templates/defwithtemplate/webservice.yaml index 26c8acde5..61a951303 100644 --- a/charts/vela-core/templates/defwithtemplate/webservice.yaml +++ b/charts/vela-core/templates/defwithtemplate/webservice.yaml @@ -163,7 +163,7 @@ spec: }] } if parameter["ports"] != _|_ { - ports: [ for v in parameter.ports { + ports: [for v in parameter.ports { { containerPort: { if v.containerPort != _|_ {v.containerPort} @@ -221,7 +221,7 @@ spec: } if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ { - volumeMounts: [ for v in parameter.volumes { + volumeMounts: [for v in parameter.volumes { { mountPath: v.mountPath name: v.name @@ -248,14 +248,14 @@ spec: } if parameter["imagePullSecrets"] != _|_ { - imagePullSecrets: [ for v in parameter.imagePullSecrets { + imagePullSecrets: [for v in parameter.imagePullSecrets { name: v }, ] } if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ { - volumes: [ for v in parameter.volumes { + volumes: [for v in parameter.volumes { { name: v.name if v.type == "pvc" { diff --git a/charts/vela-core/templates/defwithtemplate/worker.yaml b/charts/vela-core/templates/defwithtemplate/worker.yaml index 32b87eba1..ceb6ee403 100644 --- a/charts/vela-core/templates/defwithtemplate/worker.yaml +++ b/charts/vela-core/templates/defwithtemplate/worker.yaml @@ -171,7 +171,7 @@ spec: } if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ { - volumeMounts: [ for v in parameter.volumes { + volumeMounts: [for v in parameter.volumes { { mountPath: v.mountPath name: v.name @@ -193,14 +193,14 @@ spec: }] if parameter["imagePullSecrets"] != _|_ { - imagePullSecrets: [ for v in parameter.imagePullSecrets { + imagePullSecrets: [for v in parameter.imagePullSecrets { name: v }, ] } if parameter["volumes"] != _|_ && parameter["volumeMounts"] == _|_ { - volumes: [ for v in parameter.volumes { + volumes: [for v in parameter.volumes { { name: v.name if v.type == "pvc" { diff --git a/cmd/core/app/server.go b/cmd/core/app/server.go index 566ade772..9f2ee964f 100644 --- a/cmd/core/app/server.go +++ b/cmd/core/app/server.go @@ -29,7 +29,6 @@ import ( "github.com/kubevela/pkg/controller/sharding" "github.com/kubevela/pkg/meta" "github.com/kubevela/pkg/util/profiling" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/pkg/errors" "github.com/spf13/cobra" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -165,15 +164,6 @@ func run(ctx context.Context, s *options.CoreOptions) error { return err } - pd, err := packages.NewPackageDiscover(mgr.GetConfig()) - if err != nil { - klog.Error(err, "Failed to create CRD discovery for CUE package client") - if !packages.IsCUEParseErr(err) { - return err - } - } - s.ControllerArgs.PackageDiscover = pd - if !sharding.EnableSharding { if err = prepareRun(ctx, mgr, s); err != nil { return err diff --git a/e2e/plugin/plugin_test.go b/e2e/plugin/plugin_test.go index e92533587..fa6166e8b 100644 --- a/e2e/plugin/plugin_test.go +++ b/e2e/plugin/plugin_test.go @@ -143,7 +143,7 @@ var _ = Describe("Test Kubectl Plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(output).ShouldNot(ContainSubstring("addRevisionLabel")) }) - It("Test show webservice def with cue ignore annotation ", func() { + It("Test show webservice def with cue ignore annotation2 ", func() { tdName := "mywebservice" output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName)) Expect(err).NotTo(HaveOccurred()) diff --git a/go.mod b/go.mod index ba8b57ddd..b87118044 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/oam-dev/kubevela go 1.22 require ( - cuelang.org/go v0.5.0 + cuelang.org/go v0.9.2 github.com/AlecAivazis/survey/v2 v2.1.1 github.com/FogDong/uitable v0.0.5 github.com/Masterminds/semver/v3 v3.2.1 @@ -57,9 +57,8 @@ require ( github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.4.0 github.com/rivo/tview v0.0.0-20221128165837-db36428c92d9 - github.com/rogpeppe/go-internal v1.10.0 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/tidwall/gjson v1.14.4 @@ -68,7 +67,8 @@ require ( github.com/xlab/treeprint v1.2.0 go.uber.org/multierr v1.11.0 golang.org/x/crypto v0.25.0 - golang.org/x/oauth2 v0.12.0 + golang.org/x/mod v0.17.0 + golang.org/x/oauth2 v0.20.0 golang.org/x/sync v0.7.0 golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 @@ -98,6 +98,7 @@ require ( ) require ( + cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2 // indirect dario.cat/mergo v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect @@ -126,11 +127,11 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cloudflare/circl v1.3.7 // indirect - github.com/cockroachdb/apd/v2 v2.0.2 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/creack/pty v1.1.18 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/docker/cli v24.0.0+incompatible // indirect @@ -169,7 +170,6 @@ require ( github.com/gobuffalo/flect v0.3.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.0.1 // indirect @@ -180,9 +180,8 @@ require ( github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect @@ -224,11 +223,10 @@ require ( github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/openshift/library-go v0.0.0-20230327085348-8477ec72b725 // indirect github.com/perimeterx/marshmallow v1.1.4 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect @@ -236,9 +234,10 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect - github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b // indirect + github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rubenv/sql-migrate v1.3.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect @@ -271,11 +270,9 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/time v0.3.0 // indirect - google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.33.0 // indirect @@ -303,6 +300,7 @@ replace ( cloud.google.com/go => cloud.google.com/go v0.100.2 github.com/docker/cli => github.com/docker/cli v20.10.9+incompatible github.com/docker/docker => github.com/moby/moby v20.10.24+incompatible + github.com/kubevela/workflow => github.com/FogDong/workflow v0.0.0-20240723124017-5de159eb484c github.com/wercker/stern => github.com/oam-dev/stern v1.13.2 sigs.k8s.io/apiserver-network-proxy/konnectivity-client => sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.36 ) diff --git a/go.sum b/go.sum index 6fb0643be..f864adb3e 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,15 @@ cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cuelang.org/go v0.5.0 h1:D6N0UgTGJCOxFKU8RU+qYvavKNsVc/+ZobmifStVJzU= -cuelang.org/go v0.5.0/go.mod h1:okjJBHFQFer+a41sAe2SaGm1glWS8oEb6CmJvn5Zdws= +cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2 h1:BnG6pr9TTr6CYlrJznYUDj6V7xldD1W+1iXPum0wT/w= +cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2/go.mod h1:pK23AUVXuNzzTpfMCA06sxZGeVQ/75FdVtW249de9Uo= +cuelang.org/go v0.9.2 h1:pfNiry2PdRBr02G/aKm5k2vhzmqbAOoaB4WurmEbWvs= +cuelang.org/go v0.9.2/go.mod h1:qpAYsLOf7gTM1YdEg6cxh553uZ4q9ZDWlPbtZr9q1Wk= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -35,6 +36,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/FogDong/uitable v0.0.5 h1:1bJo/uvhGUC6i8JPHZCr8XKMHiDExE7mQkOCmDl0ryQ= github.com/FogDong/uitable v0.0.5/go.mod h1:1yEaP13SkkBUj3HvqKIUWnsb42XigyZbNle84mc5kLM= +github.com/FogDong/workflow v0.0.0-20240723124017-5de159eb484c h1:uj3GVjWUzGJ+aOuLrYo4/GTFHQhCjbyYrf4zzeFDGrM= +github.com/FogDong/workflow v0.0.0-20240723124017-5de159eb484c/go.mod h1:/tWZOtO+bp/EUQCJZjL8t3O5YDx5QXnKVllQkDTKKuw= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -171,8 +174,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= -github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= @@ -198,8 +201,9 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -365,6 +369,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-resty/resty/v2 v2.8.0 h1:J29d0JFWwSWrDCysnOK/YjsPMLQTx0TvgJEHVGvf2L8= github.com/go-resty/resty/v2 v2.8.0/go.mod h1:UCui0cMHekLrSntoMyofdSTaPpinlRHFtPpizuyDW2w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -475,8 +481,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= @@ -627,8 +634,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubevela/pkg v1.9.2 h1:K6pGoJikf6l8vlfehewmb36hyToX0KpUaQP4NVET/S8= github.com/kubevela/pkg v1.9.2/go.mod h1:u/MGuFXVSECxvIWdTKS4AQs1H+USfAMQgi30BUrOb04= -github.com/kubevela/workflow v0.6.0 h1:fYXviOYD5zqHs3J61tNbM4HZ85EcZlPm7Fyz8Q5o9Fk= -github.com/kubevela/workflow v0.6.0/go.mod h1:sjLcYqKHKeCQ+w77gijoNILwIShJKnCU+e3q7ETtZGI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= @@ -744,8 +749,6 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto= -github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -806,8 +809,8 @@ github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= -github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/openkruise/kruise-api v1.4.0 h1:MDDXQIYvaCh0ioIJSRniF4kCKby9JI3/ec6pZHHw/Ao= github.com/openkruise/kruise-api v1.4.0/go.mod h1:HyRlDV0MfW5Zm+3g36bx7u4CcWHcKBxL8g/c/2bjcd4= github.com/openkruise/rollouts v0.3.0 h1:T02r9BxHJ02MRkbc7C4F12qMGgrziZVjgmukwz6k60s= @@ -888,8 +891,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b h1:zd/2RNzIRkoGGMjE+YIsZ85CnDIz672JK2F3Zl4vux4= -github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b/go.mod h1:KjY0wibdYKc4DYkerHSbguaf3JeIPGhNJBp2BNiFH78= +github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 h1:sadMIsgmHpEOGbUs6VtHBXRR1OHevnj7hLx9ZcdNGW4= +github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= github.com/rivo/tview v0.0.0-20221128165837-db36428c92d9 h1:ccTgRxA37ypj3q8zB8G4k3xGPfBbIaMwrf3Yw6k50NY= github.com/rivo/tview v0.0.0-20221128165837-db36428c92d9/go.mod h1:YX2wUZOcJGOIycErz2s9KvDaP0jnWwRCirQMPLPpQ+Y= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -902,8 +905,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA= github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -947,8 +950,8 @@ github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSW github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1252,8 +1255,8 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1432,7 +1435,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= diff --git a/pkg/addon/addon.go b/pkg/addon/addon.go index 49aacff9f..01d9e59d8 100644 --- a/pkg/addon/addon.go +++ b/pkg/addon/addon.go @@ -32,10 +32,11 @@ import ( "sync" "time" + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "github.com/Masterminds/semver/v3" "github.com/google/go-github/v32/github" "github.com/imdario/mergo" - "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/pkg/errors" "github.com/xanzy/go-gitlab" "go.uber.org/multierr" @@ -63,11 +64,11 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/config" - "github.com/oam-dev/kubevela/pkg/cue/script" "github.com/oam-dev/kubevela/pkg/definition" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" + "github.com/oam-dev/kubevela/pkg/schema" "github.com/oam-dev/kubevela/pkg/utils" addonutil "github.com/oam-dev/kubevela/pkg/utils/addon" "github.com/oam-dev/kubevela/pkg/utils/apply" @@ -589,12 +590,11 @@ func unmarshalToContent(content []byte) (fileContent *github.RepositoryContent, } func genAddonAPISchema(addonRes *UIData) error { - cueScript := script.CUE(addonRes.Parameters) - schema, err := cueScript.ParsePropertiesToSchema() + s, err := schema.ParsePropertiesToSchema(context.Background(), addonRes.Parameters) if err != nil { return err } - addonRes.APISchema = schema + addonRes.APISchema = s return nil } @@ -700,12 +700,12 @@ func RenderDefinitions(addon *InstallPackage, config *rest.Config) ([]*unstructu } // RenderConfigTemplates render the config template -func RenderConfigTemplates(addon *InstallPackage, cli client.Client) ([]*unstructured.Unstructured, error) { +func RenderConfigTemplates(ctx context.Context, addon *InstallPackage, cli client.Client) ([]*unstructured.Unstructured, error) { templates := make([]*unstructured.Unstructured, 0) factory := config.NewConfigFactory(cli) for _, templateFile := range addon.ConfigTemplates { - t, err := factory.ParseTemplate("", []byte(templateFile.Data)) + t, err := factory.ParseTemplate(ctx, "", []byte(templateFile.Data)) if err != nil { return nil, err } @@ -738,7 +738,7 @@ func RenderDefinitionSchema(addon *InstallPackage) ([]*unstructured.Unstructured } // RenderViews will render views in addons. -func RenderViews(addon *InstallPackage) ([]*unstructured.Unstructured, error) { +func RenderViews(ctx context.Context, addon *InstallPackage) ([]*unstructured.Unstructured, error) { views := make([]*unstructured.Unstructured, 0) for _, view := range addon.YAMLViews { obj, err := renderObject(view) @@ -748,7 +748,7 @@ func RenderViews(addon *InstallPackage) ([]*unstructured.Unstructured, error) { views = append(views, obj) } for _, view := range addon.CUEViews { - obj, err := renderCUEView(view) + obj, err := renderCUEView(ctx, view) if err != nil { return nil, errors.Wrapf(err, "render velaQL view file %s", view.Name) } @@ -811,13 +811,13 @@ func renderSchemaConfigmap(elem ElementFile) (*unstructured.Unstructured, error) return util.Object2Unstructured(cm) } -func renderCUEView(elem ElementFile) (*unstructured.Unstructured, error) { +func renderCUEView(ctx context.Context, elem ElementFile) (*unstructured.Unstructured, error) { name, err := utils.GetFilenameFromLocalOrRemote(elem.Name) if err != nil { return nil, err } - cm, err := velaql.ParseViewIntoConfigMap(elem.Data, name) + cm, err := velaql.ParseViewIntoConfigMap(ctx, elem.Data, name) if err != nil { return nil, err } @@ -935,7 +935,7 @@ func NewAddonInstaller(ctx context.Context, cli client.Client, discoveryClient * return i } -func (h *Installer) enableAddon(addon *InstallPackage) (string, error) { +func (h *Installer) enableAddon(ctx context.Context, addon *InstallPackage) (string, error) { var err error h.addon = addon if !h.skipVersionValidate { @@ -946,10 +946,10 @@ func (h *Installer) enableAddon(addon *InstallPackage) (string, error) { } } - if err = h.installDependency(addon); err != nil { + if err = h.installDependency(ctx, addon); err != nil { return "", err } - if err = h.dispatchAddonResource(addon); err != nil { + if err = h.dispatchAddonResource(ctx, addon); err != nil { return "", err } // we shouldn't put continue func into dispatchAddonResource, because the re-apply app maybe already update app and @@ -1015,7 +1015,7 @@ func (h *Installer) getAddonMeta() (map[string]SourceMeta, error) { } // installDependency checks if addon's dependency and install it -func (h *Installer) installDependency(addon *InstallPackage) error { +func (h *Installer) installDependency(ctx context.Context, addon *InstallPackage) error { installedAddons, err := listInstalledAddons(h.ctx, h.cli) if err != nil { return err @@ -1069,7 +1069,7 @@ func (h *Installer) installDependency(addon *InstallPackage) error { // try to install the dependent addon from the same registry with the current addon depAddon, err = h.loadInstallPackage(dep.Name, depVersion) if err == nil { - additionalInfo, err := depHandler.enableAddon(depAddon) + additionalInfo, err := depHandler.enableAddon(ctx, depAddon) if err != nil { return errors.Wrap(err, "fail to dispatch dependent addon resource") } @@ -1096,7 +1096,7 @@ func (h *Installer) installDependency(addon *InstallPackage) error { return err } if err == nil { - additionalInfo, err := depHandler.enableAddon(depAddon) + additionalInfo, err := depHandler.enableAddon(ctx, depAddon) if err != nil { return errors.Wrap(err, "fail to dispatch dependent addon resource") } @@ -1491,7 +1491,7 @@ func (h *Installer) createOrUpdate(app *v1beta1.Application) (bool, error) { return true, nil } -func (h *Installer) dispatchAddonResource(addon *InstallPackage) error { +func (h *Installer) dispatchAddonResource(ctx context.Context, addon *InstallPackage) error { app, auxiliaryOutputs, err := RenderApp(h.ctx, addon, h.cli, h.args) if err != nil { return errors.Wrap(err, "render addon application fail") @@ -1521,7 +1521,7 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error { } // Step2: Render the config templates - templates, err := RenderConfigTemplates(addon, h.cli) + templates, err := RenderConfigTemplates(ctx, addon, h.cli) if err != nil { return errors.Wrap(err, "render the config template fail") } @@ -1533,7 +1533,7 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error { } // Step4: Render the velaQL views - views, err := RenderViews(addon) + views, err := RenderViews(ctx, addon) if err != nil { return errors.Wrap(err, "render addon views fail") } @@ -1625,15 +1625,15 @@ func (h *Installer) renderNotes(addon *InstallPackage) (string, error) { return "", err } notesFile := contextFile + "\n" + addon.Notes.Data - val, err := value.NewValue(notesFile, nil, "") - if err != nil { + val := cuecontext.New().CompileString(notesFile) + if val.Err() != nil { return "", errors.Wrap(err, "build values for NOTES.cue") } - notes, err := val.LookupValue(KeyWordNotes) - if err != nil { - return "", errors.Wrap(err, "look up notes in NOTES.cue") + notes := val.LookupPath(cue.ParsePath(KeyWordNotes)) + if !notes.Exists() { + return "", errors.New("notes not found") } - notesStr, err := notes.CueValue().String() + notesStr, err := notes.String() if err != nil { return "", errors.Wrap(err, "convert notes to string") } diff --git a/pkg/addon/addon_suite_test.go b/pkg/addon/addon_suite_test.go index 907999bf1..e66883015 100644 --- a/pkg/addon/addon_suite_test.go +++ b/pkg/addon/addon_suite_test.go @@ -441,7 +441,7 @@ var _ = Describe("func addon update ", func() { pkg := &InstallPackage{Meta: Meta{Name: "test-update", Version: "1.3.0"}} h := NewAddonInstaller(context.Background(), k8sClient, nil, nil, nil, &Registry{Name: "test"}, nil, nil, nil) h.addon = pkg - Expect(h.dispatchAddonResource(pkg)).Should(BeNil()) + Expect(h.dispatchAddonResource(context.Background(), pkg)).Should(BeNil()) Eventually(func() error { var err error @@ -504,7 +504,7 @@ var _ = Describe("test dry-run addon from local dir", func() { h := NewAddonInstaller(ctx, k8sClient, dc, apply.NewAPIApplicator(k8sClient), cfg, &Registry{Name: LocalAddonRegistryName}, map[string]interface{}{"example": "test-dry-run"}, nil, nil, DryRunAddon) - _, err = h.enableAddon(pkg) + _, err = h.enableAddon(context.Background(), pkg) Expect(err).Should(BeNil()) decoder := yaml3.NewDecoder(h.dryRunBuff) diff --git a/pkg/addon/addon_test.go b/pkg/addon/addon_test.go index 09ec44267..42cf74604 100644 --- a/pkg/addon/addon_test.go +++ b/pkg/addon/addon_test.go @@ -267,7 +267,7 @@ func TestRenderViews(t *testing.T) { DisableControlPlane: false, RuntimeCluster: false, } - views, err := RenderViews(&addonDeployToRuntime) + views, err := RenderViews(context.Background(), &addonDeployToRuntime) assert.NoError(t, err) assert.Equal(t, len(views), 2) @@ -1107,7 +1107,7 @@ func TestCheckEnableAddonErrorWhenMissMatch(t *testing.T) { version2.VelaVersion = "v1.3.0" i := InstallPackage{Meta: Meta{SystemRequirements: &SystemRequirements{VelaVersion: ">=1.4.0"}}} installer := &Installer{} - _, err := installer.enableAddon(&i) + _, err := installer.enableAddon(context.Background(), &i) assert.Equal(t, errors.As(err, &VersionUnMatchError{}), true) } diff --git a/pkg/addon/helper.go b/pkg/addon/helper.go index f34c300dd..34705d7e0 100644 --- a/pkg/addon/helper.go +++ b/pkg/addon/helper.go @@ -61,7 +61,7 @@ func EnableAddon(ctx context.Context, name string, version string, cli client.Cl if err := validateAddonPackage(pkg); err != nil { return "", errors.Wrap(err, fmt.Sprintf("failed to enable addon: %s", name)) } - return h.enableAddon(pkg) + return h.enableAddon(ctx, pkg) } // DisableAddon will disable addon from cluster. @@ -117,7 +117,7 @@ func EnableAddonByLocalDir(ctx context.Context, name string, dir string, cli cli if len(needEnableAddonNames) > 0 { return "", fmt.Errorf("you must first enable dependencies: %v", needEnableAddonNames) } - return h.enableAddon(pkg) + return h.enableAddon(ctx, pkg) } // GetAddonStatus is general func for cli and apiServer get addon status diff --git a/pkg/addon/render.go b/pkg/addon/render.go index a8ef22bbf..af51611b2 100644 --- a/pkg/addon/render.go +++ b/pkg/addon/render.go @@ -24,8 +24,10 @@ import ( "strconv" "strings" + "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" + "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/parser" "github.com/cue-exp/kubevelafix" "github.com/pkg/errors" @@ -36,7 +38,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" + + workflowerrors "github.com/kubevela/workflow/pkg/errors" common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" @@ -47,7 +50,6 @@ import ( "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" addonutil "github.com/oam-dev/kubevela/pkg/utils/addon" - verrors "github.com/oam-dev/kubevela/pkg/utils/errors" ) const ( @@ -105,19 +107,16 @@ func (a addonCueTemplateRender) toObject(cueTemplate string, path string, object if err != nil { return err } - v, err := value.NewValue(contextFile, nil, "") + v := cuecontext.New().CompileString(contextFile) + out, err := value.LookupValueByScript(v, cueTemplate) if err != nil { return err } - out, err := v.LookupByScript(cueTemplate) - if err != nil { - return err + outputContent := out.LookupPath(cue.ParsePath(path)) + if !outputContent.Exists() { + return workflowerrors.LookUpNotFoundErr(path) } - outputContent, err := out.LookupValue(path) - if err != nil { - return err - } - return outputContent.UnmarshalTo(object) + return value.UnmarshalTo(outputContent, object) } // renderApp will render Application from CUE files @@ -144,32 +143,29 @@ func (a addonCueTemplateRender) renderApp() (*v1beta1.Application, []*unstructur } // TODO(wonderflow): add package discover to support vela own packages if needed - v, err := newValueWithMainAndFiles(a.addon.AppCueTemplate.Data, files, nil, "") + v, err := newValueWithMainAndFiles(a.addon.AppCueTemplate.Data, files, "") if err != nil { return nil, nil, errors.Wrap(err, "load app template with CUE files") } - if v.Error() != nil { - return nil, nil, errors.Wrap(v.Error(), "load app template with CUE files") + if v.Err() != nil { + return nil, nil, errors.Wrap(v.Err(), "load app template with CUE files") } - outputContent, err := v.LookupValue(renderOutputCuePath) - if err != nil { - return nil, nil, errors.Wrap(err, "render app from output field from CUE") + outputContent := v.LookupPath(cue.ParsePath(renderOutputCuePath)) + if !outputContent.Exists() { + return nil, nil, errors.Wrap(workflowerrors.LookUpNotFoundErr(renderOutputCuePath), "render app from output field from CUE") } - err = outputContent.UnmarshalTo(&app) + err = value.UnmarshalTo(outputContent, &app) if err != nil { return nil, nil, errors.Wrap(err, "decode app from CUE") } - auxiliaryContent, err := v.LookupValue(renderAuxiliaryOutputsPath) - if err != nil { + auxiliaryContent := v.LookupPath(cue.ParsePath(renderAuxiliaryOutputsPath)) + if !auxiliaryContent.Exists() { // no outputs defined in app template, return normal data - if verrors.IsCuePathNotFound(err) { - return &app, res, nil - } - return nil, nil, errors.Wrap(err, "render app from output field from CUE") + return &app, res, nil } - err = auxiliaryContent.UnmarshalTo(&outputs) + err = value.UnmarshalTo(auxiliaryContent, &outputs) if err != nil { return nil, nil, errors.Wrap(err, "decode app from CUE") } @@ -184,49 +180,49 @@ func (a addonCueTemplateRender) renderApp() (*v1beta1.Application, []*unstructur } // newValueWithMainAndFiles new a value from main and appendix files -func newValueWithMainAndFiles(main string, slaveFiles []string, pd *packages.PackageDiscover, tagTempl string, opts ...func(*ast.File) error) (*value.Value, error) { +func newValueWithMainAndFiles(main string, slaveFiles []string, _ string, opts ...func(*ast.File) error) (cue.Value, error) { builder := &build.Instance{} mainFile, err := parser.ParseFile("main.cue", main, parser.ParseComments) mainFile = kubevelafix.Fix(mainFile).(*ast.File) if err != nil { - return nil, errors.Wrap(err, "parse main file") + return cue.Value{}, errors.Wrap(err, "parse main file") } if mainFile.PackageName() == "" { // add a default package main if not exist mainFile, err = parser.ParseFile("main.cue", defaultPackageHeader+main, parser.ParseComments) if err != nil { - return nil, errors.Wrap(err, "parse main file with added package main header") + return cue.Value{}, errors.Wrap(err, "parse main file with added package main header") } } for _, opt := range opts { if err := opt(mainFile); err != nil { - return nil, errors.Wrap(err, "run option func for main file") + return cue.Value{}, errors.Wrap(err, "run option func for main file") } } if err := builder.AddSyntax(mainFile); err != nil { - return nil, errors.Wrap(err, "add main file to CUE builder") + return cue.Value{}, errors.Wrap(err, "add main file to CUE builder") } for idx, sf := range slaveFiles { cueSF, err := parser.ParseFile("sf-"+strconv.Itoa(idx)+".cue", sf, parser.ParseComments) cueSF = kubevelafix.Fix(cueSF).(*ast.File) if err != nil { - return nil, errors.Wrap(err, "parse added file "+strconv.Itoa(idx)+" \n"+sf) + return cue.Value{}, errors.Wrap(err, "parse added file "+strconv.Itoa(idx)+" \n"+sf) } if cueSF.PackageName() != mainFile.PackageName() { continue } for _, opt := range opts { if err := opt(cueSF); err != nil { - return nil, errors.Wrap(err, "run option func for files") + return cue.Value{}, errors.Wrap(err, "run option func for files") } } if err := builder.AddSyntax(cueSF); err != nil { - return nil, errors.Wrap(err, "add slave files to CUE builder") + return cue.Value{}, errors.Wrap(err, "add slave files to CUE builder") } } - return value.NewValueWithInstance(builder, pd, tagTempl) + return cuecontext.New().BuildInstance(builder), nil } // generateAppFramework generate application from yaml defined by template.yaml or cue file from template.cue diff --git a/pkg/addon/suite_test.go b/pkg/addon/suite_test.go index da2928467..99fbd0e8f 100644 --- a/pkg/addon/suite_test.go +++ b/pkg/addon/suite_test.go @@ -39,8 +39,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" coreoam "github.com/oam-dev/kubevela/apis/core.oam.dev" - - "github.com/kubevela/workflow/pkg/cue/packages" // +kubebuilder:scaffold:imports ) @@ -48,7 +46,6 @@ var cfg *rest.Config var scheme *runtime.Scheme var k8sClient client.Client var testEnv *envtest.Environment -var pd *packages.PackageDiscover var testns string var dc *discovery.DiscoveryClient @@ -87,9 +84,6 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) Expect(dc).ShouldNot(BeNil()) - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(pd).ToNot(BeNil()) testns = "vela-system" Expect(k8sClient.Create(context.Background(), &v12.Namespace{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Namespace"}, ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/appfile/appfile.go b/pkg/appfile/appfile.go index 8c14ae446..1dec8334d 100644 --- a/pkg/appfile/appfile.go +++ b/pkg/appfile/appfile.go @@ -23,6 +23,7 @@ import ( "reflect" "strings" + "cuelang.org/go/cue" "github.com/crossplane/crossplane-runtime/pkg/fieldpath" "github.com/kubevela/pkg/util/slices" terraformapi "github.com/oam-dev/terraform-controller/api/v1beta2" @@ -85,7 +86,7 @@ type Component struct { Traits []*Trait FullTemplate *Template Ctx process.Context - Patch *value.Value + Patch *cue.Value engine definition.AbstractEngine SkipApplyWorkload bool } @@ -533,14 +534,14 @@ func baseGenerateComponent(pCtx process.Context, comp *Component, appName, ns st } if patcher := comp.Patch; patcher != nil { workload, auxiliaries := pCtx.Output() - if p, err := patcher.LookupValue("workload"); err == nil { - if err := workload.Unify(p.CueValue()); err != nil { + if p := patcher.LookupPath(cue.ParsePath("workload")); p.Exists() { + if err := workload.Unify(p); err != nil { return nil, errors.WithMessage(err, "patch workload") } } for _, aux := range auxiliaries { - if p, err := patcher.LookupByScript(fmt.Sprintf("traits[\"%s\"]", aux.Name)); err == nil && p.CueValue().Err() == nil { - if err := aux.Ins.Unify(p.CueValue()); err != nil { + if p, err := value.LookupValueByScript(*patcher, fmt.Sprintf("traits[\"%s\"]", aux.Name)); err == nil && p.Err() == nil { + if err := aux.Ins.Unify(p); err != nil { return nil, errors.WithMessagef(err, "patch outputs.%s", aux.Name) } } diff --git a/pkg/appfile/appfile_test.go b/pkg/appfile/appfile_test.go index fc782196b..521a5aa92 100644 --- a/pkg/appfile/appfile_test.go +++ b/pkg/appfile/appfile_test.go @@ -386,7 +386,7 @@ variable "password" { }, }, CapabilityCategory: oamtypes.TerraformCategory, - engine: definition.NewWorkloadAbstractEngine(compName, pd), + engine: definition.NewWorkloadAbstractEngine(compName), Params: map[string]interface{}{ "variable": map[string]interface{}{ "account_name": "oamtest", @@ -716,7 +716,7 @@ func TestBaseGenerateComponent(t *testing.T) { assert.NoError(t, err) tr := &Trait{ Name: traitName, - engine: definition.NewTraitAbstractEngine(traitName, nil), + engine: definition.NewTraitAbstractEngine(traitName), Template: `outputs:mytrait:{ if context.componentType == "stateless" { kind: "Deployment" @@ -759,7 +759,7 @@ var _ = Describe("Test use context.appLabels& context.appAnnotations in componen "image": "busybox", "cmd": []interface{}{"sleep", "1000"}, }, - engine: definition.NewWorkloadAbstractEngine("myweb", pd), + engine: definition.NewWorkloadAbstractEngine("myweb"), FullTemplate: &Template{ TemplateStr: ` output: { diff --git a/pkg/appfile/dryrun/diff.go b/pkg/appfile/dryrun/diff.go index d0c4df349..530c46356 100644 --- a/pkg/appfile/dryrun/diff.go +++ b/pkg/appfile/dryrun/diff.go @@ -30,7 +30,6 @@ import ( "sigs.k8s.io/yaml" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" @@ -41,9 +40,9 @@ import ( ) // NewLiveDiffOption creates a live-diff option -func NewLiveDiffOption(c client.Client, cfg *rest.Config, pd *packages.PackageDiscover, as []*unstructured.Unstructured) *LiveDiffOption { - parser := appfile.NewApplicationParser(c, pd) - return &LiveDiffOption{DryRun: NewDryRunOption(c, cfg, pd, as, false), Parser: parser} +func NewLiveDiffOption(c client.Client, cfg *rest.Config, as []*unstructured.Unstructured) *LiveDiffOption { + parser := appfile.NewApplicationParser(c) + return &LiveDiffOption{DryRun: NewDryRunOption(c, cfg, as, false), Parser: parser} } // ManifestKind enums the kind of OAM objects diff --git a/pkg/appfile/dryrun/diff_test.go b/pkg/appfile/dryrun/diff_test.go index be41077fc..2879d2160 100644 --- a/pkg/appfile/dryrun/diff_test.go +++ b/pkg/appfile/dryrun/diff_test.go @@ -153,8 +153,8 @@ var _ = Describe("Test Live-Diff", func() { It("Test renderless diff", func() { liveDiffOpt := LiveDiffOption{ - DryRun: NewDryRunOption(k8sClient, cfg, pd, nil, false), - Parser: appfile.NewApplicationParser(k8sClient, pd), + DryRun: NewDryRunOption(k8sClient, cfg, nil, false), + Parser: appfile.NewApplicationParser(k8sClient), } applyFile := func(filename string, ns string) { bs, err := os.ReadFile("./testdata/" + filename) diff --git a/pkg/appfile/dryrun/dryrun.go b/pkg/appfile/dryrun/dryrun.go index 5593a0d7b..4b59ad51b 100644 --- a/pkg/appfile/dryrun/dryrun.go +++ b/pkg/appfile/dryrun/dryrun.go @@ -35,8 +35,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" @@ -56,9 +54,9 @@ type DryRun interface { } // NewDryRunOption creates a dry-run option -func NewDryRunOption(c client.Client, cfg *rest.Config, pd *packages.PackageDiscover, as []*unstructured.Unstructured, serverSideDryRun bool) *Option { - parser := appfile.NewDryRunApplicationParser(c, pd, as) - return &Option{c, pd, parser, parser.GenerateAppFileFromApp, cfg, as, serverSideDryRun} +func NewDryRunOption(c client.Client, cfg *rest.Config, as []*unstructured.Unstructured, serverSideDryRun bool) *Option { + parser := appfile.NewDryRunApplicationParser(c, as) + return &Option{c, parser, parser.GenerateAppFileFromApp, cfg, as, serverSideDryRun} } // GenerateAppFileFunc generate the app file model from an application @@ -67,7 +65,6 @@ type GenerateAppFileFunc func(ctx context.Context, app *v1beta1.Application) (*a // Option contains options to execute dry-run type Option struct { Client client.Client - PackageDiscover *packages.PackageDiscover Parser *appfile.Parser GenerateAppFile GenerateAppFileFunc cfg *rest.Config @@ -227,7 +224,7 @@ func (d *Option) ExecuteDryRunWithPolicies(ctx context.Context, application *v1b app.Namespace = appNs.(string) } ctx = oamutil.SetNamespaceInCtx(ctx, app.Namespace) - parser := appfile.NewDryRunApplicationParser(d.Client, d.PackageDiscover, d.Auxiliaries) + parser := appfile.NewDryRunApplicationParser(d.Client, d.Auxiliaries) af, err := parser.GenerateAppFileFromApp(ctx, app) if err != nil { return err diff --git a/pkg/appfile/dryrun/suit_test.go b/pkg/appfile/dryrun/suit_test.go index 46e710915..cbf06f869 100644 --- a/pkg/appfile/dryrun/suit_test.go +++ b/pkg/appfile/dryrun/suit_test.go @@ -43,8 +43,6 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "github.com/kubevela/workflow/pkg/cue/packages" - coreoam "github.com/oam-dev/kubevela/apis/core.oam.dev" "github.com/oam-dev/kubevela/pkg/appfile" oamutil "github.com/oam-dev/kubevela/pkg/oam/util" @@ -54,7 +52,6 @@ var cfg *rest.Config var scheme *runtime.Scheme var k8sClient client.Client var testEnv *envtest.Environment -var pd *packages.PackageDiscover var dryrunOpt *Option var diffOpt *LiveDiffOption @@ -85,9 +82,6 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(pd).ToNot(BeNil()) By("Prepare capability definitions") myingressYAML := readDataFromFile("./testdata/td-myingress.yaml") @@ -113,8 +107,8 @@ var _ = BeforeSuite(func() { wfsd.SetNamespace(types.DefaultKubeVelaNS) Expect(k8sClient.Create(context.TODO(), &wfsd)).Should(BeNil()) - dryrunOpt = NewDryRunOption(k8sClient, cfg, pd, []*unstructured.Unstructured{cdMyWorker, tdMyIngress}, false) - diffOpt = &LiveDiffOption{DryRun: dryrunOpt, Parser: appfile.NewApplicationParser(k8sClient, pd)} + dryrunOpt = NewDryRunOption(k8sClient, cfg, []*unstructured.Unstructured{cdMyWorker, tdMyIngress}, false) + diffOpt = &LiveDiffOption{DryRun: dryrunOpt, Parser: appfile.NewApplicationParser(k8sClient)} }) var _ = AfterSuite(func() { diff --git a/pkg/appfile/parser.go b/pkg/appfile/parser.go index 16fbdd753..5c7852d98 100644 --- a/pkg/appfile/parser.go +++ b/pkg/appfile/parser.go @@ -33,7 +33,6 @@ import ( monitorContext "github.com/kubevela/pkg/monitor/context" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" @@ -63,24 +62,21 @@ func (fn TemplateLoaderFn) LoadTemplate(ctx context.Context, c client.Client, ca // Parser is an application parser type Parser struct { client client.Client - pd *packages.PackageDiscover tmplLoader TemplateLoaderFn } // NewApplicationParser create appfile parser -func NewApplicationParser(cli client.Client, pd *packages.PackageDiscover) *Parser { +func NewApplicationParser(cli client.Client) *Parser { return &Parser{ client: cli, - pd: pd, tmplLoader: LoadTemplate, } } // NewDryRunApplicationParser create an appfile parser for DryRun -func NewDryRunApplicationParser(cli client.Client, pd *packages.PackageDiscover, defs []*unstructured.Unstructured) *Parser { +func NewDryRunApplicationParser(cli client.Client, defs []*unstructured.Unstructured) *Parser { return &Parser{ client: cli, - pd: pd, tmplLoader: DryRunTemplateLoader(defs), } } @@ -515,7 +511,7 @@ func (p *Parser) convertTemplate2Component(name, typ string, props *runtime.RawE CapabilityCategory: templ.CapabilityCategory, FullTemplate: templ, Params: settings, - engine: definition.NewWorkloadAbstractEngine(name, p.pd), + engine: definition.NewWorkloadAbstractEngine(name), }, nil } @@ -710,7 +706,7 @@ func (p *Parser) convertTemplate2Trait(name string, properties map[string]interf HealthCheckPolicy: templ.Health, CustomStatusFormat: templ.CustomStatus, FullTemplate: templ, - engine: definition.NewTraitAbstractEngine(traitName, p.pd), + engine: definition.NewTraitAbstractEngine(traitName), }, nil } diff --git a/pkg/appfile/parser_test.go b/pkg/appfile/parser_test.go index 672e183bf..5c9c01df5 100644 --- a/pkg/appfile/parser_test.go +++ b/pkg/appfile/parser_test.go @@ -265,21 +265,21 @@ var _ = Describe("Test application parser", func() { }, } - appfile, err := NewApplicationParser(&tclient, pd).GenerateAppFile(context.TODO(), &o) + appfile, err := NewApplicationParser(&tclient).GenerateAppFile(context.TODO(), &o) Expect(err).ShouldNot(HaveOccurred()) Expect(equal(expectedExceptApp, appfile)).Should(BeTrue()) notfound := v1beta1.Application{} err = yaml.Unmarshal([]byte(appfileYaml2), ¬found) Expect(err).ShouldNot(HaveOccurred()) - _, err = NewApplicationParser(&tclient, pd).GenerateAppFile(context.TODO(), ¬found) + _, err = NewApplicationParser(&tclient).GenerateAppFile(context.TODO(), ¬found) Expect(err).Should(HaveOccurred()) By("app with empty policy") emptyPolicy := v1beta1.Application{} err = yaml.Unmarshal([]byte(appfileYamlEmptyPolicy), &emptyPolicy) Expect(err).ShouldNot(HaveOccurred()) - _, err = NewApplicationParser(&tclient, pd).GenerateAppFile(context.TODO(), &emptyPolicy) + _, err = NewApplicationParser(&tclient).GenerateAppFile(context.TODO(), &emptyPolicy) Expect(err).Should(HaveOccurred()) Expect(err.Error()).Should(ContainSubstring("have empty properties")) }) @@ -439,7 +439,7 @@ patch: spec: replicas: parameter.replicas It("Test we can parse an application revision to an appFile 1", func() { - appfile, err := NewApplicationParser(&mockClient, pd).GenerateAppFile(context.TODO(), &app) + appfile, err := NewApplicationParser(&mockClient).GenerateAppFile(context.TODO(), &app) Expect(err).ShouldNot(HaveOccurred()) Expect(equal(expectedExceptAppfile, appfile)).Should(BeTrue()) Expect(len(appfile.WorkflowSteps) > 0 && @@ -469,7 +469,7 @@ patch: spec: replicas: parameter.replicas It("Test we can parse an application revision to an appFile 2", func() { - appfile, err := NewApplicationParser(&mockClient, pd).GenerateAppFile(context.TODO(), &app) + appfile, err := NewApplicationParser(&mockClient).GenerateAppFile(context.TODO(), &app) Expect(err).ShouldNot(HaveOccurred()) Expect(equal(expectedExceptAppfile, appfile)).Should(BeTrue()) Expect(len(appfile.WorkflowSteps) > 0 && @@ -500,7 +500,7 @@ patch: spec: replicas: parameter.replicas It("Test we can parse an application revision to an appFile 3", func() { - _, err := NewApplicationParser(&mockClient, pd).GenerateAppFile(context.TODO(), &app) + _, err := NewApplicationParser(&mockClient).GenerateAppFile(context.TODO(), &app) Expect(err).Should(HaveOccurred()) Expect(err.Error()).Should(SatisfyAll( ContainSubstring("failed to get workflow step definition apply-application-unknown: not found"), @@ -594,7 +594,7 @@ func TestParser_parseTraits(t *testing.T) { }, } - p := NewApplicationParser(nil, pd) + p := NewApplicationParser(nil) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p.tmplLoader = tt.mockTemplateLoaderFn @@ -696,7 +696,7 @@ func TestParser_parseTraitsFromRevision(t *testing.T) { }, }, } - p := NewApplicationParser(fake.NewClientBuilder().Build(), pd) + p := NewApplicationParser(fake.NewClientBuilder().Build()) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.wantErr(t, p.parseTraitsFromRevision(tt.args.comp, tt.args.appRev, tt.args.workload), fmt.Sprintf("parseTraitsFromRevision(%v, %v, %v)", tt.args.comp, tt.args.appRev, tt.args.workload)) diff --git a/pkg/appfile/suit_test.go b/pkg/appfile/suit_test.go index a639e98d8..871bc3092 100644 --- a/pkg/appfile/suit_test.go +++ b/pkg/appfile/suit_test.go @@ -32,8 +32,6 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "github.com/kubevela/workflow/pkg/cue/packages" - coreoam "github.com/oam-dev/kubevela/apis/core.oam.dev" // +kubebuilder:scaffold:imports ) @@ -42,7 +40,6 @@ var cfg *rest.Config var scheme *runtime.Scheme var k8sClient client.Client var testEnv *envtest.Environment -var pd *packages.PackageDiscover func TestAppFile(t *testing.T) { RegisterFailHandler(Fail) @@ -71,9 +68,6 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(pd).ToNot(BeNil()) }) var _ = AfterSuite(func() { diff --git a/pkg/appfile/validate_test.go b/pkg/appfile/validate_test.go index 5642369b3..3ae6d2b63 100644 --- a/pkg/appfile/validate_test.go +++ b/pkg/appfile/validate_test.go @@ -43,19 +43,19 @@ var _ = Describe("Test validate CUE schematic Appfile", func() { Name: "myscaler", CapabilityCategory: types.CUECategory, Template: tc.traitDefTmpl1, - engine: definition.NewTraitAbstractEngine("myscaler", pd), + engine: definition.NewTraitAbstractEngine("myscaler"), }, { Name: "myingress", CapabilityCategory: types.CUECategory, Template: tc.traitDefTmpl2, - engine: definition.NewTraitAbstractEngine("myingress", pd), + engine: definition.NewTraitAbstractEngine("myingress"), }, }, FullTemplate: &Template{ TemplateStr: tc.compDefTmpl, }, - engine: definition.NewWorkloadAbstractEngine("myweb", pd), + engine: definition.NewWorkloadAbstractEngine("myweb"), } ctxData := GenerateContextDataFromAppFile(&Appfile{ diff --git a/pkg/cache/informer.go b/pkg/cache/informer.go index e8d9d4f04..a25d6f774 100644 --- a/pkg/cache/informer.go +++ b/pkg/cache/informer.go @@ -33,8 +33,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - ctrlutils "github.com/oam-dev/kubevela/pkg/controller/utils" "github.com/oam-dev/kubevela/pkg/features" + "github.com/oam-dev/kubevela/pkg/utils/apply" ) var ( @@ -104,7 +104,7 @@ func (in *ObjectCache[T]) DeleteRef(hash string, ref string) { // Remap relocate the object ptr with given ref func (in *ObjectCache[T]) Remap(m map[string]*T, ref string) { for key, o := range m { - if hash, err := ctrlutils.ComputeSpecHash(o); err == nil { + if hash, err := apply.ComputeSpecHash(o); err == nil { m[key] = in.Add(hash, o, ref) } } @@ -113,7 +113,7 @@ func (in *ObjectCache[T]) Remap(m map[string]*T, ref string) { // Unmap drop all the hash object from the map func (in *ObjectCache[T]) Unmap(m map[string]*T, ref string) { for _, o := range m { - if hash, err := ctrlutils.ComputeSpecHash(o); err == nil { + if hash, err := apply.ComputeSpecHash(o); err == nil { in.DeleteRef(hash, ref) } } diff --git a/pkg/config/factory.go b/pkg/config/factory.go index a2149a7b4..770d2e0e3 100644 --- a/pkg/config/factory.go +++ b/pkg/config/factory.go @@ -214,7 +214,7 @@ func (e *Validation) Error() string { // Factory handle the config type Factory interface { - ParseTemplate(defaultName string, content []byte) (*Template, error) + ParseTemplate(ctx context.Context, defaultName string, content []byte) (*Template, error) ParseConfig(ctx context.Context, template NamespacedName, meta Metadata) (*Config, error) LoadTemplate(ctx context.Context, name, ns string) (*Template, error) @@ -269,9 +269,9 @@ type kubeConfigFactory struct { } // ParseTemplate parse a config template instance form the cue script -func (k *kubeConfigFactory) ParseTemplate(defaultName string, content []byte) (*Template, error) { +func (k *kubeConfigFactory) ParseTemplate(ctx context.Context, defaultName string, content []byte) (*Template, error) { cueScript := script.BuildCUEScriptWithDefaultContext(icontext.DefaultContext, content) - value, err := cueScript.ParseToTemplateValueWithCueX() + value, err := cueScript.ParseToTemplateValueWithCueX(ctx) if err != nil { return nil, fmt.Errorf("the cue script is invalid:%w", err) } @@ -292,7 +292,7 @@ func (k *kubeConfigFactory) ParseTemplate(defaultName string, content []byte) (* if !templateValue.Exists() { return nil, fmt.Errorf("failed to lookup value: var(path=template) not exist") } - schema, err := cueScript.ParsePropertiesToSchemaWithCueX("template") + schema, err := cueScript.ParsePropertiesToSchemaWithCueX(ctx, "template") if err != nil { return nil, fmt.Errorf("the properties of the cue script is invalid:%w", err) } diff --git a/pkg/config/factory_test.go b/pkg/config/factory_test.go index 302d7fd97..4e7ed1092 100644 --- a/pkg/config/factory_test.go +++ b/pkg/config/factory_test.go @@ -34,7 +34,7 @@ func TestParseConfigTemplate(t *testing.T) { content, err := os.ReadFile("testdata/helm-repo.cue") r.Equal(err, nil) var inf = &kubeConfigFactory{} - template, err := inf.ParseTemplate("default", content) + template, err := inf.ParseTemplate(context.Background(), "default", content) r.Equal(err, nil) r.NotEqual(template, nil) r.Equal(template.Name, "default") @@ -52,7 +52,7 @@ var _ = Describe("test config factory", func() { It("apply the nacos server template", func() { data, err := os.ReadFile("./testdata/nacos-server.cue") Expect(err).Should(BeNil()) - t, err := fac.ParseTemplate("", data) + t, err := fac.ParseTemplate(context.Background(), "", data) Expect(err).Should(BeNil()) Expect(fac.CreateOrUpdateConfigTemplate(context.TODO(), "default", t)).Should(BeNil()) }) @@ -78,7 +78,7 @@ var _ = Describe("test config factory", func() { By("apply a template that with the nacos writer") data, err := os.ReadFile("./testdata/mysql-db-nacos.cue") Expect(err).Should(BeNil()) - t, err := fac.ParseTemplate("", data) + t, err := fac.ParseTemplate(context.Background(), "", data) Expect(err).Should(BeNil()) Expect(t.ExpandedWriter.Nacos).ShouldNot(BeNil()) Expect(t.ExpandedWriter.Nacos.Endpoint.Name).Should(Equal("nacos")) diff --git a/pkg/config/provider/provider.go b/pkg/config/provider/provider.go deleted file mode 100644 index edd3b6317..000000000 --- a/pkg/config/provider/provider.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2023 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package provider - -import ( - "errors" - "strings" - - "sigs.k8s.io/controller-runtime/pkg/client" - - monitorContext "github.com/kubevela/pkg/monitor/context" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/types" - - "github.com/oam-dev/kubevela/pkg/config" -) - -const ( - // ProviderName is provider name - ProviderName = "config" -) - -// ErrRequestInvalid means the request is invalid -var ErrRequestInvalid = errors.New("the request is in valid") - -type provider struct { - factory config.Factory -} - -// CreateConfigProperties the request body for creating a config -type CreateConfigProperties struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Template string `json:"template,omitempty"` - Config map[string]interface{} `json:"config"` -} - -// Response the response body -type Response struct { - Status string `json:"status"` - Message string `json:"message"` -} - -func (p *provider) Create(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - var ccp CreateConfigProperties - if err := v.UnmarshalTo(&ccp); err != nil { - return ErrRequestInvalid - } - name := ccp.Template - namespace := "vela-system" - if strings.Contains(ccp.Template, "/") { - namespacedName := strings.SplitN(ccp.Template, "/", 2) - namespace = namespacedName[0] - name = namespacedName[1] - } - configItem, err := p.factory.ParseConfig(ctx.GetContext(), config.NamespacedName{ - Name: name, - Namespace: namespace, - }, config.Metadata{ - NamespacedName: config.NamespacedName{ - Name: ccp.Name, - Namespace: ccp.Namespace, - }, - Properties: ccp.Config, - }) - if err != nil { - return err - } - return p.factory.CreateOrUpdateConfig(ctx.GetContext(), configItem, ccp.Namespace) -} - -func (p *provider) Read(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - var nn config.NamespacedName - if err := v.UnmarshalTo(&nn); err != nil { - return ErrRequestInvalid - } - content, err := p.factory.ReadConfig(ctx.GetContext(), nn.Namespace, nn.Name) - if err != nil { - return err - } - return v.FillObject(content, "config") -} - -func (p *provider) List(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - template, err := v.GetString("template") - if err != nil { - return ErrRequestInvalid - } - namespace, err := v.GetString("namespace") - if err != nil { - return ErrRequestInvalid - } - if strings.Contains(template, "/") { - namespacedName := strings.SplitN(template, "/", 2) - template = namespacedName[1] - } - configs, err := p.factory.ListConfigs(ctx.GetContext(), namespace, template, "", false) - if err != nil { - return err - } - var contents = []map[string]interface{}{} - for _, c := range configs { - contents = append(contents, map[string]interface{}{ - "name": c.Name, - "alias": c.Alias, - "description": c.Description, - "config": c.Properties, - }) - } - return v.FillObject(contents, "configs") -} - -func (p *provider) Delete(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - var nn config.NamespacedName - if err := v.UnmarshalTo(&nn); err != nil { - return errors.New("the request is in valid") - } - return p.factory.DeleteConfig(ctx.GetContext(), nn.Namespace, nn.Name) -} - -// Install register handlers to provider discover. -func Install(p types.Providers, cli client.Client, apply config.Dispatcher) { - prd := &provider{ - factory: config.NewConfigFactoryWithDispatcher(cli, apply), - } - p.Register(ProviderName, map[string]types.Handler{ - "create": prd.Create, - "read": prd.Read, - "list": prd.List, - "delete": prd.Delete, - }) -} diff --git a/pkg/config/writer/nacos.go b/pkg/config/writer/nacos.go index 43f97e7ff..93be72c0f 100644 --- a/pkg/config/writer/nacos.go +++ b/pkg/config/writer/nacos.go @@ -22,6 +22,7 @@ import ( "runtime/debug" "strings" + "cuelang.org/go/cue" "github.com/nacos-group/nacos-sdk-go/v2/clients" "github.com/nacos-group/nacos-sdk-go/v2/clients/config_client" "github.com/nacos-group/nacos-sdk-go/v2/common/constant" @@ -32,7 +33,6 @@ import ( "github.com/oam-dev/kubevela/apis/types" icontext "github.com/oam-dev/kubevela/pkg/config/context" - "github.com/oam-dev/kubevela/pkg/cue" "github.com/oam-dev/kubevela/pkg/cue/script" ) @@ -62,15 +62,17 @@ type NacosData struct { } // parseNacosConfig parse the nacos server config -func parseNacosConfig(templateField *value.Value, wc *ExpandedWriterConfig) { - nacos, _ := templateField.LookupValue("nacos") - if nacos != nil { - format, err := nacos.GetString("format") - if err != nil && !cue.IsFieldNotExist(err) { +func parseNacosConfig(templateField cue.Value, wc *ExpandedWriterConfig) { + nacos := templateField.LookupPath(cue.ParsePath("nacos")) + if nacos.Err() == nil { + formatValue := nacos.LookupPath(cue.ParsePath("format")) + format, err := formatValue.String() + if err != nil { klog.Warningf("fail to get the format from the nacos config: %s", err.Error()) } - endpoint, err := nacos.GetString("endpoint", "name") - if err != nil && !cue.IsFieldNotExist(err) { + endpointValue := nacos.LookupPath(value.FieldPath("endpoint", "name")) + endpoint, err := endpointValue.String() + if err != nil { klog.Warningf("fail to get the endpoint name from the nacos config: %s", err.Error()) } wc.Nacos = &NacosConfig{ @@ -87,17 +89,18 @@ func renderNacos(config *NacosConfig, template script.CUE, context icontext.Conf if err != nil { return nil, err } - format, err := nacos.GetString("format") + formatValue := nacos.LookupPath(cue.ParsePath("format")) + format, err := formatValue.String() if err != nil { format = config.Format } var nacosData NacosData - if err := nacos.UnmarshalTo(&nacosData); err != nil { + if err := value.UnmarshalTo(nacos, &nacosData); err != nil { return nil, err } - content, err := nacos.LookupValue("content") - if err != nil { - return nil, err + content := nacos.LookupPath(cue.ParsePath("content")) + if content.Err() != nil { + return nil, content.Err() } out, err := encodingOutput(content, format) diff --git a/pkg/config/writer/nacos_test.go b/pkg/config/writer/nacos_test.go index 0a938ad1d..3db1ed4cf 100644 --- a/pkg/config/writer/nacos_test.go +++ b/pkg/config/writer/nacos_test.go @@ -25,7 +25,7 @@ import ( "github.com/nacos-group/nacos-sdk-go/v2/vo" "github.com/stretchr/testify/require" - "github.com/kubevela/workflow/pkg/cue/model/value" + "cuelang.org/go/cue/cuecontext" configcontext "github.com/oam-dev/kubevela/pkg/config/context" "github.com/oam-dev/kubevela/pkg/cue/script" @@ -34,15 +34,15 @@ import ( func TestNacosWriter(t *testing.T) { r := require.New(t) - v, err := value.NewValue(` + v := cuecontext.New().CompileString(` nacos: { endpoint: { name: "test-nacos-server" } format: "json" } - `, nil, "") - r.Equal(err, nil) + `) + r.Equal(v.Err(), nil) ewc := &ExpandedWriterConfig{} parseNacosConfig(v, ewc) r.Equal(ewc.Nacos.Endpoint.Name, "test-nacos-server") diff --git a/pkg/config/writer/writer.go b/pkg/config/writer/writer.go index 1a688f990..4aacdf811 100644 --- a/pkg/config/writer/writer.go +++ b/pkg/config/writer/writer.go @@ -25,13 +25,12 @@ import ( "cuelang.org/go/cue" + "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/magiconair/properties" "github.com/pelletier/go-toml" "gopkg.in/yaml.v3" "k8s.io/klog/v2" - "github.com/kubevela/workflow/pkg/cue/model/value" - icontext "github.com/oam-dev/kubevela/pkg/config/context" "github.com/oam-dev/kubevela/pkg/cue/script" ) @@ -94,9 +93,9 @@ func Write(ctx context.Context, ewd *ExpandedWriterData, ri icontext.ReadConfigP } // encodingOutput support the json、toml、xml、properties and yaml formats. -func encodingOutput(input *value.Value, format string) ([]byte, error) { +func encodingOutput(input cue.Value, format string) ([]byte, error) { var data = make(map[string]interface{}) - if err := input.UnmarshalTo(&data); err != nil { + if err := value.UnmarshalTo(input, &data); err != nil { return nil, err } switch strings.ToLower(format) { diff --git a/pkg/config/writer/writter_test.go b/pkg/config/writer/writter_test.go index 4390e2a0d..5b28728ec 100644 --- a/pkg/config/writer/writter_test.go +++ b/pkg/config/writer/writter_test.go @@ -19,7 +19,7 @@ package writer import ( "testing" - "github.com/kubevela/workflow/pkg/cue/model/value" + "cuelang.org/go/cue/cuecontext" "github.com/stretchr/testify/require" ) @@ -70,10 +70,10 @@ func TestEncodingOutput(t *testing.T) { key9: {key10: [{"wang": true}]} } ` - v, err := value.NewValue(testValue, nil, "") - r.Equal(err, nil) + v := cuecontext.New().CompileString(testValue) + r.Equal(v.Err(), nil) - _, err = encodingOutput(v, "yaml") + _, err := encodingOutput(v, "yaml") r.Equal(err, nil) _, err = encodingOutput(v, "properties") diff --git a/pkg/controller/core.oam.dev/oamruntime_controller.go b/pkg/controller/core.oam.dev/oamruntime_controller.go index bbc19da3f..f89f17a2b 100644 --- a/pkg/controller/core.oam.dev/oamruntime_controller.go +++ b/pkg/controller/core.oam.dev/oamruntime_controller.go @@ -18,8 +18,6 @@ package core_oam_dev import ( "github.com/spf13/pflag" - - "github.com/kubevela/workflow/pkg/cue/packages" ) // Args args used by controller @@ -37,9 +35,6 @@ type Args struct { // The default value is 20. DefRevisionLimit int - // PackageDiscover used for CRD discovery in CUE packages, a K8s client is contained in it. - PackageDiscover *packages.PackageDiscover - // ConcurrentReconciles is the concurrent reconcile number of the controller ConcurrentReconciles int diff --git a/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go b/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go index eebb746b5..63f1a69ce 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go @@ -45,7 +45,6 @@ import ( monitorContext "github.com/kubevela/pkg/monitor/context" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/kubevela/workflow/pkg/executor" wffeatures "github.com/kubevela/workflow/pkg/features" @@ -86,7 +85,6 @@ var ( // Reconciler reconciles an Application object type Reconciler struct { client.Client - pd *packages.PackageDiscover Scheme *runtime.Scheme Recorder event.Recorder options @@ -139,7 +137,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu setVelaVersion(app) logCtx.AddTag("publish_version", app.GetAnnotations()[oam.AnnotationPublishVersion]) - appParser := appfile.NewApplicationParser(r.Client, r.pd) + appParser := appfile.NewApplicationParser(r.Client) handler, err := NewAppHandler(logCtx, r, app) if err != nil { return r.endWithNegativeCondition(logCtx, app, condition.ReconcileError(err), common.ApplicationStarting) @@ -203,7 +201,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu app.Status.SetConditions(condition.ReadyCondition(common.RenderCondition.String())) r.Recorder.Event(app, event.Normal(velatypes.ReasonRendered, velatypes.MessageRendered)) - workflowExecutor := executor.New(workflowInstance, r.Client, nil) + workflowExecutor := executor.New(workflowInstance) authCtx := logCtx.Fork("execute application workflow") defer authCtx.Commit("finish execute application workflow") authCtx = auth.MonitorContextWithUserInfo(authCtx, app) @@ -600,7 +598,6 @@ func Setup(mgr ctrl.Manager, args core.Args) error { Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: event.NewAPIRecorder(mgr.GetEventRecorderFor("Application")), - pd: args.PackageDiscover, options: parseOptions(args), } return reconciler.SetupWithManager(mgr) diff --git a/pkg/controller/core.oam.dev/v1beta1/application/apply.go b/pkg/controller/core.oam.dev/v1beta1/application/apply.go index bf3b9c950..39f11993a 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/apply.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/apply.go @@ -20,7 +20,6 @@ import ( "context" "sync" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" @@ -47,7 +46,6 @@ import ( // AppHandler handles application reconcile type AppHandler struct { client.Client - pd *packages.PackageDiscover app *v1beta1.Application currentAppRev *v1beta1.ApplicationRevision @@ -78,14 +76,13 @@ func NewAppHandler(ctx context.Context, r *Reconciler, app *v1beta1.Application) } return &AppHandler{ Client: r.Client, - pd: r.pd, app: app, resourceKeeper: resourceHandler, }, nil } // Dispatch apply manifests into k8s. -func (h *AppHandler) Dispatch(ctx context.Context, cluster string, owner string, manifests ...*unstructured.Unstructured) error { +func (h *AppHandler) Dispatch(ctx context.Context, _ client.Client, cluster string, owner string, manifests ...*unstructured.Unstructured) error { manifests = multicluster.ResourcesWithClusterName(cluster, manifests...) if err := h.resourceKeeper.Dispatch(ctx, manifests, nil); err != nil { return err @@ -113,7 +110,7 @@ func (h *AppHandler) Dispatch(ctx context.Context, cluster string, owner string, } // Delete delete manifests from k8s. -func (h *AppHandler) Delete(ctx context.Context, cluster string, owner string, manifest *unstructured.Unstructured) error { +func (h *AppHandler) Delete(ctx context.Context, _ client.Client, cluster string, owner string, manifest *unstructured.Unstructured) error { manifests := multicluster.ResourcesWithClusterName(cluster, manifest) if err := h.resourceKeeper.Delete(ctx, manifests); err != nil { return err @@ -224,11 +221,11 @@ func (h *AppHandler) addServiceStatus(cover bool, svcs ...common.ApplicationComp } // collectTraitHealthStatus collect trait health status -func (h *AppHandler) collectTraitHealthStatus(comp *appfile.Component, tr *appfile.Trait, appRev *v1beta1.ApplicationRevision, overrideNamespace string) (common.ApplicationTraitStatus, []*unstructured.Unstructured, error) { +func (h *AppHandler) collectTraitHealthStatus(comp *appfile.Component, tr *appfile.Trait, overrideNamespace string) (common.ApplicationTraitStatus, []*unstructured.Unstructured, error) { defer func(clusterName string) { comp.Ctx.SetCtx(pkgmulticluster.WithCluster(comp.Ctx.GetCtx(), clusterName)) }(multicluster.ClusterNameInContext(comp.Ctx.GetCtx())) - + appRev := h.currentAppRev var ( pCtx = comp.Ctx appName = appRev.Spec.Application.Name @@ -259,10 +256,11 @@ func (h *AppHandler) collectTraitHealthStatus(comp *appfile.Component, tr *appfi } // collectWorkloadHealthStatus collect workload health status -func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, status *common.ApplicationComponentStatus, accessor util.NamespaceAccessor) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { +func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, comp *appfile.Component, status *common.ApplicationComponentStatus, accessor util.NamespaceAccessor) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { var output *unstructured.Unstructured var outputs []*unstructured.Unstructured var ( + appRev = h.currentAppRev appName = appRev.Spec.Application.Name isHealth = true ) @@ -303,7 +301,7 @@ func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, comp *appf // nolint // collectHealthStatus will collect health status of component, including component itself and traits. -func (h *AppHandler) collectHealthStatus(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, overrideNamespace string, skipWorkload bool, traitFilters ...TraitFilter) (*common.ApplicationComponentStatus, *unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { +func (h *AppHandler) collectHealthStatus(ctx context.Context, comp *appfile.Component, overrideNamespace string, skipWorkload bool, traitFilters ...TraitFilter) (*common.ApplicationComponentStatus, *unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { output := new(unstructured.Unstructured) outputs := make([]*unstructured.Unstructured, 0) accessor := util.NewApplicationResourceNamespaceAccessor(h.app.Namespace, overrideNamespace) @@ -321,7 +319,7 @@ func (h *AppHandler) collectHealthStatus(ctx context.Context, comp *appfile.Comp status = h.getServiceStatus(status) if !skipWorkload { - isHealth, output, outputs, err = h.collectWorkloadHealthStatus(ctx, comp, appRev, &status, accessor) + isHealth, output, outputs, err = h.collectWorkloadHealthStatus(ctx, comp, &status, accessor) if err != nil { return nil, nil, nil, false, err } @@ -337,7 +335,7 @@ collectNext: } } - traitStatus, _outputs, err := h.collectTraitHealthStatus(comp, tr, appRev, overrideNamespace) + traitStatus, _outputs, err := h.collectTraitHealthStatus(comp, tr, overrideNamespace) if err != nil { return nil, nil, nil, false, err } @@ -405,7 +403,7 @@ func (h *AppHandler) ApplyPolicies(ctx context.Context, af *appfile.Appfile) err oam.LabelAppNamespace: h.app.GetNamespace(), }) } - if err = h.Dispatch(ctx, "", common.PolicyResourceCreator, policyManifests...); err != nil { + if err = h.Dispatch(ctx, h.Client, "", common.PolicyResourceCreator, policyManifests...); err != nil { return errors.Wrapf(err, "failed to dispatch policy manifests") } } diff --git a/pkg/controller/core.oam.dev/v1beta1/application/apply_test.go b/pkg/controller/core.oam.dev/v1beta1/application/apply_test.go index ace63ee0c..93c4a6ca5 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/apply_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/apply_test.go @@ -227,7 +227,7 @@ var _ = Describe("Test deleter resource", func() { h, err := NewAppHandler(ctx, reconciler, &v1beta1.Application{ObjectMeta: metav1.ObjectMeta{Name: "example", Namespace: "default"}}) Expect(err).Should(Succeed()) h.appliedResources = appliedRsc - Expect(h.Delete(ctx, "", common.WorkflowResourceCreator, &u)) + Expect(h.Delete(ctx, h.Client, "", common.WorkflowResourceCreator, &u)) checkDeploy := unstructured.Unstructured{} checkDeploy.SetAPIVersion("apps/v1") checkDeploy.SetKind("Deployment") diff --git a/pkg/controller/core.oam.dev/v1beta1/application/assemble/suit_test.go b/pkg/controller/core.oam.dev/v1beta1/application/assemble/suit_test.go index 155a33b2d..0a10f26ae 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/assemble/suit_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/assemble/suit_test.go @@ -36,8 +36,6 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/appfile" // +kubebuilder:scaffold:imports @@ -89,10 +87,8 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - pd, err := packages.NewPackageDiscover(cfg) - Expect(err).To(BeNil()) - appParser = appfile.NewApplicationParser(k8sClient, pd) + appParser = appfile.NewApplicationParser(k8sClient) }) var _ = AfterSuite(func() { diff --git a/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go b/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go index 45614d475..52b966d92 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go @@ -129,7 +129,7 @@ func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, rea if !h.resourceKeeper.ContainsResources(manifests) { return false, nil } - _, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, appRev, options.OverrideNamespace, skipWorkload, + _, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, options.OverrideNamespace, skipWorkload, ByTraitType(readyTraits, options.Traits)) if err != nil { return false, err @@ -139,10 +139,10 @@ func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, rea dispatcher.run = func(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) { skipWorkload, dispatchManifests := assembleManifestFn(comp.SkipApplyWorkload) if isHealth, err := dispatcher.healthCheck(ctx, comp, appRev); !isHealth || err != nil { - if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, dispatchManifests...); err != nil { + if err := h.Dispatch(ctx, h.Client, clusterName, common.WorkflowResourceCreator, dispatchManifests...); err != nil { return false, errors.WithMessage(err, "Dispatch") } - status, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, appRev, options.OverrideNamespace, skipWorkload, + status, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, options.OverrideNamespace, skipWorkload, ByTraitType(readyTraits, options.Traits)) if err != nil { return false, errors.WithMessage(err, "CollectHealthStatus") diff --git a/pkg/controller/core.oam.dev/v1beta1/application/gc_policy_test.go b/pkg/controller/core.oam.dev/v1beta1/application/gc_policy_test.go index b43e49af5..a1d4693f2 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/gc_policy_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/gc_policy_test.go @@ -545,7 +545,7 @@ var _ = Describe("Test Application with GC options", func() { return errors.New("app is not in running status") } return nil - }, 3*time.Second, 300*time.Second).Should(BeNil()) + }, 3*time.Second, time.Second).Should(BeNil()) By("check the resourceTrackers number") listOpts := []client.ListOption{ diff --git a/pkg/controller/core.oam.dev/v1beta1/application/generator.go b/pkg/controller/core.oam.dev/v1beta1/application/generator.go index ea60a2686..88852eec8 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/generator.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/generator.go @@ -18,15 +18,15 @@ package application import ( "context" "encoding/json" - "os" "strings" "time" + "cuelang.org/go/cue" + "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/klog/v2" "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" @@ -34,11 +34,9 @@ import ( pkgmulticluster "github.com/kubevela/pkg/multicluster" "github.com/kubevela/pkg/util/slices" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" - "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/kubevela/workflow/pkg/executor" "github.com/kubevela/workflow/pkg/generator" - "github.com/kubevela/workflow/pkg/providers" - "github.com/kubevela/workflow/pkg/providers/kube" + providertypes "github.com/kubevela/workflow/pkg/providers/types" wfTypes "github.com/kubevela/workflow/pkg/types" "github.com/oam-dev/kubevela/apis/core.oam.dev/common" @@ -47,7 +45,7 @@ import ( "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/appfile" "github.com/oam-dev/kubevela/pkg/auth" - configprovider "github.com/oam-dev/kubevela/pkg/config/provider" + "github.com/oam-dev/kubevela/pkg/config" "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1/application/assemble" ctrlutil "github.com/oam-dev/kubevela/pkg/controller/utils" velaprocess "github.com/oam-dev/kubevela/pkg/cue/process" @@ -56,22 +54,12 @@ import ( "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" - "github.com/oam-dev/kubevela/pkg/stdlib" "github.com/oam-dev/kubevela/pkg/utils/apply" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" - multiclusterProvider "github.com/oam-dev/kubevela/pkg/workflow/providers/multicluster" - oamProvider "github.com/oam-dev/kubevela/pkg/workflow/providers/oam" - terraformProvider "github.com/oam-dev/kubevela/pkg/workflow/providers/terraform" + "github.com/oam-dev/kubevela/pkg/workflow/providers" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" "github.com/oam-dev/kubevela/pkg/workflow/template" ) -func init() { - if err := stdlib.SetupBuiltinImports(); err != nil { - klog.ErrorS(err, "Unable to set up builtin imports on package initialization") - os.Exit(1) - } -} - var ( // DisableResourceApplyDoubleCheck optimize applyComponentFunc by disable post resource existing check after dispatch DisableResourceApplyDoubleCheck = false @@ -94,40 +82,36 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context, oam.LabelAppName: app.Name, oam.LabelAppNamespace: app.Namespace, } - handlerProviders := providers.NewProviders() - kube.Install(handlerProviders, h.Client, appLabels, &kube.Handlers{ - Apply: h.Dispatch, - Delete: h.Delete, - }) - configprovider.Install(handlerProviders, h.Client, func(ctx context.Context, resources []*unstructured.Unstructured, applyOptions []apply.ApplyOption) error { - for _, res := range resources { - res.SetLabels(util.MergeMapOverrideWithDst(res.GetLabels(), appLabels)) - } - return h.resourceKeeper.Dispatch(ctx, resources, applyOptions) - }) - oamProvider.Install(handlerProviders, app, af, h.Client, - h.applyComponentFunc(appParser, appRev, af), - h.renderComponentFunc(appParser, appRev, af), - ) pCtx := velaprocess.NewContext(generateContextDataFromApp(app, appRev.Name)) - renderer := func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) { - return appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev) - } - multiclusterProvider.Install(handlerProviders, h.Client, app, af, - h.applyComponentFunc(appParser, appRev, af), - h.checkComponentHealth(appParser, appRev, af), - renderer) - terraformProvider.Install(handlerProviders, app, renderer) - query.Install(handlerProviders, h.Client, nil) - + ctxWithRuntimeParams := oamprovidertypes.WithRuntimeParams(ctx.GetContext(), oamprovidertypes.RuntimeParams{ + ComponentApply: h.applyComponentFunc(appParser, af), + ComponentRender: h.renderComponentFunc(appParser, af), + ComponentHealthCheck: h.checkComponentHealth(appParser, af), + WorkloadRender: func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) { + return appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev) + }, + App: app, + AppLabels: appLabels, + Appfile: af, + KubeHandlers: &providertypes.KubeHandlers{ + Apply: h.Dispatch, + Delete: h.Delete, + }, + ConfigFactory: config.NewConfigFactoryWithDispatcher(h.Client, func(ctx context.Context, resources []*unstructured.Unstructured, applyOptions []apply.ApplyOption) error { + for _, res := range resources { + res.SetLabels(util.MergeMapOverrideWithDst(res.GetLabels(), appLabels)) + } + return h.resourceKeeper.Dispatch(ctx, resources, applyOptions) + }), + KubeClient: h.Client, + }) + ctx.SetContext(ctxWithRuntimeParams) instance := generateWorkflowInstance(af, app) executor.InitializeWorkflowInstance(instance) runners, err := generator.GenerateRunners(ctx, instance, wfTypes.StepGeneratorOptions{ - Providers: handlerProviders, - PackageDiscover: h.pd, - ProcessCtx: pCtx, - TemplateLoader: template.NewWorkflowStepTemplateRevisionLoader(appRev, h.Client.RESTMapper()), - Client: h.Client, + Compiler: providers.Compiler.Get(), + ProcessCtx: pCtx, + TemplateLoader: template.NewWorkflowStepTemplateRevisionLoader(appRev, h.Client.RESTMapper()), StepConvertor: map[string]func(step workflowv1alpha1.WorkflowStep) (workflowv1alpha1.WorkflowStep, error){ wfTypes.WorkflowStepTypeApplyComponent: func(lstep workflowv1alpha1.WorkflowStep) (workflowv1alpha1.WorkflowStep, error) { copierStep := lstep.DeepCopy() @@ -317,31 +301,31 @@ func checkDependsOnValidComponent(dependsOnComponentNames, allComponentNames []s return "", true } -func (h *AppHandler) renderComponentFunc(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile) oamProvider.ComponentRender { - return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) { +func (h *AppHandler) renderComponentFunc(appParser *appfile.Parser, af *appfile.Appfile) oamprovidertypes.ComponentRender { + return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) { ctx := multicluster.ContextWithClusterName(baseCtx, clusterName) - _, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, appRev, patcher, af) + _, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, patcher, af) if err != nil { return nil, nil, err } - return renderComponentsAndTraits(manifest, appRev, clusterName, overrideNamespace) + return renderComponentsAndTraits(manifest, h.currentAppRev, clusterName, overrideNamespace) } } -func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile) oamProvider.ComponentHealthCheck { - return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { +func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, af *appfile.Appfile) oamprovidertypes.ComponentHealthCheck { + return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { ctx := multicluster.ContextWithClusterName(baseCtx, clusterName) ctx = contextWithComponentNamespace(ctx, overrideNamespace) ctx = contextWithReplicaKey(ctx, comp.ReplicaKey) - wl, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, appRev, patcher, af) + wl, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, patcher, af) if err != nil { return false, nil, nil, err } wl.Ctx.SetCtx(auth.ContextWithUserInfo(ctx, h.app)) - readyWorkload, readyTraits, err := renderComponentsAndTraits(manifest, appRev, clusterName, overrideNamespace) + readyWorkload, readyTraits, err := renderComponentsAndTraits(manifest, h.currentAppRev, clusterName, overrideNamespace) if err != nil { return false, nil, nil, err } @@ -355,7 +339,7 @@ func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1b return false, nil, nil, err } - _, output, outputs, isHealth, err := h.collectHealthStatus(auth.ContextWithUserInfo(ctx, h.app), wl, appRev, overrideNamespace, false) + _, output, outputs, isHealth, err := h.collectHealthStatus(auth.ContextWithUserInfo(ctx, h.app), wl, overrideNamespace, false) if err != nil { return false, nil, nil, err } @@ -364,16 +348,17 @@ func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1b } } -func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile) oamProvider.ComponentApply { - return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { +func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, af *appfile.Appfile) oamprovidertypes.ComponentApply { + return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { t := time.Now() + appRev := h.currentAppRev defer func() { metrics.ApplyComponentTimeHistogram.WithLabelValues("-").Observe(time.Since(t).Seconds()) }() ctx := multicluster.ContextWithClusterName(baseCtx, clusterName) ctx = contextWithComponentNamespace(ctx, overrideNamespace) ctx = contextWithReplicaKey(ctx, comp.ReplicaKey) - wl, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, appRev, patcher, af) + wl, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, patcher, af) if err != nil { return nil, nil, false, err } @@ -403,10 +388,10 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet dispatchResources = append([]*unstructured.Unstructured{readyWorkload}, readyTraits...) } - if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, dispatchResources...); err != nil { + if err := h.Dispatch(ctx, h.Client, clusterName, common.WorkflowResourceCreator, dispatchResources...); err != nil { return nil, nil, false, errors.WithMessage(err, "Dispatch") } - _, _, _, isHealth, err = h.collectHealthStatus(ctx, wl, appRev, overrideNamespace, false) + _, _, _, isHealth, err = h.collectHealthStatus(ctx, wl, overrideNamespace, false) if err != nil { return nil, nil, false, errors.WithMessage(err, "CollectHealthStatus") } @@ -438,10 +423,9 @@ func redirectTraitToLocalIfNeed(appRev *v1beta1.ApplicationRevision, readyTraits func (h *AppHandler) prepareWorkloadAndManifests(ctx context.Context, appParser *appfile.Parser, comp common.ApplicationComponent, - appRev *v1beta1.ApplicationRevision, - patcher *value.Value, + patcher *cue.Value, af *appfile.Appfile) (*appfile.Component, *types.ComponentManifest, error) { - wl, err := appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev) + wl, err := appParser.ParseComponentFromRevisionAndClient(ctx, comp, h.currentAppRev) if err != nil { return nil, nil, errors.WithMessage(err, "ParseWorkload") } diff --git a/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go b/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go index efeb0e4b4..0e9e79384 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go @@ -165,7 +165,7 @@ var _ = Describe("test generate revision ", func() { It("Test application revision compare", func() { By("Apply the application") - appParser := appfile.NewApplicationParser(reconciler.Client, reconciler.pd) + appParser := appfile.NewApplicationParser(reconciler.Client) ctx = util.SetNamespaceInCtx(ctx, app.Namespace) generatedAppfile, err := appParser.GenerateAppFile(ctx, &app) Expect(err).Should(Succeed()) @@ -186,7 +186,7 @@ var _ = Describe("test generate revision ", func() { It("Test apply success for none rollout case", func() { By("Apply the application") - appParser := appfile.NewApplicationParser(reconciler.Client, reconciler.pd) + appParser := appfile.NewApplicationParser(reconciler.Client) ctx = util.SetNamespaceInCtx(ctx, app.Namespace) annoKey1 := "testKey1" app.SetAnnotations(map[string]string{annoKey1: "true"}) @@ -337,7 +337,7 @@ var _ = Describe("test generate revision ", func() { It("Test apply passes all label and annotation from app to appRevision", func() { By("Apply the application") - appParser := appfile.NewApplicationParser(reconciler.Client, reconciler.pd) + appParser := appfile.NewApplicationParser(reconciler.Client) ctx = util.SetNamespaceInCtx(ctx, app.Namespace) labelKey1 := "labelKey1" app.SetLabels(map[string]string{labelKey1: "true"}) @@ -723,7 +723,7 @@ status: {} It("Test currentAppRevIsNew func", func() { By("Backport 1.2 version that WorkflowStepDefinitions are not patched to application revision") // generate appfile - appfile, err := appfile.NewApplicationParser(reconciler.Client, reconciler.pd).GenerateAppFile(ctx, &app) + appfile, err := appfile.NewApplicationParser(reconciler.Client).GenerateAppFile(ctx, &app) ctx = util.SetNamespaceInCtx(ctx, app.Namespace) Expect(err).To(Succeed()) Expect(handler.PrepareCurrentAppRevision(ctx, appfile)).Should(Succeed()) diff --git a/pkg/controller/core.oam.dev/v1beta1/application/suite_test.go b/pkg/controller/core.oam.dev/v1beta1/application/suite_test.go index 35841fe6f..99aa3e5f2 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/suite_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/suite_test.go @@ -27,6 +27,7 @@ import ( "time" "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/kubevela/pkg/util/singleton" terraformv1beta2 "github.com/oam-dev/terraform-controller/api/v1beta2" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -45,8 +46,6 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/appfile" "github.com/oam-dev/kubevela/pkg/multicluster" @@ -109,15 +108,12 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - pd, err := packages.NewPackageDiscover(cfg) - Expect(err).To(BeNil()) - - appParser = appfile.NewApplicationParser(k8sClient, pd) + singleton.KubeClient.Set(k8sClient) + appParser = appfile.NewApplicationParser(k8sClient) reconciler = &Reconciler{ Client: k8sClient, Scheme: testScheme, - pd: pd, Recorder: event.NewAPIRecorder(recorder), } diff --git a/pkg/controller/core.oam.dev/v1beta1/application/workflow_test.go b/pkg/controller/core.oam.dev/v1beta1/application/workflow_test.go index c3cdc5e36..8f5c0ea54 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/workflow_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/workflow_test.go @@ -381,6 +381,8 @@ var _ = Describe("Test Workflow", func() { }, } + b, _ := json.Marshal(appwithInputOutput) + fmt.Println("app", string(b)) Expect(k8sClient.Create(context.Background(), appwithInputOutput)).Should(BeNil()) appKey := types.NamespacedName{Namespace: ns.Name, Name: appwithInputOutput.Name} testutil.ReconcileOnceAfterFinalizer(reconciler, reconcile.Request{NamespacedName: appKey}) @@ -824,8 +826,12 @@ spec: } } // wait until workload.status equal "Running" + w: *false | bool + if apply.value.spec != _|_ if apply.value.spec.key != "" { + w: true + } wait: op.#ConditionalWait & { - continue: apply.value.spec.key != "" + continue: w } ` ) diff --git a/pkg/controller/core.oam.dev/v1beta1/core/workflow/workflowstepdefinition/suite_test.go b/pkg/controller/core.oam.dev/v1beta1/core/workflow/workflowstepdefinition/suite_test.go index 67320d1bc..bbce8c6ba 100644 --- a/pkg/controller/core.oam.dev/v1beta1/core/workflow/workflowstepdefinition/suite_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/core/workflow/workflowstepdefinition/suite_test.go @@ -23,6 +23,7 @@ import ( "testing" "time" + "github.com/kubevela/pkg/util/singleton" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -71,6 +72,7 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) + singleton.KubeClient.Set(k8sClient) By("Starting the controller in the background") mgr, err := ctrl.NewManager(cfg, ctrl.Options{ diff --git a/pkg/controller/utils/capability.go b/pkg/controller/utils/capability.go index f1210ab0e..7032d2da4 100644 --- a/pkg/controller/utils/capability.go +++ b/pkg/controller/utils/capability.go @@ -40,8 +40,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/appfile" - "github.com/oam-dev/kubevela/pkg/cue/script" "github.com/oam-dev/kubevela/pkg/oam/util" + "github.com/oam-dev/kubevela/pkg/schema" "github.com/oam-dev/kubevela/pkg/utils/common" "github.com/oam-dev/kubevela/pkg/utils/terraform" ) @@ -121,12 +121,12 @@ func NewCapabilityComponentDef(componentDefinition *v1beta1.ComponentDefinition) } // GetOpenAPISchema gets OpenAPI v3 schema by WorkloadDefinition name -func (def *CapabilityComponentDefinition) GetOpenAPISchema(name string) ([]byte, error) { +func (def *CapabilityComponentDefinition) GetOpenAPISchema(ctx context.Context, name string) ([]byte, error) { capability, err := appfile.ConvertTemplateJSON2Object(name, def.ComponentDefinition.Spec.Extension, def.ComponentDefinition.Spec.Schematic) if err != nil { return nil, fmt.Errorf("failed to convert ComponentDefinition to Capability Object") } - return getOpenAPISchema(capability) + return getOpenAPISchema(ctx, capability) } // GetOpenAPISchemaFromTerraformComponentDefinition gets OpenAPI v3 schema by WorkloadDefinition name @@ -383,7 +383,7 @@ func (def *CapabilityComponentDefinition) StoreOpenAPISchema(ctx context.Context } jsonSchema, err = GetOpenAPISchemaFromTerraformComponentDefinition(configuration) default: - jsonSchema, err = def.GetOpenAPISchema(name) + jsonSchema, err = def.GetOpenAPISchema(ctx, name) } if err != nil { return "", fmt.Errorf("failed to generate OpenAPI v3 JSON schema for capability %s: %w", def.Name, err) @@ -441,17 +441,17 @@ func NewCapabilityTraitDef(traitdefinition *v1beta1.TraitDefinition) CapabilityT } // GetOpenAPISchema gets OpenAPI v3 schema by TraitDefinition name -func (def *CapabilityTraitDefinition) GetOpenAPISchema(name string) ([]byte, error) { +func (def *CapabilityTraitDefinition) GetOpenAPISchema(ctx context.Context, name string) ([]byte, error) { capability, err := appfile.ConvertTemplateJSON2Object(name, def.TraitDefinition.Spec.Extension, def.TraitDefinition.Spec.Schematic) if err != nil { return nil, fmt.Errorf("failed to convert WorkloadDefinition to Capability Object") } - return getOpenAPISchema(capability) + return getOpenAPISchema(ctx, capability) } // StoreOpenAPISchema stores OpenAPI v3 schema from TraitDefinition in ConfigMap func (def *CapabilityTraitDefinition) StoreOpenAPISchema(ctx context.Context, k8sClient client.Client, namespace, name string, revName string) (string, error) { - jsonSchema, err := def.GetOpenAPISchema(name) + jsonSchema, err := def.GetOpenAPISchema(ctx, name) if err != nil { return "", fmt.Errorf("failed to generate OpenAPI v3 JSON schema for capability %s: %w", def.Name, err) } @@ -507,12 +507,12 @@ func NewCapabilityStepDef(stepdefinition *v1beta1.WorkflowStepDefinition) Capabi } // GetOpenAPISchema gets OpenAPI v3 schema by StepDefinition name -func (def *CapabilityStepDefinition) GetOpenAPISchema(name string) ([]byte, error) { +func (def *CapabilityStepDefinition) GetOpenAPISchema(ctx context.Context, name string) ([]byte, error) { capability, err := appfile.ConvertTemplateJSON2Object(name, nil, def.StepDefinition.Spec.Schematic) if err != nil { return nil, fmt.Errorf("failed to convert WorkflowStepDefinition to Capability Object") } - return getOpenAPISchema(capability) + return getOpenAPISchema(ctx, capability) } // StoreOpenAPISchema stores OpenAPI v3 schema from StepDefinition in ConfigMap @@ -520,7 +520,7 @@ func (def *CapabilityStepDefinition) StoreOpenAPISchema(ctx context.Context, k8s var jsonSchema []byte var err error - jsonSchema, err = def.GetOpenAPISchema(name) + jsonSchema, err = def.GetOpenAPISchema(ctx, name) if err != nil { return "", fmt.Errorf("failed to generate OpenAPI v3 JSON schema for capability %s: %w", def.Name, err) } @@ -576,12 +576,12 @@ func NewCapabilityPolicyDef(policydefinition *v1beta1.PolicyDefinition) Capabili } // GetOpenAPISchema gets OpenAPI v3 schema by StepDefinition name -func (def *CapabilityPolicyDefinition) GetOpenAPISchema(name string) ([]byte, error) { +func (def *CapabilityPolicyDefinition) GetOpenAPISchema(ctx context.Context, name string) ([]byte, error) { capability, err := appfile.ConvertTemplateJSON2Object(name, nil, def.PolicyDefinition.Spec.Schematic) if err != nil { return nil, fmt.Errorf("failed to convert WorkflowStepDefinition to Capability Object") } - return getOpenAPISchema(capability) + return getOpenAPISchema(ctx, capability) } // StoreOpenAPISchema stores OpenAPI v3 schema from StepDefinition in ConfigMap @@ -589,7 +589,7 @@ func (def *CapabilityPolicyDefinition) StoreOpenAPISchema(ctx context.Context, k var jsonSchema []byte var err error - jsonSchema, err = def.GetOpenAPISchema(name) + jsonSchema, err = def.GetOpenAPISchema(ctx, name) if err != nil { return "", fmt.Errorf("failed to generate OpenAPI v3 JSON schema for capability %s: %w", def.Name, err) } @@ -687,14 +687,13 @@ func (def *CapabilityBaseDefinition) CreateOrUpdateConfigMap(ctx context.Context } // getOpenAPISchema is the main function for GetDefinition API -func getOpenAPISchema(capability types.Capability) ([]byte, error) { - cueTemplate := script.CUE(capability.CueTemplate) - schema, err := cueTemplate.ParsePropertiesToSchema() +func getOpenAPISchema(ctx context.Context, capability types.Capability) ([]byte, error) { + s, err := schema.ParsePropertiesToSchema(ctx, capability.CueTemplate) if err != nil { return nil, err } - klog.Infof("parsed %d properties by %s/%s", len(schema.Properties), capability.Type, capability.Name) - parameter, err := schema.MarshalJSON() + klog.Infof("parsed %d properties by %s/%s", len(s.Properties), capability.Type, capability.Name) + parameter, err := s.MarshalJSON() if err != nil { return nil, err } diff --git a/pkg/controller/utils/capability_integrate_test.go b/pkg/controller/utils/capability_integrate_test.go index 5120d6673..c4e9c9202 100644 --- a/pkg/controller/utils/capability_integrate_test.go +++ b/pkg/controller/utils/capability_integrate_test.go @@ -111,7 +111,7 @@ spec: def := &CapabilityComponentDefinition{Name: componentDefinitionName, ComponentDefinition: *componentDefinition.DeepCopy()} By("Test GetOpenAPISchema") - schema, err := def.GetOpenAPISchema(namespace) + schema, err := def.GetOpenAPISchema(context.Background(), namespace) Expect(err).Should(BeNil()) Expect(schema).Should(Not(BeNil())) }) diff --git a/pkg/controller/utils/capability_suite_test.go b/pkg/controller/utils/capability_suite_test.go index 9fa90883f..7b0b3d3fb 100644 --- a/pkg/controller/utils/capability_suite_test.go +++ b/pkg/controller/utils/capability_suite_test.go @@ -29,15 +29,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/kubevela/workflow/pkg/cue/packages" - oamCore "github.com/oam-dev/kubevela/apis/core.oam.dev" ) var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment -var pd *packages.PackageDiscover func TestCapability(t *testing.T) { RegisterFailHandler(Fail) @@ -67,9 +64,6 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) }) var _ = AfterSuite(func() { diff --git a/pkg/controller/utils/capability_test.go b/pkg/controller/utils/capability_test.go index a64aafede..79b7a1279 100644 --- a/pkg/controller/utils/capability_test.go +++ b/pkg/controller/utils/capability_test.go @@ -187,7 +187,7 @@ parameter: [string]: string }, } capability, _ := appfile.ConvertTemplateJSON2Object(tc.name, nil, schematic) - schema, err := getOpenAPISchema(capability) + schema, err := getOpenAPISchema(context.Background(), capability) if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { t.Errorf("\n%s\ngetOpenAPISchema(...): -want error, +got error:\n%s", tc.reason, diff) } diff --git a/pkg/cue/convert.go b/pkg/cue/convert.go index 50cf6c096..93dffd826 100644 --- a/pkg/cue/convert.go +++ b/pkg/cue/convert.go @@ -18,13 +18,10 @@ package cue import ( "errors" - "fmt" "strings" "cuelang.org/go/cue" - - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" + "cuelang.org/go/cue/cuecontext" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/cue/process" @@ -34,16 +31,13 @@ import ( var ErrParameterNotExist = errors.New("parameter not exist") // GetParameters get parameter from cue template -func GetParameters(templateStr string, pd *packages.PackageDiscover) ([]types.Parameter, error) { - template, err := value.NewValue(templateStr+BaseTemplate, pd, "") - if err != nil { - return nil, fmt.Errorf("error in template: %w", err) - } - paramVal, err := template.LookupValue(process.ParameterFieldName) - if err != nil || !paramVal.CueValue().Exists() { +func GetParameters(templateStr string) ([]types.Parameter, error) { + template := cuecontext.New().CompileString(templateStr + BaseTemplate) + paramVal := template.LookupPath(cue.ParsePath(process.ParameterFieldName)) + if !paramVal.Exists() { return nil, ErrParameterNotExist } - iter, err := paramVal.CueValue().Fields(cue.Definitions(true), cue.Hidden(true), cue.All()) + iter, err := paramVal.Fields(cue.Definitions(true), cue.Hidden(true), cue.All()) if err != nil { return nil, err } diff --git a/pkg/cue/convert_test.go b/pkg/cue/convert_test.go index 4158d49df..7cf0da082 100644 --- a/pkg/cue/convert_test.go +++ b/pkg/cue/convert_test.go @@ -28,7 +28,7 @@ import ( func TestGetParameter(t *testing.T) { data, _ := os.ReadFile("testdata/workloads/metrics.cue") - params, err := GetParameters(string(data), nil) + params, err := GetParameters(string(data)) assert.NoError(t, err) assert.Equal(t, params, []types.Parameter{ {Name: "format", Required: false, Default: "prometheus", Usage: "format of the metrics, " + @@ -38,7 +38,7 @@ func TestGetParameter(t *testing.T) { {Name: "selector", Required: false, Usage: "the label selector for the pods, default is the workload labels", Type: cue.StructKind}, }) data, _ = os.ReadFile("testdata/workloads/deployment.cue") - params, err = GetParameters(string(data), nil) + params, err = GetParameters(string(data)) assert.NoError(t, err) assert.Equal(t, []types.Parameter{ {Name: "name", Required: true, Default: "", Type: cue.StringKind}, @@ -50,7 +50,7 @@ func TestGetParameter(t *testing.T) { params) data, _ = os.ReadFile("testdata/workloads/test-param.cue") - params, err = GetParameters(string(data), nil) + params, err = GetParameters(string(data)) assert.NoError(t, err) assert.Equal(t, []types.Parameter{ {Name: "name", Required: true, Default: "", Type: cue.StringKind}, @@ -61,13 +61,13 @@ func TestGetParameter(t *testing.T) { {Name: "fval", Default: 64.3, Type: cue.FloatKind}, {Name: "nval", Default: float64(0), Required: true, Type: cue.NumberKind}}, params) data, _ = os.ReadFile("testdata/workloads/empty.cue") - params, err = GetParameters(string(data), nil) + params, err = GetParameters(string(data)) assert.NoError(t, err) var exp []types.Parameter assert.Equal(t, exp, params) data, _ = os.ReadFile("testdata/workloads/webservice.cue") // test cue parameter with "// +ignore" annotation - params, err = GetParameters(string(data), nil) // Only test for func RetrieveComments + params, err = GetParameters(string(data)) // Only test for func RetrieveComments assert.NoError(t, err) var flag bool for _, para := range params { diff --git a/pkg/cue/cuex/compiler.go b/pkg/cue/cuex/compiler.go index 998d4c00f..b31340c1d 100644 --- a/pkg/cue/cuex/compiler.go +++ b/pkg/cue/cuex/compiler.go @@ -23,8 +23,8 @@ import ( "github.com/oam-dev/kubevela/pkg/cue/cuex/providers/config" ) -// KubeVelaDefaultCompiler compiler for cuex to compile -var KubeVelaDefaultCompiler = singleton.NewSingleton[*cuex.Compiler](func() *cuex.Compiler { +// ConfigCompiler ... +var ConfigCompiler = singleton.NewSingleton[*cuex.Compiler](func() *cuex.Compiler { compiler := cuex.NewCompilerWithInternalPackages( config.Package, ) diff --git a/pkg/cue/definition/template.go b/pkg/cue/definition/template.go index 437cbfd04..d4659875d 100644 --- a/pkg/cue/definition/template.go +++ b/pkg/cue/definition/template.go @@ -20,9 +20,9 @@ import ( "context" "encoding/json" "fmt" + "strings" "cuelang.org/go/cue" - "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "github.com/kubevela/pkg/multicluster" @@ -33,7 +33,6 @@ import ( "github.com/kubevela/workflow/pkg/cue/model" "github.com/kubevela/workflow/pkg/cue/model/sets" "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/kubevela/workflow/pkg/cue/process" velaprocess "github.com/oam-dev/kubevela/pkg/cue/process" @@ -75,7 +74,6 @@ type AbstractEngine interface { type def struct { name string - pd *packages.PackageDiscover } type workloadDef struct { @@ -83,21 +81,16 @@ type workloadDef struct { } // NewWorkloadAbstractEngine create Workload Definition AbstractEngine -func NewWorkloadAbstractEngine(name string, pd *packages.PackageDiscover) AbstractEngine { +func NewWorkloadAbstractEngine(name string) AbstractEngine { return &workloadDef{ def: def{ name: name, - pd: pd, }, } } // Complete do workload definition's rendering func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string, params interface{}) error { - bi := build.NewContext().NewInstance("", nil) - if err := value.AddFile(bi, "-", renderTemplate(abstractTemplate)); err != nil { - return errors.WithMessagef(err, "invalid cue template of workload %s", wd.name) - } var paramFile = velaprocess.ParameterFieldName + ": {}" if params != nil { bt, err := json.Marshal(params) @@ -108,22 +101,15 @@ func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string, pa paramFile = fmt.Sprintf("%s: %s", velaprocess.ParameterFieldName, string(bt)) } } - if err := value.AddFile(bi, velaprocess.ParameterFieldName, paramFile); err != nil { - return errors.WithMessagef(err, "invalid parameter of workload %s", wd.name) - } c, err := ctx.BaseContextFile() if err != nil { return err } - if err := value.AddFile(bi, "context", c); err != nil { - return err - } - val, err := wd.pd.ImportPackagesAndBuildValue(bi) - if err != nil { - return err - } + val := cuecontext.New().CompileString(strings.Join([]string{ + renderTemplate(abstractTemplate), paramFile, c, + }, "\n")) if err := val.Validate(); err != nil { return errors.WithMessagef(err, "invalid cue template of workload %s after merge parameter and context", wd.name) @@ -260,10 +246,10 @@ func checkHealth(templateContext map[string]interface{}, healthPolicyTemplate st // Status get workload status by customStatusTemplate func (wd *workloadDef) Status(templateContext map[string]interface{}, customStatusTemplate string, parameter interface{}) (string, error) { - return getStatusMessage(wd.pd, templateContext, customStatusTemplate, parameter) + return getStatusMessage(templateContext, customStatusTemplate, parameter) } -func getStatusMessage(pd *packages.PackageDiscover, templateContext map[string]interface{}, customStatusTemplate string, parameter interface{}) (string, error) { +func getStatusMessage(templateContext map[string]interface{}, customStatusTemplate string, parameter interface{}) (string, error) { if customStatusTemplate == "" { return "", nil } @@ -273,11 +259,11 @@ func getStatusMessage(pd *packages.PackageDiscover, templateContext map[string]i } var buff = customStatusTemplate + "\n" + runtimeContextBuff - val, err := value.NewValue(buff, pd, "") - if err != nil { - return "", errors.WithMessage(err, "compile status template") + val := cuecontext.New().CompileString(buff) + if val.Err() != nil { + return "", errors.WithMessage(val.Err(), "compile status template") } - message, err := val.CueValue().LookupPath(value.FieldPath(CustomMessage)).String() + message, err := val.LookupPath(value.FieldPath(CustomMessage)).String() if err != nil { return "", errors.WithMessage(err, "evaluate customStatus.message") } @@ -293,11 +279,10 @@ type traitDef struct { } // NewTraitAbstractEngine create Trait Definition AbstractEngine -func NewTraitAbstractEngine(name string, pd *packages.PackageDiscover) AbstractEngine { +func NewTraitAbstractEngine(name string) AbstractEngine { return &traitDef{ def: def{ name: name, - pd: pd, }, } } @@ -305,7 +290,6 @@ func NewTraitAbstractEngine(name string, pd *packages.PackageDiscover) AbstractE // Complete do trait definition's rendering // nolint:gocyclo func (td *traitDef) Complete(ctx process.Context, abstractTemplate string, params interface{}) error { - bi := build.NewContext().NewInstance("", nil) buff := abstractTemplate + "\n" if params != nil { bt, err := json.Marshal(params) @@ -321,15 +305,8 @@ func (td *traitDef) Complete(ctx process.Context, abstractTemplate string, param return err } buff += c - if err := value.AddFile(bi, "-", buff); err != nil { - return errors.WithMessagef(err, "invalid context of trait %s", td.name) - } - - val, err := td.pd.ImportPackagesAndBuildValue(bi) - if err != nil { - return err - } + val := cuecontext.New().CompileString(buff) if err := val.Validate(); err != nil { return errors.WithMessagef(err, "invalid template of trait %s after merge with parameter and context", td.name) } @@ -479,7 +456,7 @@ func (td *traitDef) getTemplateContext(ctx process.Context, cli client.Reader, a // Status get trait status by customStatusTemplate func (td *traitDef) Status(templateContext map[string]interface{}, customStatusTemplate string, parameter interface{}) (string, error) { - return getStatusMessage(td.pd, templateContext, customStatusTemplate, parameter) + return getStatusMessage(templateContext, customStatusTemplate, parameter) } // HealthCheck address health check for trait diff --git a/pkg/cue/definition/template_test.go b/pkg/cue/definition/template_test.go index 4c5228704..9d13a949f 100644 --- a/pkg/cue/definition/template_test.go +++ b/pkg/cue/definition/template_test.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "github.com/kubevela/workflow/pkg/cue/packages" wfprocess "github.com/kubevela/workflow/pkg/cue/process" "github.com/oam-dev/kubevela/apis/types" @@ -245,7 +244,7 @@ output:{ AppRevisionName: "myapp-v1", ClusterVersion: types.ClusterVersion{Minor: "19+"}, }) - wt := NewWorkloadAbstractEngine("testWorkload", &packages.PackageDiscover{}) + wt := NewWorkloadAbstractEngine("testWorkload") err := wt.Complete(ctx, v.workloadTemplate, v.params) hasError := err != nil assert.Equal(t, v.hasCompileErr, hasError) @@ -1081,7 +1080,7 @@ parameter: { errs: [...string] }`, Namespace: "default", AppRevisionName: "myapp-v1", }) - wt := NewWorkloadAbstractEngine("-", &packages.PackageDiscover{}) + wt := NewWorkloadAbstractEngine("-") if err := wt.Complete(ctx, baseTemplate, map[string]interface{}{ "replicas": 2, "enemies": "enemies-data", @@ -1091,7 +1090,7 @@ parameter: { errs: [...string] }`, t.Error(err) return } - td := NewTraitAbstractEngine(v.traitName, &packages.PackageDiscover{}) + td := NewTraitAbstractEngine(v.traitName) r := require.New(t) err := td.Complete(ctx, v.traitTemplate, v.params) if v.hasCompileErr { @@ -1179,7 +1178,7 @@ outputs: service :{ }, } for k, v := range testcases { - wd := NewWorkloadAbstractEngine(k, &packages.PackageDiscover{}) + wd := NewWorkloadAbstractEngine(k) ctx := process.NewContext(process.ContextData{ AppName: "myapp", CompName: k, @@ -1264,7 +1263,7 @@ outputs: abc :{ }, } for k, v := range testcases { - td := NewTraitAbstractEngine(k, &packages.PackageDiscover{}) + td := NewTraitAbstractEngine(k) ctx := process.NewContext(process.ContextData{ AppName: "myapp", CompName: k, @@ -1476,7 +1475,7 @@ if len(context.outputs.ingress.status.loadBalancer.ingress) == 0 { }, } for message, ca := range cases { - gotMessage, err := getStatusMessage(&packages.PackageDiscover{}, ca.tpContext, ca.statusTemp, ca.parameter) + gotMessage, err := getStatusMessage(ca.tpContext, ca.statusTemp, ca.parameter) assert.NoError(t, err, message) assert.Equal(t, ca.expMessage, gotMessage, message) } @@ -1516,12 +1515,12 @@ func TestTraitPatchSingleOutput(t *testing.T) { Namespace: "default", AppRevisionName: "myapp-v1", }) - wt := NewWorkloadAbstractEngine("-", &packages.PackageDiscover{}) + wt := NewWorkloadAbstractEngine("-") if err := wt.Complete(ctx, baseTemplate, map[string]interface{}{}); err != nil { t.Error(err) return } - td := NewTraitAbstractEngine("single-patch", &packages.PackageDiscover{}) + td := NewTraitAbstractEngine("single-patch") r := require.New(t) err := td.Complete(ctx, traitTemplate, map[string]string{}) r.NoError(err) @@ -1560,7 +1559,7 @@ parameter: { }, } for k, v := range cases { - td := NewTraitAbstractEngine(k, &packages.PackageDiscover{}) + td := NewTraitAbstractEngine(k) err := td.Complete(v.ctx, v.template, v.params) assert.Error(t, err) assert.Contains(t, err.Error(), v.err) diff --git a/pkg/cue/script/template.go b/pkg/cue/script/template.go index b120ba1ad..d0f7e6bdd 100644 --- a/pkg/cue/script/template.go +++ b/pkg/cue/script/template.go @@ -22,14 +22,21 @@ import ( "fmt" "strings" + "github.com/getkin/kin-openapi/openapi3" "github.com/kubevela/pkg/cue/cuex" - cuelang "cuelang.org/go/cue" + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" + + "github.com/kubevela/workflow/pkg/cue/model/sets" "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/pkg/cue" + "github.com/oam-dev/kubevela/pkg/appfile" velacuex "github.com/oam-dev/kubevela/pkg/cue/cuex" + "github.com/oam-dev/kubevela/pkg/cue/process" + "github.com/oam-dev/kubevela/pkg/oam/util" + "github.com/oam-dev/kubevela/pkg/utils/common" ) // CUE the cue script with the template format @@ -45,68 +52,74 @@ import ( // ------------ type CUE string +// BaseTemplate include base info provided by KubeVela for CUE template +const BaseTemplate = ` +context: { + name: string + config?: [...{ + name: string + value: string + }] + ... +} +` + // BuildCUEScriptWithDefaultContext build a cue script instance from a byte array. func BuildCUEScriptWithDefaultContext(defaultContext []byte, content []byte) CUE { return CUE(content) + "\n" + CUE(defaultContext) } // ParseToValue parse the cue script to cue.Value -func (c CUE) ParseToValue() (*value.Value, error) { +func (c CUE) ParseToValue() (cue.Value, error) { // the cue script must be first, it could include the imports - template := string(c) + "\n" + cue.BaseTemplate - v, err := value.NewValue(template, nil, "") - if err != nil { - return nil, fmt.Errorf("fail to parse the template:%w", err) - } - return v, nil + template := string(c) + "\n" + BaseTemplate + v := cuecontext.New().CompileString(template) + return v, v.Err() } // ParseToValueWithCueX parse the cue script to cue.Value -func (c CUE) ParseToValueWithCueX() (cuelang.Value, error) { +func (c CUE) ParseToValueWithCueX(ctx context.Context) (cue.Value, error) { // the cue script must be first, it could include the imports - template := string(c) + "\n" + cue.BaseTemplate - val, err := velacuex.KubeVelaDefaultCompiler.Get().CompileStringWithOptions(context.Background(), template, cuex.DisableResolveProviderFunctions{}) + template := string(c) + "\n" + BaseTemplate + val, err := velacuex.ConfigCompiler.Get().CompileStringWithOptions(ctx, template, cuex.DisableResolveProviderFunctions{}) if err != nil { - return cuelang.Value{}, fmt.Errorf("failed to compile config template: %w", err) + return cue.Value{}, fmt.Errorf("failed to compile config template: %w", err) } return val, nil } // ParseToTemplateValue parse the cue script to cue.Value. It must include a valid template. -func (c CUE) ParseToTemplateValue() (*value.Value, error) { +func (c CUE) ParseToTemplateValue() (cue.Value, error) { // the cue script must be first, it could include the imports - template := string(c) + "\n" + cue.BaseTemplate - v, err := value.NewValue(template, nil, "") - if err != nil { - return nil, fmt.Errorf("fail to parse the template:%w", err) + template := string(c) + "\n" + BaseTemplate + v := cuecontext.New().CompileString(template) + if v.Err() != nil { + return cue.Value{}, fmt.Errorf("fail to parse the template:%w", v.Err()) } - _, err = v.LookupValue("template") - if err != nil { - if v.Error() != nil { - return nil, fmt.Errorf("the template cue is invalid:%w", v.Error()) - } - return nil, fmt.Errorf("the template cue must include the template field:%w", err) + res := v.LookupPath(value.FieldPath("template")) + if res.Err() != nil { + return cue.Value{}, fmt.Errorf("the template cue is invalid:%w", res.Err()) } - _, err = v.LookupValue("template", "parameter") - if err != nil { - return nil, fmt.Errorf("the template cue must include the template.parameter field") + parameter := v.LookupPath(value.FieldPath("template", "parameter")) + if parameter.Err() != nil { + return cue.Value{}, fmt.Errorf("the template cue must include the template.parameter field") } return v, nil } // ParseToTemplateValueWithCueX parse the cue script to cue.Value. It must include a valid template. -func (c CUE) ParseToTemplateValueWithCueX() (cuelang.Value, error) { - val, err := c.ParseToValueWithCueX() +func (c CUE) ParseToTemplateValueWithCueX(ctx context.Context) (cue.Value, error) { + val, err := c.ParseToValueWithCueX(ctx) if err != nil { - return cuelang.Value{}, err + return cue.Value{}, err } - templateValue := val.LookupPath(cuelang.ParsePath("template")) + templateValue := val.LookupPath(cue.ParsePath("template")) if !templateValue.Exists() { - return cuelang.Value{}, fmt.Errorf("the template cue must include the template field") + return cue.Value{}, fmt.Errorf("the template cue must include the template field") } - tmplParamValue := val.LookupPath(cuelang.ParsePath("template.parameter")) + tmplParamValue := val.LookupPath(cue.ParsePath("template.parameter")) if !tmplParamValue.Exists() { - return cuelang.Value{}, fmt.Errorf("the template cue must include the template.parameter field") + return cue.Value{}, fmt.Errorf("the template cue must include the template.parameter field") } return val, nil } @@ -114,87 +127,88 @@ func (c CUE) ParseToTemplateValueWithCueX() (cuelang.Value, error) { // MergeValues merge the input values to the cue script // The context variables could be referenced in all fields. // The parameter only could be referenced in the template area. -func (c CUE) MergeValues(context interface{}, properties map[string]interface{}) (*value.Value, error) { +func (c CUE) MergeValues(context interface{}, properties map[string]interface{}) (cue.Value, error) { parameterByte, err := json.Marshal(properties) if err != nil { - return nil, fmt.Errorf("the parameter is invalid %w", err) + return cue.Value{}, fmt.Errorf("the parameter is invalid %w", err) } contextByte, err := json.Marshal(context) if err != nil { - return nil, fmt.Errorf("the context is invalid %w", err) + return cue.Value{}, fmt.Errorf("the context is invalid %w", err) } var script = strings.Builder{} _, err = script.WriteString(string(c) + "\n") if err != nil { - return nil, err + return cue.Value{}, err } if properties != nil { _, err = script.WriteString(fmt.Sprintf("template: parameter: %s \n", string(parameterByte))) if err != nil { - return nil, err + return cue.Value{}, err } } if context != nil { _, err = script.WriteString(fmt.Sprintf("context: %s \n", string(contextByte))) if err != nil { - return nil, err + return cue.Value{}, err } } - mergeValue, err := value.NewValue(script.String(), nil, "") - if err != nil { - return nil, err + mergeValue := cuecontext.New().CompileString(script.String()) + if mergeValue.Err() != nil { + return cue.Value{}, mergeValue.Err() } - if err := mergeValue.CueValue().Validate(); err != nil { - return nil, fmt.Errorf("fail to validate the merged value %w", err) + if err := mergeValue.Validate(); err != nil { + return cue.Value{}, fmt.Errorf("fail to validate the merged value %w", err) } return mergeValue, nil } // RunAndOutput run the cue script and return the values of the specified field. // The output field must be under the template field. -func (c CUE) RunAndOutput(context interface{}, properties map[string]interface{}, outputField ...string) (*value.Value, error) { +func (c CUE) RunAndOutput(context interface{}, properties map[string]interface{}, outputField ...string) (cue.Value, error) { // Validate the properties if err := c.ValidateProperties(properties); err != nil { - return nil, err + return cue.Value{}, err } render, err := c.MergeValues(context, properties) if err != nil { - return nil, fmt.Errorf("fail to merge the properties to template %w", err) + return cue.Value{}, fmt.Errorf("fail to merge the properties to template %w", err) } - if render.Error() != nil { - return nil, fmt.Errorf("fail to merge the properties to template %w", render.Error()) + if render.Err() != nil { + return cue.Value{}, fmt.Errorf("fail to merge the properties to template %w", render.Err()) } if len(outputField) == 0 { outputField = []string{"template", "output"} } - return render.LookupValue(outputField...) + lookup := render.LookupPath(value.FieldPath(outputField...)) + return lookup, lookup.Err() } // RunAndOutputWithCueX run the cue script and return the values of the specified field. // The output field must be under the template field. -func (c CUE) RunAndOutputWithCueX(ctx context.Context, context interface{}, properties map[string]interface{}, outputField ...string) (cuelang.Value, error) { +func (c CUE) RunAndOutputWithCueX(ctx context.Context, context interface{}, properties map[string]interface{}, outputField ...string) (cue.Value, error) { // Validate the properties - if err := c.ValidatePropertiesWithCueX(properties); err != nil { - return cuelang.Value{}, err + if err := c.ValidatePropertiesWithCueX(ctx, properties); err != nil { + return cue.Value{}, err } contextOption := cuex.WithExtraData("context", context) parameterOption := cuex.WithExtraData("template.parameter", properties) - val, err := velacuex.KubeVelaDefaultCompiler.Get().CompileStringWithOptions(ctx, string(c), contextOption, parameterOption) + val, err := velacuex.ConfigCompiler.Get().CompileStringWithOptions(ctx, string(c), contextOption, parameterOption) if !val.Exists() { - return cuelang.Value{}, fmt.Errorf("failed to compile config template") + return cue.Value{}, fmt.Errorf("failed to compile config template") } if err != nil { - return cuelang.Value{}, fmt.Errorf("failed to compile config template: %w", err) + return cue.Value{}, fmt.Errorf("failed to compile config template: %w", err) } if Error(val) != nil { - return cuelang.Value{}, fmt.Errorf("failed to compile config template: %w", Error(val)) + return cue.Value{}, fmt.Errorf("failed to compile config template: %w", Error(val)) } if len(outputField) == 0 { return val, nil } - outputFieldVal := val.LookupPath(cuelang.ParsePath(strings.Join(outputField, "."))) + outputFieldVal := val.LookupPath(cue.ParsePath(strings.Join(outputField, "."))) if !outputFieldVal.Exists() { - return cuelang.Value{}, fmt.Errorf("failed to lookup value: var(path=%s) not exist", strings.Join(outputField, ".")) + return cue.Value{}, fmt.Errorf("failed to lookup value: var(path=%s) not exist", strings.Join(outputField, ".")) } return outputFieldVal, nil } @@ -205,11 +219,11 @@ func (c CUE) ValidateProperties(properties map[string]interface{}) error { if err != nil { return err } - parameter, err := template.LookupValue("template", "parameter") - if err != nil { - return err + parameter := template.LookupPath(value.FieldPath("template", "parameter")) + if parameter.Err() != nil { + return parameter.Err() } - parameterStr, err := parameter.String() + parameterStr, err := sets.ToString(parameter) if err != nil { return fmt.Errorf("the parameter is invalid %w", err) } @@ -220,14 +234,14 @@ func (c CUE) ValidateProperties(properties map[string]interface{}) error { newCue := strings.Builder{} newCue.WriteString(parameterStr + "\n") newCue.WriteString(string(propertiesByte) + "\n") - newValue, err := value.NewValue(newCue.String(), nil, "") - if err != nil { + newValue := cuecontext.New().CompileString(newCue.String()) + if newValue.Err() != nil { + return ConvertFieldError(newValue.Err()) + } + if err := newValue.Validate(); err != nil { return ConvertFieldError(err) } - if err := newValue.CueValue().Validate(); err != nil { - return ConvertFieldError(err) - } - _, err = newValue.CueValue().MarshalJSON() + _, err = newValue.MarshalJSON() if err != nil { return ConvertFieldError(err) } @@ -235,17 +249,17 @@ func (c CUE) ValidateProperties(properties map[string]interface{}) error { } // ValidatePropertiesWithCueX validate the input properties by the template -func (c CUE) ValidatePropertiesWithCueX(properties map[string]interface{}) error { - template, err := c.ParseToTemplateValueWithCueX() +func (c CUE) ValidatePropertiesWithCueX(ctx context.Context, properties map[string]interface{}) error { + template, err := c.ParseToTemplateValueWithCueX(ctx) if err != nil { return err } - paramPath := cuelang.ParsePath("template.parameter") + paramPath := cue.ParsePath("template.parameter") parameter := template.LookupPath(paramPath) if !parameter.Exists() { return fmt.Errorf("failed to lookup value: var(path=template.parameter) not exist") } - props := parameter.FillPath(cuelang.ParsePath(""), properties) + props := parameter.FillPath(cue.ParsePath(""), properties) if props.Err() != nil { return ConvertFieldError(props.Err()) } @@ -290,7 +304,7 @@ func ConvertFieldError(err error) error { } // Error return value's error information. -func Error(val cuelang.Value) error { +func Error(val cue.Value) error { if !val.Exists() { return errors.New("empty value") } @@ -298,7 +312,7 @@ func Error(val cuelang.Value) error { return err } var gerr error - val.Walk(func(value cuelang.Value) bool { + val.Walk(func(value cue.Value) bool { if err := value.Eval().Err(); err != nil { gerr = err return false @@ -307,3 +321,76 @@ func Error(val cuelang.Value) error { }, nil) return gerr } + +// ParsePropertiesToSchemaWithCueX parse the properties in cue script to the openapi schema +// Read the template.parameter field +func (c CUE) ParsePropertiesToSchemaWithCueX(ctx context.Context, templateFieldPath string) (*openapi3.Schema, error) { + val, err := c.ParseToValueWithCueX(ctx) + if err != nil { + return nil, err + } + var template cue.Value + if len(templateFieldPath) == 0 { + template = val + } else { + template = val.LookupPath(cue.ParsePath(templateFieldPath)) + if !template.Exists() { + return nil, fmt.Errorf("failed to lookup value: var(path=%s) not exist, cue script: %s", templateFieldPath, c) + } + } + data, err := common.GenOpenAPIWithCueX(template) + if err != nil { + return nil, err + } + schema, err := ConvertOpenAPISchema2SwaggerObject(data) + if err != nil { + return nil, err + } + FixOpenAPISchema("", schema) + return schema, nil +} + +// FIXME: double code with pkg/schema/schema.go to avoid import cycle + +// FixOpenAPISchema fixes tainted `description` filed, missing of title `field`. +func FixOpenAPISchema(name string, schema *openapi3.Schema) { + t := schema.Type + switch t { + case "object": + for k, v := range schema.Properties { + s := v.Value + FixOpenAPISchema(k, s) + } + case "array": + if schema.Items != nil { + FixOpenAPISchema("", schema.Items.Value) + } + } + if name != "" { + schema.Title = name + } + + description := schema.Description + if strings.Contains(description, appfile.UsageTag) { + description = strings.Split(description, appfile.UsageTag)[1] + } + if strings.Contains(description, appfile.ShortTag) { + description = strings.Split(description, appfile.ShortTag)[0] + description = strings.TrimSpace(description) + } + schema.Description = description +} + +// ConvertOpenAPISchema2SwaggerObject converts OpenAPI v2 JSON schema to Swagger Object +func ConvertOpenAPISchema2SwaggerObject(data []byte) (*openapi3.Schema, error) { + swagger, err := openapi3.NewLoader().LoadFromData(data) + if err != nil { + return nil, err + } + + schemaRef, ok := swagger.Components.Schemas[process.ParameterFieldName] + if !ok { + return nil, errors.New(util.ErrGenerateOpenAPIV2JSONSchemaForCapability) + } + return schemaRef.Value, nil +} diff --git a/pkg/cue/script/template_test.go b/pkg/cue/script/template_test.go index e5c2113b9..4cae1238f 100644 --- a/pkg/cue/script/template_test.go +++ b/pkg/cue/script/template_test.go @@ -22,6 +22,8 @@ import ( "strings" "testing" + "cuelang.org/go/cue" + "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/stretchr/testify/assert" ) @@ -127,22 +129,6 @@ parameter: { } ` -var withImport = ` -import ( - "vela/op" -) - -apply: op.#Apply & { - value: parameter.value - cluster: parameter.cluster -} -parameter: { - // +usage=Specify the value of the object - value: {...} - // +usage=Specify the cluster of the object - cluster: *"" | string -}` - var withTemplate = ` metadata: { name: "xxx" @@ -164,15 +150,15 @@ template: { func TestMergeValues(t *testing.T) { var cueScript = CUE(templateScript) - value, err := cueScript.MergeValues(nil, map[string]interface{}{ + v, err := cueScript.MergeValues(nil, map[string]interface{}{ "url": "hub.docker.com", "username": "name", }) assert.Equal(t, err, nil) - output, err := value.LookupValue("template", "output") - assert.Equal(t, err, nil) + output := v.LookupPath(cue.ParsePath("template.output")) + assert.Equal(t, output.Err(), nil) var data = map[string]interface{}{} - err = output.UnmarshalTo(&data) + err = value.UnmarshalTo(output, &data) assert.Equal(t, err, nil) assert.Equal(t, data["url"], "hub.docker.com") } @@ -190,7 +176,7 @@ func TestRunAndOutput(t *testing.T) { }) assert.Equal(t, err, nil) var data = map[string]interface{}{} - err = output.UnmarshalTo(&data) + err = value.UnmarshalTo(output, &data) assert.Equal(t, err, nil) assert.Equal(t, data["name"], "nnn") assert.Equal(t, data["namespace"], "ns") @@ -254,14 +240,15 @@ func TestValidateProperties(t *testing.T) { func TestValidatePropertiesWithCueX(t *testing.T) { var cueScript = CUE(templateScript) + ctx := context.Background() // miss the required parameter - err := cueScript.ValidatePropertiesWithCueX(map[string]interface{}{ + err := cueScript.ValidatePropertiesWithCueX(ctx, map[string]interface{}{ "url": "hub.docker.com", }) assert.Equal(t, err.(*ParameterError).Message, "This parameter is required") // wrong the parameter value type - err = cueScript.ValidatePropertiesWithCueX(map[string]interface{}{ + err = cueScript.ValidatePropertiesWithCueX(ctx, map[string]interface{}{ "url": 1, "username": "ddd", }) @@ -269,7 +256,7 @@ func TestValidatePropertiesWithCueX(t *testing.T) { assert.Equal(t, strings.Contains(err.(*ParameterError).Name, "url"), true) // wrong the parameter value - err = cueScript.ValidatePropertiesWithCueX(map[string]interface{}{ + err = cueScript.ValidatePropertiesWithCueX(ctx, map[string]interface{}{ "url": "ddd", "username": "ddd", }) @@ -277,7 +264,7 @@ func TestValidatePropertiesWithCueX(t *testing.T) { assert.Equal(t, strings.Contains(err.(*ParameterError).Name, "options"), true) // wrong the parameter value and no required value - err = cueScript.ValidatePropertiesWithCueX(map[string]interface{}{ + err = cueScript.ValidatePropertiesWithCueX(ctx, map[string]interface{}{ "url": "ddd", "username": "ddd", "options": "o3", @@ -287,31 +274,15 @@ func TestValidatePropertiesWithCueX(t *testing.T) { assert.Equal(t, strings.Contains(err.(*ParameterError).Message, "2 errors in empty disjunction"), true) } -func TestParsePropertiesToSchema(t *testing.T) { - cue := CUE(withPackage) - schema, err := cue.ParsePropertiesToSchema() - assert.Equal(t, err, nil) - assert.Equal(t, len(schema.Properties), 10) - - cue = CUE(withImport) - schema, err = cue.ParsePropertiesToSchema() - assert.Equal(t, err, nil) - assert.Equal(t, len(schema.Properties), 2) - - cue = CUE([]byte(withTemplate)) - schema, err = cue.ParsePropertiesToSchema("template") - assert.Equal(t, err, nil) - assert.Equal(t, len(schema.Properties), 2) -} - func TestParsePropertiesToSchemaWithCueX(t *testing.T) { cue := CUE([]byte(withPackage)) - schema, err := cue.ParsePropertiesToSchemaWithCueX("") + ctx := context.Background() + schema, err := cue.ParsePropertiesToSchemaWithCueX(ctx, "") assert.Equal(t, err, nil) assert.Equal(t, len(schema.Properties), 10) cue = CUE([]byte(withTemplate)) - schema, err = cue.ParsePropertiesToSchemaWithCueX("template") + schema, err = cue.ParsePropertiesToSchemaWithCueX(ctx, "template") assert.Equal(t, err, nil) assert.Equal(t, len(schema.Properties), 2) } diff --git a/pkg/definition/definition.go b/pkg/definition/definition.go index 55b44f6a6..63a3ca112 100644 --- a/pkg/definition/definition.go +++ b/pkg/definition/definition.go @@ -40,9 +40,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" + "github.com/kubevela/pkg/cue/cuex" "github.com/kubevela/workflow/pkg/cue/model/sets" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" @@ -50,6 +49,7 @@ import ( "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/filters" + "github.com/oam-dev/kubevela/pkg/workflow/providers" ) const ( @@ -379,8 +379,8 @@ func (def *Definition) FromYAML(data []byte) error { } // FromCUEString converts cue string into Definition -func (def *Definition) FromCUEString(cueString string, config *rest.Config) error { - cuectx := cuecontext.New() +func (def *Definition) FromCUEString(cueString string, _ *rest.Config) error { + // cuectx := cuecontext.New() f, err := parser.ParseFile("-", cueString, parser.ParseComments) if err != nil { return err @@ -430,23 +430,15 @@ func (def *Definition) FromCUEString(cueString string, config *rest.Config) erro return errors.Wrapf(err, "failed to encode template decls to string") } - inst := cuectx.CompileString(metadataString) - if inst.Err() != nil { - return inst.Err() + inst, err := providers.Compiler.Get().CompileStringWithOptions(context.Background(), metadataString, cuex.DisableResolveProviderFunctions{}) + if err != nil { + return err } templateString, err = formatCUEString(importString + templateString) if err != nil { return err } - var pd *packages.PackageDiscover - // validate template - if config != nil { - pd, err = packages.NewPackageDiscover(config) - if err != nil { - return err - } - } - if _, err = value.NewValue(templateString+"\n"+velacue.BaseTemplate, pd, ""); err != nil { + if _, err := providers.Compiler.Get().CompileStringWithOptions(context.Background(), templateString+"\n"+velacue.BaseTemplate, cuex.DisableResolveProviderFunctions{}); err != nil { return err } return def.FromCUE(&inst, templateString) diff --git a/pkg/definition/gen_sdk/gen_sdk.go b/pkg/definition/gen_sdk/gen_sdk.go index 52ea83d4f..a77525897 100644 --- a/pkg/definition/gen_sdk/gen_sdk.go +++ b/pkg/definition/gen_sdk/gen_sdk.go @@ -18,6 +18,7 @@ package gen_sdk import ( "bytes" + "context" "fmt" "io" "io/fs" @@ -33,8 +34,8 @@ import ( "cuelang.org/go/cue" "cuelang.org/go/encoding/openapi" "github.com/getkin/kin-openapi/openapi3" + "github.com/kubevela/pkg/cue/cuex" "github.com/kubevela/pkg/util/slices" - "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/rest" @@ -42,9 +43,9 @@ import ( velacue "github.com/oam-dev/kubevela/pkg/cue" "github.com/oam-dev/kubevela/pkg/definition" - "github.com/oam-dev/kubevela/pkg/stdlib" "github.com/oam-dev/kubevela/pkg/utils/common" "github.com/oam-dev/kubevela/pkg/utils/system" + "github.com/oam-dev/kubevela/pkg/workflow/providers" ) type byteHandler func([]byte) []byte @@ -126,7 +127,6 @@ func NewLanguageArgs(lang string, langArgs []string) (LanguageArgs, error) { if len(parts) != 2 { return nil, errors.Errorf("argument %s is not in the format of key=value", arg) } - fmt.Println("====availableArgs", availableArgs, langArgKey(parts[0])) if _, ok := availableArgs[langArgKey(parts[0])]; !ok { return nil, errors.Errorf("argument %s is not supported for language %s", parts[0], lang) } @@ -163,10 +163,6 @@ func (meta *GenMeta) Init(c common.Args, langArgs []string) (err error) { if err != nil { klog.Info("No kubeconfig found, skipping") } - err = stdlib.SetupBuiltinImports() - if err != nil { - return err - } if _, ok := SupportedLangs[meta.Lang]; !ok { return fmt.Errorf("language %s is not supported", meta.Lang) } @@ -320,7 +316,7 @@ func (meta *GenMeta) PrepareGeneratorAndTemplate() error { // Run will generally do two thing: // 1. Generate OpenAPI schema from cue files // 2. Generate code from OpenAPI schema -func (meta *GenMeta) Run() error { +func (meta *GenMeta) Run(ctx context.Context) error { g := NewModifiableGenerator(meta) if len(meta.cuePaths) == 0 { return nil @@ -333,7 +329,7 @@ func (meta *GenMeta) Run() error { if err != nil { return errors.Wrapf(err, "failed to read %s", cuePath) } - template, defName, defKind, err := g.GetDefinitionValue(cueBytes) + template, defName, defKind, err := g.GetDefinitionValue(ctx, cueBytes) if err != nil { return err } @@ -375,28 +371,29 @@ func (meta *GenMeta) SetDefinition(defName, defKind string) { } // GetDefinitionValue returns a value.Value definition name, definition kind from cue bytes -func (g *Generator) GetDefinitionValue(cueBytes []byte) (*value.Value, string, string, error) { +func (g *Generator) GetDefinitionValue(ctx context.Context, cueBytes []byte) (cue.Value, string, string, error) { g.def = definition.Definition{Unstructured: unstructured.Unstructured{}} if err := g.def.FromCUEString(string(cueBytes), g.meta.config); err != nil { - return nil, "", "", errors.Wrapf(err, "failed to parse CUE") + return cue.Value{}, "", "", errors.Wrapf(err, "failed to parse CUE") } templateString, _, err := unstructured.NestedString(g.def.Object, definition.DefinitionTemplateKeys...) if err != nil { - return nil, "", "", err + return cue.Value{}, "", "", err } if templateString == "" { - return nil, "", "", errors.New("definition doesn't include cue schematic") + return cue.Value{}, "", "", errors.New("definition doesn't include cue schematic") } - template, err := value.NewValue(templateString+velacue.BaseTemplate, nil, "") + + template, err := providers.Compiler.Get().CompileStringWithOptions(ctx, templateString+velacue.BaseTemplate, cuex.DisableResolveProviderFunctions{}) if err != nil { - return nil, "", "", err + return cue.Value{}, "", "", err } return template, g.def.GetName(), g.def.GetKind(), nil } // GenOpenAPISchema generates OpenAPI json schema from cue.Instance -func (g *Generator) GenOpenAPISchema(val *value.Value) error { +func (g *Generator) GenOpenAPISchema(val cue.Value) error { var err error defer func() { if r := recover(); r != nil { @@ -405,8 +402,8 @@ func (g *Generator) GenOpenAPISchema(val *value.Value) error { return } }() - if val.CueValue().Err() != nil { - return val.CueValue().Err() + if val.Err() != nil { + return val.Err() } paramOnlyVal, err := common.RefineParameterValue(val) if err != nil { diff --git a/pkg/definition/gen_sdk/gen_sdk_test.go b/pkg/definition/gen_sdk/gen_sdk_test.go index e67f83eb0..a9040ece1 100644 --- a/pkg/definition/gen_sdk/gen_sdk_test.go +++ b/pkg/definition/gen_sdk/gen_sdk_test.go @@ -17,6 +17,7 @@ limitations under the License. package gen_sdk import ( + "context" "os" "path/filepath" @@ -60,7 +61,7 @@ var _ = Describe("Test Generating SDK", func() { Expect(err).Should(BeNil()) err = meta.PrepareGeneratorAndTemplate() Expect(err).Should(BeNil()) - err = meta.Run() + err = meta.Run(context.Background()) Expect(err).Should(BeNil()) } It("Test generating SDK and init the scaffold", func() { diff --git a/pkg/resourcetracker/app.go b/pkg/resourcetracker/app.go index c755a8667..51396a2cf 100644 --- a/pkg/resourcetracker/app.go +++ b/pkg/resourcetracker/app.go @@ -156,7 +156,7 @@ func listApplicationResourceTrackers(ctx context.Context, cli client.Client, app } rtError := err if !kerrors.IsForbidden(err) && !kerrors.IsUnauthorized(err) { - return nil, err + return nil, errors.WithMessage(err, "failed to list ResourceTrackers") } appRts := &unstructured.UnstructuredList{} appRts.SetGroupVersionKind(applicationResourceTrackerGroupVersionKind) @@ -188,7 +188,7 @@ func ListApplicationResourceTrackers(ctx context.Context, cli client.Client, app metrics.ListResourceTrackerCounter.WithLabelValues("application").Inc() rts, err := listApplicationResourceTrackers(ctx, cli, app) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, errors.WithMessage(err, "failed to list ResourceTrackers") } for _, _rt := range rts { rt := _rt.DeepCopy() diff --git a/pkg/rollout/suit_test.go b/pkg/rollout/suit_test.go index 806adacda..930abd53e 100644 --- a/pkg/rollout/suit_test.go +++ b/pkg/rollout/suit_test.go @@ -43,8 +43,6 @@ import ( kruisev1alpha1 "github.com/openkruise/rollouts/api/v1alpha1" - "github.com/kubevela/workflow/pkg/cue/packages" - coreoam "github.com/oam-dev/kubevela/apis/core.oam.dev" // +kubebuilder:scaffold:imports ) @@ -53,7 +51,6 @@ var cfg *rest.Config var scheme *runtime.Scheme var k8sClient client.Client var testEnv *envtest.Environment -var pd *packages.PackageDiscover var testns string var dc *discovery.DiscoveryClient @@ -93,9 +90,6 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) Expect(dc).ShouldNot(BeNil()) - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(pd).ToNot(BeNil()) testns = "vela-system" Expect(k8sClient.Create(context.Background(), &v12.Namespace{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Namespace"}, ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/cue/script/schema.go b/pkg/schema/schema.go similarity index 65% rename from pkg/cue/script/schema.go rename to pkg/schema/schema.go index 39fab66e0..2016b1a77 100644 --- a/pkg/cue/script/schema.go +++ b/pkg/schema/schema.go @@ -1,5 +1,5 @@ /* -Copyright 2022 The KubeVela Authors. +Copyright 2024 The KubeVela Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,39 +14,54 @@ See the License for the specific language governing permissions and limitations under the License. */ -package script +package schema import ( + "context" "errors" "fmt" "strings" "cuelang.org/go/cue" - "github.com/getkin/kin-openapi/openapi3" - + "github.com/kubevela/pkg/cue/cuex" "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/oam-dev/kubevela/pkg/appfile" - "github.com/oam-dev/kubevela/pkg/cue/process" "github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/utils/common" + "github.com/oam-dev/kubevela/pkg/workflow/providers" ) +// BaseTemplate include base info provided by KubeVela for CUE template +const BaseTemplate = ` +context: { + name: string + config?: [...{ + name: string + value: string + }] + ... +} +` + +// ErrGenerateOpenAPIV2JSONSchemaForCapability is the error while generating OpenAPI v3 schema +const ErrGenerateOpenAPIV2JSONSchemaForCapability = "cannot generate OpenAPI v3 JSON schema for capability %s: %v" + // ParsePropertiesToSchema parse the properties in cue script to the openapi schema -// Read the template.parameter field -func (c CUE) ParsePropertiesToSchema(templateFieldPath ...string) (*openapi3.Schema, error) { - val, err := c.ParseToValue() +func ParsePropertiesToSchema(ctx context.Context, s string, templateFieldPath ...string) (*openapi3.Schema, error) { + t := s + "\n" + BaseTemplate + val, err := providers.Compiler.Get().CompileStringWithOptions(ctx, t, cuex.DisableResolveProviderFunctions{}) if err != nil { return nil, err } - var template *value.Value + var template cue.Value if len(templateFieldPath) == 0 { template = val } else { - template, err = val.LookupValue(templateFieldPath...) - if err != nil { - return nil, fmt.Errorf("%w cue script: %s", err, c) + template = val.LookupPath(value.FieldPath(templateFieldPath...)) + if template.Err() != nil { + return nil, fmt.Errorf("%w cue script: %s", template.Err(), s) } } data, err := common.GenOpenAPI(template) @@ -61,32 +76,18 @@ func (c CUE) ParsePropertiesToSchema(templateFieldPath ...string) (*openapi3.Sch return schema, nil } -// ParsePropertiesToSchemaWithCueX parse the properties in cue script to the openapi schema -// Read the template.parameter field -func (c CUE) ParsePropertiesToSchemaWithCueX(templateFieldPath string) (*openapi3.Schema, error) { - val, err := c.ParseToValueWithCueX() +// ConvertOpenAPISchema2SwaggerObject converts OpenAPI v2 JSON schema to Swagger Object +func ConvertOpenAPISchema2SwaggerObject(data []byte) (*openapi3.Schema, error) { + swagger, err := openapi3.NewLoader().LoadFromData(data) if err != nil { return nil, err } - var template cue.Value - if len(templateFieldPath) == 0 { - template = val - } else { - template = val.LookupPath(cue.ParsePath(templateFieldPath)) - if !template.Exists() { - return nil, fmt.Errorf("failed to lookup value: var(path=%s) not exist, cue script: %s", templateFieldPath, c) - } + + schemaRef, ok := swagger.Components.Schemas["parameter"] + if !ok { + return nil, errors.New(util.ErrGenerateOpenAPIV2JSONSchemaForCapability) } - data, err := common.GenOpenAPIWithCueX(template) - if err != nil { - return nil, err - } - schema, err := ConvertOpenAPISchema2SwaggerObject(data) - if err != nil { - return nil, err - } - FixOpenAPISchema("", schema) - return schema, nil + return schemaRef.Value, nil } // FixOpenAPISchema fixes tainted `description` filed, missing of title `field`. @@ -117,17 +118,3 @@ func FixOpenAPISchema(name string, schema *openapi3.Schema) { } schema.Description = description } - -// ConvertOpenAPISchema2SwaggerObject converts OpenAPI v2 JSON schema to Swagger Object -func ConvertOpenAPISchema2SwaggerObject(data []byte) (*openapi3.Schema, error) { - swagger, err := openapi3.NewLoader().LoadFromData(data) - if err != nil { - return nil, err - } - - schemaRef, ok := swagger.Components.Schemas[process.ParameterFieldName] - if !ok { - return nil, errors.New(util.ErrGenerateOpenAPIV2JSONSchemaForCapability) - } - return schemaRef.Value, nil -} diff --git a/pkg/cue/script/schema_test.go b/pkg/schema/schema_test.go similarity index 99% rename from pkg/cue/script/schema_test.go rename to pkg/schema/schema_test.go index 9ac3c96d1..f4748cd41 100644 --- a/pkg/cue/script/schema_test.go +++ b/pkg/schema/schema_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package script +package schema import ( "os" diff --git a/pkg/cue/script/testdata/arrayWithoutItemsSchema.json b/pkg/schema/testdata/arrayWithoutItemsSchema.json similarity index 100% rename from pkg/cue/script/testdata/arrayWithoutItemsSchema.json rename to pkg/schema/testdata/arrayWithoutItemsSchema.json diff --git a/pkg/cue/script/testdata/arrayWithoutItemsSchemaFixed.json b/pkg/schema/testdata/arrayWithoutItemsSchemaFixed.json similarity index 100% rename from pkg/cue/script/testdata/arrayWithoutItemsSchemaFixed.json rename to pkg/schema/testdata/arrayWithoutItemsSchemaFixed.json diff --git a/pkg/cue/script/testdata/shortTagSchema.json b/pkg/schema/testdata/shortTagSchema.json similarity index 100% rename from pkg/cue/script/testdata/shortTagSchema.json rename to pkg/schema/testdata/shortTagSchema.json diff --git a/pkg/cue/script/testdata/shortTagSchemaFixed.json b/pkg/schema/testdata/shortTagSchemaFixed.json similarity index 100% rename from pkg/cue/script/testdata/shortTagSchemaFixed.json rename to pkg/schema/testdata/shortTagSchemaFixed.json diff --git a/pkg/cue/script/testdata/webservice.json b/pkg/schema/testdata/webservice.json similarity index 100% rename from pkg/cue/script/testdata/webservice.json rename to pkg/schema/testdata/webservice.json diff --git a/pkg/cue/script/testdata/webserviceFixed.json b/pkg/schema/testdata/webserviceFixed.json similarity index 100% rename from pkg/cue/script/testdata/webserviceFixed.json rename to pkg/schema/testdata/webserviceFixed.json diff --git a/pkg/stdlib/op.cue b/pkg/stdlib/op.cue deleted file mode 100644 index d62006200..000000000 --- a/pkg/stdlib/op.cue +++ /dev/null @@ -1,93 +0,0 @@ -#GetPlacementsFromTopologyPolicies: multicluster.#GetPlacementsFromTopologyPolicies - -#Deploy: multicluster.#Deploy - -#ApplyApplication: #Steps & { - load: oam.#LoadComponetsInOrder @step(1) - components: #Steps & { - for name, c in load.value { - "\(name)": oam.#ApplyComponent & { - value: c - } - } - } @step(2) -} - -// This operator will dispatch all the components in parallel when applying an application. -// Currently it works for Addon Observability to speed up the installation. It can also works for other applications, which -// needs to skip health check for components. -#ApplyApplicationInParallel: #Steps & { - load: oam.#LoadComponetsInOrder @step(1) - components: #Steps & { - for name, c in load.value { - "\(name)": oam.#ApplyComponent & { - value: c - waitHealthy: false - } - } - } @step(2) -} - -#ApplyComponent: oam.#ApplyComponent - -#RenderComponent: oam.#RenderComponent - -#ApplyComponentRemaining: #Steps & { - // exceptions specify the resources not to apply. - exceptions: [...string] - exceptions_: {for c in exceptions {"\(c)": true}} - component: string - - load: oam.#LoadComponets @step(1) - render: #Steps & { - rendered: oam.#RenderComponent & { - value: load.value[component] - } - comp: kube.#Apply & { - value: rendered.output - } - for name, c in rendered.outputs { - if exceptions_[name] == _|_ { - "\(name)": kube.#Apply & { - value: c - } - } - } - } @step(2) -} - -#ApplyRemaining: #Steps & { - // exceptions specify the resources not to apply. - exceptions: [...string] - exceptions_: {for c in exceptions {"\(c)": true}} - - load: oam.#LoadComponets @step(1) - components: #Steps & { - for name, c in load.value { - if exceptions_[name] == _|_ { - "\(name)": oam.#ApplyComponent & { - value: c - } - } - - } - } @step(2) -} - -#ApplyEnvBindApp: multicluster.#ApplyEnvBindApp - -#DeployCloudResource: terraform.#DeployCloudResource - -#ShareCloudResource: terraform.#ShareCloudResource - -#LoadPolicies: oam.#LoadPolicies - -#ListClusters: multicluster.#ListClusters - -#MakePlacementDecisions: multicluster.#MakePlacementDecisions - -#PatchApplication: multicluster.#PatchApplication - -#Load: oam.#LoadComponets - -#LoadInOrder: oam.#LoadComponetsInOrder diff --git a/pkg/stdlib/packages.go b/pkg/stdlib/packages.go deleted file mode 100644 index 9daccebda..000000000 --- a/pkg/stdlib/packages.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package stdlib - -import ( - "embed" - "fmt" - "strings" - - "github.com/kubevela/workflow/pkg/stdlib" -) - -var ( - //go:embed pkgs op.cue ql.cue - fs embed.FS -) - -// SetupBuiltinImports set up builtin imports -func SetupBuiltinImports() error { - pkgs, err := getPackages() - if err != nil { - return err - } - return stdlib.SetupBuiltinImports(pkgs) -} - -// getPackages get stdlib packages -func getPackages() (map[string]string, error) { - files, err := fs.ReadDir("pkgs") - if err != nil { - return nil, err - } - - opBytes, err := fs.ReadFile("op.cue") - if err != nil { - return nil, err - } - - qlBytes, err := fs.ReadFile("ql.cue") - if err != nil { - return nil, err - } - - opContent := string(opBytes) + "\n" - qlContent := string(qlBytes) + "\n" - for _, file := range files { - body, err := fs.ReadFile("pkgs/" + file.Name()) - if err != nil { - return nil, err - } - pkgContent := fmt.Sprintf("%s: {\n%s\n}\n", strings.TrimSuffix(file.Name(), ".cue"), string(body)) - opContent += pkgContent - if file.Name() == "kube.cue" || file.Name() == "query.cue" { - qlContent += pkgContent - } - } - - return map[string]string{ - "vela/op": opContent, - "vela/ql": qlContent, - }, nil -} diff --git a/pkg/stdlib/packages_test.go b/pkg/stdlib/packages_test.go deleted file mode 100644 index dac5d9b27..000000000 --- a/pkg/stdlib/packages_test.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package stdlib - -import ( - "testing" - - "cuelang.org/go/cue" - "cuelang.org/go/cue/build" - "cuelang.org/go/cue/cuecontext" - "cuelang.org/go/cue/parser" - "github.com/stretchr/testify/assert" - - "github.com/kubevela/workflow/pkg/stdlib" -) - -func TestGetPackages(t *testing.T) { - pkgs, err := getPackages() - assert.NoError(t, err) - cuectx := cuecontext.New() - for path, content := range pkgs { - file, err := parser.ParseFile(path, content) - assert.NoError(t, err) - _ = cuectx.BuildFile(file) - } - - file, err := parser.ParseFile("-", ` -import "vela/custom" -out: custom.context`) - assert.NoError(t, err) - builder := &build.Instance{} - err = builder.AddSyntax(file) - assert.NoError(t, err) - err = stdlib.AddImportsFor(builder, "context: id: \"xxx\"") - assert.NoError(t, err) - - inst := cuectx.BuildInstance(builder) - str, err := inst.LookupPath(cue.ParsePath("out.id")).String() - assert.NoError(t, err) - assert.Equal(t, str, "xxx") -} diff --git a/pkg/stdlib/pkgs/oam.cue b/pkg/stdlib/pkgs/oam.cue deleted file mode 100644 index a0c422329..000000000 --- a/pkg/stdlib/pkgs/oam.cue +++ /dev/null @@ -1,55 +0,0 @@ -#ApplyComponent: { - #provider: "oam" - #do: "component-apply" - - // +usage=The cluster to use - cluster: *"" | string - // +usage=The env to use - env: *"" | string - // +usage=The namespace to apply - namespace: *"" | string - // +usage=Whether to wait healthy of the applied component - waitHealthy: *true | bool - // +usage=The value of the component resource - value: {...} - // +usage=The patcher that will be applied to the resource, you can define the strategy of list merge through comments. Reference doc here: https://kubevela.io/docs/platform-engineers/traits/patch-trait#patch-in-workflow-step - patch?: {...} - ... -} - -#RenderComponent: { - #provider: "oam" - #do: "component-render" - cluster: *"" | string - env: *"" | string - namespace: *"" | string - value: {...} - patch?: {...} - output?: {...} - outputs?: {...} - ... -} - -#LoadComponets: { - #provider: "oam" - #do: "load" - - // +usage=If specify `app`, use specified application to load its component resources otherwise use current application - app?: string - // +usage=The value of the components will be filled in this field after the action is executed, you can use value[componentName] to refer a specified component - value?: {...} - ... -} - -#LoadPolicies: { - #provider: "oam" - #do: "load-policies" - value?: {...} - ... -} - -#LoadComponetsInOrder: { - #provider: "oam" - #do: "load-comps-in-order" - ... -} diff --git a/pkg/stdlib/ql.cue b/pkg/stdlib/ql.cue deleted file mode 100644 index 72d11adff..000000000 --- a/pkg/stdlib/ql.cue +++ /dev/null @@ -1,81 +0,0 @@ -#Read: { - #do: "read" - #provider: "kube" - - // +usage=The cluster to use - cluster: *"" | string - // +usage=The resource to read, this field will be filled with the resource read from the cluster after the action is executed - value?: {...} - ... -} - -#List: { - #do: "list" - #provider: "kube" - - // +usage=The cluster to use - cluster: *"" | string - // +usage=The resource to list - resource: { - // +usage=The api version of the resource - apiVersion: string - // +usage=The kind of the resource - kind: string - } - // +usage=The filter to list the resources - filter?: { - // +usage=The namespace to list the resources - namespace?: *"" | string - // +usage=The label selector to filter the resources - matchingLabels?: {...} - } - // +usage=The listed resources will be filled in this field after the action is executed - list?: {...} - ... -} - -#Delete: { - #do: "delete" - #provider: "kube" - - // +usage=The cluster to use - cluster: *"" | string - // +usage=The resource to delete - value: { - // +usage=The api version of the resource - apiVersion: string - // +usage=The kind of the resource - kind: string - // +usage=The metadata of the resource - metadata: { - // +usage=The name of the resource - name?: string - // +usage=The namespace of the resource - namespace: *"default" | string - } - } - // +usage=The filter to delete the resources - filter?: { - // +usage=The namespace to list the resources - namespace?: string - // +usage=The label selector to filter the resources - matchingLabels?: {...} - } - ... -} - -#ListResourcesInApp: query.#ListResourcesInApp - -#ListAppliedResources: query.#ListAppliedResources - -#CollectPods: query.#CollectPods - -#CollectServices: query.#CollectServices - -#SearchEvents: query.#SearchEvents - -#CollectLogsInPod: query.#CollectLogsInPod - -#CollectServiceEndpoints: query.#CollectServiceEndpoints - -#GetApplicationTree: query.#GetApplicationTree diff --git a/pkg/utils/apply/apply.go b/pkg/utils/apply/apply.go index 9a7f6a80a..2697adaeb 100644 --- a/pkg/utils/apply/apply.go +++ b/pkg/utils/apply/apply.go @@ -21,8 +21,10 @@ import ( "encoding/json" "fmt" "reflect" + "strconv" "github.com/crossplane/crossplane-runtime/pkg/fieldpath" + "github.com/mitchellh/hashstructure/v2" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -38,7 +40,6 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/controller/utils" "github.com/oam-dev/kubevela/pkg/features" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" @@ -259,11 +260,22 @@ func (a *APIApplicator) Apply(ctx context.Context, desired client.Object, ao ... } } +// ComputeSpecHash computes the hash value of a k8s resource spec +func ComputeSpecHash(spec interface{}) (string, error) { + // compute a hash value of any resource spec + specHash, err := hashstructure.Hash(spec, hashstructure.FormatV2, nil) + if err != nil { + return "", err + } + specHashLabel := strconv.FormatUint(specHash, 16) + return specHashLabel, nil +} + func generateRenderHash(desired client.Object) (string, error) { if desired == nil { return "", nil } - desiredHash, err := utils.ComputeSpecHash(desired) + desiredHash, err := ComputeSpecHash(desired) if err != nil { return "", errors.Wrap(err, "compute desired hash") } diff --git a/pkg/utils/common/args.go b/pkg/utils/common/args.go index 55a57f38d..b938d8c02 100644 --- a/pkg/utils/common/args.go +++ b/pkg/utils/common/args.go @@ -17,8 +17,6 @@ limitations under the License. package common import ( - "fmt" - pkgmulticluster "github.com/kubevela/pkg/multicluster" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -30,8 +28,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/client/fake" - - "github.com/kubevela/workflow/pkg/cue/packages" ) // Args is args for controller-runtime client @@ -40,7 +36,6 @@ type Args struct { rawConfig *api.Config Schema *runtime.Scheme client client.Client - pd *packages.PackageDiscover dc *discovery.DiscoveryClient } @@ -139,24 +134,6 @@ func (a *Args) GetFakeClient(defs []*unstructured.Unstructured) (client.Client, return fake.NewClientBuilder().WithObjects(objs...).WithScheme(a.Schema).Build(), nil } -// GetPackageDiscover get PackageDiscover client if exist, create if not exist. -func (a *Args) GetPackageDiscover() (*packages.PackageDiscover, error) { - if a.config == nil { - if err := a.SetConfig(nil); err != nil { - return nil, err - } - } - if a.pd != nil { - return a.pd, nil - } - pd, err := packages.NewPackageDiscover(a.config) - if err != nil { - return nil, fmt.Errorf("failed to create CRD discovery for CUE package client %w", err) - } - a.pd = pd - return pd, nil -} - // GetDiscoveryClient return a discovery client from cli args func (a *Args) GetDiscoveryClient() (*discovery.DiscoveryClient, error) { if a.dc != nil { diff --git a/pkg/utils/common/common.go b/pkg/utils/common/common.go index 125fc5ee4..e4207f975 100644 --- a/pkg/utils/common/common.go +++ b/pkg/utils/common/common.go @@ -57,8 +57,6 @@ import ( gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" "sigs.k8s.io/yaml" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" clustergatewayapi "github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1" terraformapiv1 "github.com/oam-dev/terraform-controller/api/v1beta1" terraformapi "github.com/oam-dev/terraform-controller/api/v1beta2" @@ -202,21 +200,18 @@ func HTTPGetKubernetesObjects(ctx context.Context, url string) ([]*unstructured. } // GetCUEParameterValue converts definitions to cue format -func GetCUEParameterValue(cueStr string, pd *packages.PackageDiscover) (cue.Value, error) { - template, err := value.NewValue(cueStr+velacue.BaseTemplate, pd, "") - if err != nil { - return cue.Value{}, err - } - val, err := template.LookupValue(process.ParameterFieldName) - if err != nil || !val.CueValue().Exists() { +func GetCUEParameterValue(cueStr string) (cue.Value, error) { + template := cuecontext.New().CompileString(cueStr + velacue.BaseTemplate) + val := template.LookupPath(cue.ParsePath(process.ParameterFieldName)) + if !val.Exists() { return cue.Value{}, velacue.ErrParameterNotExist } - return val.CueValue(), nil + return val, nil } // GenOpenAPI generates OpenAPI json schema from cue.Instance -func GenOpenAPI(val *value.Value) (b []byte, err error) { +func GenOpenAPI(val cue.Value) (b []byte, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("invalid cue definition to generate open api: %v", r) @@ -224,8 +219,8 @@ func GenOpenAPI(val *value.Value) (b []byte, err error) { return } }() - if val.CueValue().Err() != nil { - return nil, val.CueValue().Err() + if val.Err() != nil { + return nil, val.Err() } paramOnlyVal, err := RefineParameterValue(val) if err != nil { @@ -265,23 +260,17 @@ func GenOpenAPIWithCueX(val cue.Value) (b []byte, err error) { } // RefineParameterValue refines cue value to merely include `parameter` identifier -func RefineParameterValue(val *value.Value) (cue.Value, error) { - defaultValue := cuecontext.New().CompileString("#parameter: {}") +func RefineParameterValue(val cue.Value) (cue.Value, error) { + cuectx := val.Context() + defaultValue := cuectx.CompileString("#parameter: {}") parameterPath := cue.MakePath(cue.Def(process.ParameterFieldName)) - v, err := val.MakeValue("{}") - if err != nil { - return defaultValue, err - } - paramVal, err := val.LookupValue(process.ParameterFieldName) - if err != nil { - // nolint:nilerr - return defaultValue, nil - } - switch k := paramVal.CueValue().IncompleteKind(); k { + v := cuectx.CompileString("{}") + paramVal := val.LookupPath(cue.ParsePath(process.ParameterFieldName)) + switch k := paramVal.IncompleteKind(); k { case cue.BottomKind: return defaultValue, nil default: - paramOnlyVal := v.CueValue().FillPath(parameterPath, paramVal.CueValue()) + paramOnlyVal := v.FillPath(parameterPath, paramVal) return paramOnlyVal, nil } } diff --git a/pkg/utils/common/common_test.go b/pkg/utils/common/common_test.go index d83cbfeda..247c40da3 100644 --- a/pkg/utils/common/common_test.go +++ b/pkg/utils/common/common_test.go @@ -33,7 +33,6 @@ import ( "cuelang.org/go/cue/load" "github.com/crossplane/crossplane-runtime/pkg/test" "github.com/google/go-cmp/cmp" - "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/stretchr/testify/assert" ) @@ -252,7 +251,7 @@ output: { for name, tc := range cases { t.Run(name, func(t *testing.T) { - _, err := GetCUEParameterValue(tc.cueStr, nil) + _, err := GetCUEParameterValue(tc.cueStr) if tc.want.err != nil { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { t.Errorf("\n%s\nGenOpenAPIFromFile(...): -want error, +got error:\n%s", tc.reason, diff) @@ -291,7 +290,7 @@ func TestGetCUEParameterValue4RareCases(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - _, err := GetCUEParameterValue(tc.cueStr, nil) + _, err := GetCUEParameterValue(tc.cueStr) if diff := cmp.Diff(tc.want.errMsg, err.Error(), test.EquateConditions()); diff != "" { t.Errorf("\n%s\nGenOpenAPIFromFile(...): -want error, +got error:\n%s", tc.reason, diff) } @@ -334,8 +333,7 @@ func TestGenOpenAPI(t *testing.T) { instances := load.Instances([]string{filepath.FromSlash(tc.fileName)}, &load.Config{ Dir: "testdata", }) - val, err := value.NewValueWithInstance(instances[0], nil, "") - assert.NoError(t, err) + val := cuecontext.New().BuildInstance(instances[0]) got, err := GenOpenAPI(val) if tc.want.err != nil { if diff := cmp.Diff(tc.want.err, errors.New(err.Error()), test.EquateErrors()); diff != "" { @@ -509,10 +507,10 @@ patch: { label: parameter.x } }` - val, err := value.NewValue(s, nil, "") - assert.NoError(t, err) - assert.NoError(t, val.CueValue().Err()) - _, err = RefineParameterValue(val) + cuectx := cuecontext.New() + val := cuectx.CompileString(s) + assert.NoError(t, val.Err()) + _, err := RefineParameterValue(val) assert.NoError(t, err) // test #parameter not exist but parameter exists s = `parameter: { @@ -521,18 +519,17 @@ patch: { y: string } }` - val, err = value.NewValue(s, nil, "") - assert.NoError(t, err) - assert.NoError(t, val.CueValue().Err()) + val = cuectx.CompileString(s) + assert.NoError(t, val.Err()) assert.NoError(t, err) _, err = RefineParameterValue(val) assert.NoError(t, err) // test #parameter as int s = `parameter: #parameter #parameter: int` - val, err = value.NewValue(s, nil, "") + val = cuectx.CompileString(s) assert.NoError(t, err) - assert.NoError(t, val.CueValue().Err()) + assert.NoError(t, val.Err()) _, err = RefineParameterValue(val) assert.NoError(t, err) } diff --git a/pkg/utils/k8s.go b/pkg/utils/k8s.go index 98c154135..a37165dd4 100644 --- a/pkg/utils/k8s.go +++ b/pkg/utils/k8s.go @@ -50,7 +50,7 @@ import ( "github.com/oam-dev/kubevela/pkg/oam/util" velaerr "github.com/oam-dev/kubevela/pkg/utils/errors" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" ) // MutateOption defines the function pattern for mutate diff --git a/pkg/velaql/providers/query/types/health_status.go b/pkg/utils/types/health_status.go similarity index 100% rename from pkg/velaql/providers/query/types/health_status.go rename to pkg/utils/types/health_status.go diff --git a/pkg/velaql/providers/query/types/type.go b/pkg/utils/types/ql_type.go similarity index 81% rename from pkg/velaql/providers/query/types/type.go rename to pkg/utils/types/ql_type.go index 6022c090d..42a79e4e4 100644 --- a/pkg/velaql/providers/query/types/type.go +++ b/pkg/utils/types/ql_type.go @@ -123,18 +123,18 @@ type AppliedResource struct { // ResourceTreeNode is the tree node of every resource type ResourceTreeNode struct { - Cluster string `json:"cluster"` - APIVersion string `json:"apiVersion,omitempty"` - Kind string `json:"kind"` - Namespace string `json:"namespace,omitempty"` - Name string `json:"name,omitempty"` - UID types.UID `json:"uid,omitempty"` - HealthStatus HealthStatus `json:"healthStatus,omitempty"` - DeletionTimestamp time.Time `json:"deletionTimestamp,omitempty"` - CreationTimestamp time.Time `json:"creationTimestamp,omitempty"` - LeafNodes []*ResourceTreeNode `json:"leafNodes,omitempty"` - AdditionalInfo map[string]interface{} `json:"additionalInfo,omitempty"` - Object unstructured.Unstructured `json:"-"` + Cluster string `json:"cluster"` + APIVersion string `json:"apiVersion,omitempty"` + Kind string `json:"kind"` + Namespace string `json:"namespace,omitempty"` + Name string `json:"name,omitempty"` + UID types.UID `json:"uid,omitempty"` + HealthStatus HealthStatus `json:"healthStatus,omitempty"` + DeletionTimestamp time.Time `json:"deletionTimestamp,omitempty"` + CreationTimestamp time.Time `json:"creationTimestamp,omitempty"` + LeafNodes []*ResourceTreeNode `json:"leafNodes,omitempty"` + AdditionalInfo map[string]interface{} `json:"additionalInfo,omitempty"` + Object *unstructured.Unstructured `json:"-"` } // GroupVersionKind returns the stored group, version, and kind from AppliedResource @@ -149,12 +149,12 @@ func (rtn *ResourceTreeNode) GroupVersionKind() schema.GroupVersionKind { // ResourceItem the resource base info struct type ResourceItem struct { - Cluster string `json:"cluster"` - Workload Workload `json:"workload"` - Component string `json:"component"` - Object unstructured.Unstructured `json:"object"` - PublishVersion string `json:"publishVersion"` - DeployVersion string `json:"deployVersion"` + Cluster string `json:"cluster"` + Workload Workload `json:"workload"` + Component string `json:"component"` + Object *unstructured.Unstructured `json:"object"` + PublishVersion string `json:"publishVersion"` + DeployVersion string `json:"deployVersion"` } // Workload workload resource base info diff --git a/pkg/velaql/context.go b/pkg/velaql/context.go deleted file mode 100644 index 4f32df91a..000000000 --- a/pkg/velaql/context.go +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright 2021. The KubeVela Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package velaql - -import ( - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" -) - -// NewViewContext new view context -func NewViewContext() (wfContext.Context, error) { - viewContext := &ViewContext{} - var err error - viewContext.vars, err = value.NewValue("", nil, "") - return viewContext, err -} - -// ViewContext is view context -type ViewContext struct { - vars *value.Value -} - -// GetVar get variable from workflow context. -func (c ViewContext) GetVar(paths ...string) (*value.Value, error) { - return c.vars.LookupValue(paths...) -} - -// SetVar set variable to workflow context. -func (c ViewContext) SetVar(v *value.Value, paths ...string) error { - str, err := v.String() - if err != nil { - return errors.WithMessage(err, "compile var") - } - if err := c.vars.FillRaw(str, paths...); err != nil { - return err - } - return c.vars.Error() -} - -// GetStore get configmap of workflow context. -func (c ViewContext) GetStore() *corev1.ConfigMap { - return nil -} - -// GetMutableValue get mutable data from workflow context. -func (c ViewContext) GetMutableValue(_ ...string) string { - return "" -} - -// SetMutableValue set mutable data in workflow context config map. -func (c ViewContext) SetMutableValue(_ string, _ ...string) { -} - -// IncreaseCountValueInMemory increase count in workflow context memory store. -func (c ViewContext) IncreaseCountValueInMemory(_ ...string) int { - return 0 -} - -// SetValueInMemory set data in workflow context memory store. -func (c ViewContext) SetValueInMemory(_ interface{}, _ ...string) { -} - -// GetValueInMemory get data in workflow context memory store. -func (c ViewContext) GetValueInMemory(_ ...string) (interface{}, bool) { - return "", true -} - -// DeleteValueInMemory delete data in workflow context memory store. -func (c ViewContext) DeleteValueInMemory(_ ...string) { -} - -// DeleteMutableValue delete mutable data in workflow context. -func (c ViewContext) DeleteMutableValue(_ ...string) { -} - -// Commit the workflow context and persist it's content. -func (c ViewContext) Commit() error { - return errors.New("not support func Commit") -} - -// MakeParameter make 'value' with string -func (c ViewContext) MakeParameter(parameter string) (*value.Value, error) { - if parameter == "" { - parameter = "{}" - } - - return c.vars.MakeValue(parameter) -} - -// StoreRef return the store reference of workflow context. -func (c ViewContext) StoreRef() *corev1.ObjectReference { - return nil -} diff --git a/pkg/velaql/parse.go b/pkg/velaql/parse.go index c8d0dfab2..9aca35adb 100644 --- a/pkg/velaql/parse.go +++ b/pkg/velaql/parse.go @@ -17,15 +17,16 @@ package velaql import ( + "context" "regexp" "strconv" "strings" + "cuelang.org/go/cue" "github.com/pkg/errors" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/pkg/utils" + "github.com/oam-dev/kubevela/pkg/workflow/providers" ) // QueryView contains query data @@ -98,20 +99,19 @@ func ParseVelaQL(ql string) (QueryView, error) { } // ParseVelaQLFromPath will parse a velaQL file path to QueryView -func ParseVelaQLFromPath(velaQLViewPath string) (*QueryView, error) { +func ParseVelaQLFromPath(ctx context.Context, velaQLViewPath string) (*QueryView, error) { body, err := utils.ReadRemoteOrLocalPath(velaQLViewPath, false) if err != nil { return nil, errors.Errorf("read view file from %s: %v", velaQLViewPath, err) } - - val, err := value.NewValue(string(body), nil, "") + val, err := providers.Compiler.Get().CompileString(ctx, string(body)) if err != nil { - return nil, errors.Errorf("new value for view: %v", err) + return nil, errors.Errorf("error when parsing view: %v", err) } var expStr string - exp, err := val.LookupValue(KeyWordExport) - if err == nil { + exp := val.LookupPath(cue.ParsePath(KeyWordExport)) + if exp.Err() == nil { expStr, err = exp.String() if err != nil { expStr = DefaultExportValue diff --git a/pkg/velaql/providers/query/utils_test.go b/pkg/velaql/providers/query/utils_test.go deleted file mode 100644 index 0e169aae0..000000000 --- a/pkg/velaql/providers/query/utils_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright 2022. The KubeVela Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package query - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - - "github.com/kubevela/workflow/pkg/cue/model/value" -) - -func TestFillQueryResult(t *testing.T) { - testcases := map[string]struct { - queryRes interface{} - json string - }{ - "test fill query result which contains *unstructured.Unstructured": { - queryRes: []Resource{ - { - Cluster: "local", - Component: "web", - Revision: "v1", - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "spec": map[string]interface{}{ - "template": map[string]interface{}{ - "metadata": map[string]interface{}{ - "creationTimestamp": nil, - }, - }, - }, - }, - }, - }, - { - Cluster: "ap-southeast-1", - Component: "web", - Revision: "v2", - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": map[string]interface{}{ - "creationTimestamp": "2022-05-25T12:07:02Z", - }, - }, - }, - }, - }, - json: `{"list":[{"cluster":"local","component":"web","revision":"v1","object":{"apiVersion":"apps/v1","kind":"Deployment","spec":{"template":{"metadata":{"creationTimestamp":null}}}}},{"cluster":"ap-southeast-1","component":"web","revision":"v2","object":{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"creationTimestamp":"2022-05-25T12:07:02Z"}}}]}`, - }, - } - - for name, testcase := range testcases { - t.Run(name, func(t *testing.T) { - value, err := value.NewValue("", nil, "") - assert.NoError(t, err) - err = fillQueryResult(value, testcase.queryRes, "list") - assert.NoError(t, err) - json, err := value.CueValue().MarshalJSON() - assert.NoError(t, err) - assert.Equal(t, testcase.json, string(json)) - }) - } -} diff --git a/pkg/velaql/suite_test.go b/pkg/velaql/suite_test.go index e22d01f33..f07a6f5e2 100644 --- a/pkg/velaql/suite_test.go +++ b/pkg/velaql/suite_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "github.com/kubevela/pkg/util/singleton" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -31,8 +32,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -52,7 +51,9 @@ var _ = BeforeSuite(func() { ControlPlaneStartTimeout: time.Minute * 3, ControlPlaneStopTimeout: time.Minute, UseExistingCluster: pointer.Bool(false), - CRDDirectoryPaths: []string{"../../charts/vela-core/crds"}, + CRDDirectoryPaths: []string{ + "../../../../charts/vela-core/crds", + }, } By("start kube test env") @@ -67,11 +68,9 @@ var _ = BeforeSuite(func() { Expect(err).Should(BeNil()) Expect(k8sClient).ToNot(BeNil()) By("new kube client success") + singleton.KubeClient.Set(k8sClient) - pd, err := packages.NewPackageDiscover(cfg) - Expect(err).To(BeNil()) - - viewHandler = NewViewHandler(k8sClient, cfg, pd) + viewHandler = NewViewHandler(k8sClient, cfg) ctx := context.Background() ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}} diff --git a/pkg/velaql/view.go b/pkg/velaql/view.go index ec711d263..a01ec791b 100644 --- a/pkg/velaql/view.go +++ b/pkg/velaql/view.go @@ -20,9 +20,10 @@ import ( "context" "encoding/json" "fmt" - "os" "strings" + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -30,37 +31,23 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" pkgtypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/rest" - "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - monitorContext "github.com/kubevela/pkg/monitor/context" + "github.com/kubevela/pkg/cue/cuex" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" + "github.com/kubevela/workflow/pkg/cue/model/sets" "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/kubevela/workflow/pkg/executor" - "github.com/kubevela/workflow/pkg/generator" - "github.com/kubevela/workflow/pkg/providers" - "github.com/kubevela/workflow/pkg/providers/kube" - wfTypes "github.com/kubevela/workflow/pkg/types" + providertypes "github.com/kubevela/workflow/pkg/providers/types" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/cue/process" "github.com/oam-dev/kubevela/pkg/multicluster" - oamutil "github.com/oam-dev/kubevela/pkg/oam/util" - "github.com/oam-dev/kubevela/pkg/stdlib" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/apply" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" + "github.com/oam-dev/kubevela/pkg/workflow/providers" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" "github.com/oam-dev/kubevela/pkg/workflow/template" ) -func init() { - if err := stdlib.SetupBuiltinImports(); err != nil { - klog.ErrorS(err, "Unable to set up builtin imports on package initialization") - os.Exit(1) - } -} - const ( qlNs = "vela-system" @@ -72,94 +59,50 @@ const ( type ViewHandler struct { cli client.Client cfg *rest.Config - viewTask workflowv1alpha1.WorkflowStep - pd *packages.PackageDiscover namespace string } // NewViewHandler new view handler -func NewViewHandler(cli client.Client, cfg *rest.Config, pd *packages.PackageDiscover) *ViewHandler { +func NewViewHandler(cli client.Client, cfg *rest.Config) *ViewHandler { return &ViewHandler{ cli: cli, cfg: cfg, - pd: pd, namespace: qlNs, } } // QueryView generate view step -func (handler *ViewHandler) QueryView(ctx context.Context, qv QueryView) (*value.Value, error) { +func (handler *ViewHandler) QueryView(ctx context.Context, qv QueryView) (cue.Value, error) { outputsTemplate := fmt.Sprintf(OutputsTemplate, qv.Export, qv.Export) queryKey := QueryParameterKey{} if err := json.Unmarshal([]byte(outputsTemplate), &queryKey); err != nil { - return nil, errors.Errorf("unmarhsal query template: %v", err) + return cue.Value{}, errors.Errorf("unmarhsal query template: %v", err) } - - handler.viewTask = workflowv1alpha1.WorkflowStep{ - WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{ - Name: fmt.Sprintf("%s-%s", qv.View, qv.Export), - Type: qv.View, - Properties: oamutil.Object2RawExtension(qv.Parameter), - Outputs: queryKey.Outputs, - }, - } - - instance := &wfTypes.WorkflowInstance{ - WorkflowMeta: wfTypes.WorkflowMeta{ - Name: fmt.Sprintf("%s-%s", qv.View, qv.Export), - }, - Steps: []workflowv1alpha1.WorkflowStep{ - { - WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{ - Name: fmt.Sprintf("%s-%s", qv.View, qv.Export), - Type: qv.View, - Properties: oamutil.Object2RawExtension(qv.Parameter), - Outputs: queryKey.Outputs, - }, - }, - }, - } - executor.InitializeWorkflowInstance(instance) - handlerProviders := providers.NewProviders() - kube.Install(handlerProviders, handler.cli, nil, &kube.Handlers{ - Apply: handler.dispatch, - Delete: handler.delete, + ctx = oamprovidertypes.WithRuntimeParams(ctx, oamprovidertypes.RuntimeParams{ + KubeClient: handler.cli, + KubeConfig: handler.cfg, + KubeHandlers: &providertypes.KubeHandlers{Apply: handler.dispatch, Delete: handler.delete}, }) - query.Install(handlerProviders, handler.cli, handler.cfg) loader := template.NewViewTemplateLoader(handler.cli, handler.namespace) if len(strings.Split(qv.View, "\n")) > 2 { loader = &template.EchoLoader{} } - logCtx := monitorContext.NewTraceContext(ctx, "").AddTag("velaql") - runners, err := generator.GenerateRunners(logCtx, instance, wfTypes.StepGeneratorOptions{ - Providers: handlerProviders, - PackageDiscover: handler.pd, - ProcessCtx: process.NewContext(process.ContextData{}), - TemplateLoader: loader, - Client: handler.cli, - LogLevel: 3, - }) + temp, err := loader.LoadTemplate(ctx, qv.View) if err != nil { - return nil, err + return cue.Value{}, fmt.Errorf("failed to load query templates: %w", err) } - - viewCtx, err := NewViewContext() + v, err := providers.Compiler.Get().CompileStringWithOptions(ctx, temp, cuex.WithExtraData("parameter", qv.Parameter)) if err != nil { - return nil, errors.Errorf("new view context: %v", err) + return cue.Value{}, fmt.Errorf("failed to compile query: %w", err) } - for _, runner := range runners { - status, _, err := runner.Run(viewCtx, &wfTypes.TaskRunOptions{}) - if err != nil { - return nil, errors.Errorf("run query view: %v", err) - } - if string(status.Phase) != ViewTaskPhaseSucceeded { - return nil, errors.Errorf("failed to query the view %s %s", status.Message, status.Reason) - } + res := v.LookupPath(value.FieldPath(qv.Export)) + if !res.Exists() { + return cuecontext.New().CompileString("null"), nil } - return viewCtx.GetVar(qv.Export) + return res, res.Err() } -func (handler *ViewHandler) dispatch(ctx context.Context, cluster string, _ string, manifests ...*unstructured.Unstructured) error { +func (handler *ViewHandler) dispatch(ctx context.Context, _ client.Client, cluster string, _ string, manifests ...*unstructured.Unstructured) error { ctx = multicluster.ContextWithClusterName(ctx, cluster) applicator := apply.NewAPIApplicator(handler.cli) for _, manifest := range manifests { @@ -170,30 +113,32 @@ func (handler *ViewHandler) dispatch(ctx context.Context, cluster string, _ stri return nil } -func (handler *ViewHandler) delete(ctx context.Context, _ string, _ string, manifest *unstructured.Unstructured) error { +func (handler *ViewHandler) delete(ctx context.Context, _ client.Client, _ string, _ string, manifest *unstructured.Unstructured) error { return handler.cli.Delete(ctx, manifest) } // ValidateView makes sure the cue provided can use as view. // // For now, we only check 1. cue is valid 2. `status` or `view` field exists -func ValidateView(viewStr string) error { - val, err := value.NewValue(viewStr, nil, "") +func ValidateView(ctx context.Context, viewStr string) error { + val, err := providers.Compiler.Get().CompileStringWithOptions(ctx, viewStr, cuex.DisableResolveProviderFunctions{}) if err != nil { return errors.Errorf("error when parsing view: %v", err) } // Make sure `status` or `export` field exists - vStatus, errStatus := val.LookupValue(DefaultExportValue) - vExport, errExport := val.LookupValue(KeyWordExport) + vStatus := val.LookupPath(cue.ParsePath(DefaultExportValue)) + errStatus := vStatus.Err() + vExport := val.LookupPath(cue.ParsePath(KeyWordExport)) + errExport := vExport.Err() if errStatus != nil && errExport != nil { return errors.Errorf("no `status` or `export` field found in view: %v, %v", errStatus, errExport) } if errStatus == nil { - _, errStatus = vStatus.String() + _, errStatus = sets.ToString(vStatus) } if errExport == nil { - _, errExport = vExport.String() + _, errExport = sets.ToString(vExport) } if errStatus != nil && errExport != nil { return errors.Errorf("connot get string from` status` or `export`: %v, %v", errStatus, errExport) @@ -204,8 +149,8 @@ func ValidateView(viewStr string) error { // ParseViewIntoConfigMap parses a CUE string (representing a view) into a ConfigMap // ready to be stored into etcd. -func ParseViewIntoConfigMap(viewStr, name string) (*v1.ConfigMap, error) { - err := ValidateView(viewStr) +func ParseViewIntoConfigMap(ctx context.Context, viewStr, name string) (*v1.ConfigMap, error) { + err := ValidateView(ctx, viewStr) if err != nil { return nil, err } @@ -239,7 +184,7 @@ func StoreViewFromFile(ctx context.Context, c client.Client, path, viewName stri return errors.Errorf("cannot load cue file: %v", err) } - cm, err := ParseViewIntoConfigMap(string(content), viewName) + cm, err := ParseViewIntoConfigMap(ctx, string(content), viewName) if err != nil { return err } diff --git a/pkg/velaql/view_test.go b/pkg/velaql/view_test.go index b44a28c78..3c6f6c717 100644 --- a/pkg/velaql/view_test.go +++ b/pkg/velaql/view_test.go @@ -24,6 +24,8 @@ import ( "testing" "time" + "github.com/kubevela/workflow/pkg/cue/model/sets" + "github.com/kubevela/workflow/pkg/cue/model/value" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/stretchr/testify/assert" @@ -53,7 +55,7 @@ var _ = Describe("Test VelaQL View", func() { Expect(err).Should(BeNil()) podStatus := corev1.PodStatus{} - Expect(queryValue.UnmarshalTo(&podStatus)).Should(BeNil()) + Expect(value.UnmarshalTo(queryValue, &podStatus)).Should(BeNil()) }) It("Test query view with wrong request", func() { @@ -69,7 +71,7 @@ var _ = Describe("Test VelaQL View", func() { Expect(err).ShouldNot(HaveOccurred()) v, err := viewHandler.QueryView(context.Background(), query) Expect(err).ShouldNot(HaveOccurred()) - s, err := v.String() + s, err := sets.ToString(v) Expect(err).ShouldNot(HaveOccurred()) Expect(s).Should(Equal("null\n")) @@ -136,7 +138,7 @@ export: something`, }, } for _, c := range cases { - cm, err := ParseViewIntoConfigMap(c.cueStr, "name") + cm, err := ParseViewIntoConfigMap(context.Background(), c.cueStr, "name") assert.Equal(t, c.succeed, err == nil, err) if err == nil { assert.Equal(t, c.cueStr, cm.Data["template"]) diff --git a/pkg/webhook/core.oam.dev/v1beta1/application/suite_test.go b/pkg/webhook/core.oam.dev/v1beta1/application/suite_test.go index 0bd539784..d7ffec450 100644 --- a/pkg/webhook/core.oam.dev/v1beta1/application/suite_test.go +++ b/pkg/webhook/core.oam.dev/v1beta1/application/suite_test.go @@ -38,8 +38,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/yaml" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" // +kubebuilder:scaffold:imports ) @@ -52,7 +50,6 @@ var k8sClient client.Client var testEnv *envtest.Environment var testScheme = runtime.NewScheme() var decoder *admission.Decoder -var pd *packages.PackageDiscover var ctx = context.Background() var handler *ValidatingHandler @@ -94,11 +91,7 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(pd).ToNot(BeNil()) - - handler = &ValidatingHandler{pd: pd} + handler = &ValidatingHandler{} decoder, err = admission.NewDecoder(testScheme) Expect(err).Should(BeNil()) diff --git a/pkg/webhook/core.oam.dev/v1beta1/application/validating_handler.go b/pkg/webhook/core.oam.dev/v1beta1/application/validating_handler.go index e94d75b1e..9b3951d0c 100644 --- a/pkg/webhook/core.oam.dev/v1beta1/application/validating_handler.go +++ b/pkg/webhook/core.oam.dev/v1beta1/application/validating_handler.go @@ -29,8 +29,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev" "github.com/oam-dev/kubevela/pkg/oam/util" @@ -40,7 +38,6 @@ var _ admission.Handler = &ValidatingHandler{} // ValidatingHandler handles application type ValidatingHandler struct { - pd *packages.PackageDiscover Client client.Client // Decoder decodes objects Decoder *admission.Decoder @@ -116,7 +113,7 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a } // RegisterValidatingHandler will register application validate handler to the webhook -func RegisterValidatingHandler(mgr manager.Manager, args controller.Args) { +func RegisterValidatingHandler(mgr manager.Manager, _ controller.Args) { server := mgr.GetWebhookServer() - server.Register("/validating-core-oam-dev-v1beta1-applications", &webhook.Admission{Handler: &ValidatingHandler{pd: args.PackageDiscover}}) + server.Register("/validating-core-oam-dev-v1beta1-applications", &webhook.Admission{Handler: &ValidatingHandler{}}) } diff --git a/pkg/webhook/core.oam.dev/v1beta1/application/validation.go b/pkg/webhook/core.oam.dev/v1beta1/application/validation.go index bb191b7d0..79f6e29e7 100644 --- a/pkg/webhook/core.oam.dev/v1beta1/application/validation.go +++ b/pkg/webhook/core.oam.dev/v1beta1/application/validation.go @@ -90,7 +90,7 @@ func (h *ValidatingHandler) ValidateComponents(ctx context.Context, app *v1beta1 var componentErrs field.ErrorList // try to generate an app file cli := &appRevBypassCacheClient{Client: h.Client} - appParser := appfile.NewApplicationParser(cli, h.pd) + appParser := appfile.NewApplicationParser(cli) af, err := appParser.GenerateAppFile(ctx, app) if err != nil { diff --git a/pkg/workflow/operation/operation.go b/pkg/workflow/operation/operation.go index 5b78f973e..399e8d85c 100644 --- a/pkg/workflow/operation/operation.go +++ b/pkg/workflow/operation/operation.go @@ -437,7 +437,7 @@ func (wo appWorkflowStepOperator) Restart(ctx context.Context, step string) erro return err } } - appParser := appfile.NewApplicationParser(wo.cli, nil) + appParser := appfile.NewApplicationParser(wo.cli) appFile, err := appParser.GenerateAppFile(ctx, app) if err != nil { return fmt.Errorf("failed to parse appfile: %w", err) diff --git a/pkg/workflow/operation/suit_test.go b/pkg/workflow/operation/suit_test.go index feff3e51d..712da8923 100644 --- a/pkg/workflow/operation/suit_test.go +++ b/pkg/workflow/operation/suit_test.go @@ -42,8 +42,6 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "github.com/kubevela/workflow/pkg/cue/packages" - coreoam "github.com/oam-dev/kubevela/apis/core.oam.dev" // +kubebuilder:scaffold:imports ) @@ -52,7 +50,6 @@ var cfg *rest.Config var scheme *runtime.Scheme var k8sClient client.Client var testEnv *envtest.Environment -var pd *packages.PackageDiscover var testns string var dc *discovery.DiscoveryClient @@ -92,9 +89,6 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) Expect(dc).ShouldNot(BeNil()) - pd, err = packages.NewPackageDiscover(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(pd).ToNot(BeNil()) testns = "vela-system" Expect(k8sClient.Create(context.Background(), &v12.Namespace{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Namespace"}, ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/workflow/providers/compiler.go b/pkg/workflow/providers/compiler.go new file mode 100644 index 000000000..8bce14144 --- /dev/null +++ b/pkg/workflow/providers/compiler.go @@ -0,0 +1,46 @@ +/* +Copyright 2022 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package providers + +import ( + "github.com/kubevela/pkg/cue/cuex" + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" + "github.com/kubevela/pkg/util/runtime" + "github.com/kubevela/pkg/util/singleton" + + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" +) + +const ( + // LegacyProviderName is the name of legacy provider + LegacyProviderName = "op" + // ConfigProviderName is the name of config provider + ConfigProviderName = "config" + // QLProviderName is the name of ql provider + QLProviderName = "ql" +) + +// Compiler is the workflow default compiler +var Compiler = singleton.NewSingletonE[*cuex.Compiler](func() (*cuex.Compiler, error) { + return cuex.NewCompilerWithInternalPackages( + // legacy packages + runtime.Must(cuexruntime.NewInternalPackage(LegacyProviderName, legacy.GetLegacyTemplate(), legacy.GetLegacyProviders())), + // runtime.Must(cuexruntime.NewInternalPackage(ConfigProviderName, config.GetTemplate(), config.GetProviders())), + runtime.Must(cuexruntime.NewInternalPackage(QLProviderName, query.GetTemplate(), query.GetProviders())), + ), nil +}) diff --git a/pkg/workflow/providers/legacy/config/config.cue b/pkg/workflow/providers/legacy/config/config.cue new file mode 100644 index 000000000..25ae5e846 --- /dev/null +++ b/pkg/workflow/providers/legacy/config/config.cue @@ -0,0 +1,42 @@ +// config.cue + +#Create: { + #do: "create" + #provider: "config" + + name: string + namespace: string + template?: string + config: { + ... + } +} + +#Delete: { + #do: "delete" + #provider: "config" + + name: string + namespace: string +} + +#Read: { + #do: "read" + #provider: "config" + + name: string + namespace: string + + config: {...} +} + +#List: { + #do: "list" + #provider: "config" + + // Must query with the template + template: string + namespace: string + + configs: [...{...}] +} diff --git a/pkg/workflow/providers/legacy/config/config.go b/pkg/workflow/providers/legacy/config/config.go new file mode 100644 index 000000000..9c832ee1b --- /dev/null +++ b/pkg/workflow/providers/legacy/config/config.go @@ -0,0 +1,156 @@ +/* +Copyright 2023 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "context" + _ "embed" + "errors" + "strings" + + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" + + "github.com/oam-dev/kubevela/pkg/config" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" +) + +const ( + // ProviderName is provider name + ProviderName = "config" +) + +// ErrRequestInvalid means the request is invalid +var ErrRequestInvalid = errors.New("the request is in valid") + +// CreateConfigProperties the request body for creating a config +type CreateConfigProperties struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + Template string `json:"template,omitempty"` + Config map[string]interface{} `json:"config"` +} + +// CreateParams is the create params +type CreateParams = oamprovidertypes.OAMParams[CreateConfigProperties] + +// CreateConfig creates a config +func CreateConfig(ctx context.Context, params *CreateParams) (*any, error) { + ccp := params.Params + name := ccp.Template + namespace := "vela-system" + if strings.Contains(ccp.Template, "/") { + namespacedName := strings.SplitN(ccp.Template, "/", 2) + namespace = namespacedName[0] + name = namespacedName[1] + } + factory := params.ConfigFactory + configItem, err := factory.ParseConfig(ctx, config.NamespacedName{ + Name: name, + Namespace: namespace, + }, config.Metadata{ + NamespacedName: config.NamespacedName{ + Name: ccp.Name, + Namespace: ccp.Namespace, + }, + Properties: ccp.Config, + }) + if err != nil { + return nil, err + } + return nil, factory.CreateOrUpdateConfig(ctx, configItem, ccp.Namespace) +} + +// ReadResult is the read result +type ReadResult struct { + Config map[string]any `json:"config"` +} + +// ReadConfig reads the config +func ReadConfig(ctx context.Context, params *oamprovidertypes.OAMParams[config.NamespacedName]) (*ReadResult, error) { + nn := params.Params + factory := params.ConfigFactory + content, err := factory.ReadConfig(ctx, nn.Namespace, nn.Name) + if err != nil { + return nil, err + } + return &ReadResult{Config: content}, nil +} + +// ListVars is the list vars +type ListVars struct { + Namespace string `json:"namespace"` + Template string `json:"template"` +} + +// ListResult is the list result +type ListResult struct { + Configs []map[string]any `json:"configs"` +} + +// ListConfig lists the config +func ListConfig(ctx context.Context, params *oamprovidertypes.OAMParams[ListVars]) (*ListResult, error) { + template := params.Params.Template + namespace := params.Params.Namespace + if template == "" || namespace == "" { + return nil, ErrRequestInvalid + } + + if strings.Contains(template, "/") { + namespacedName := strings.SplitN(template, "/", 2) + template = namespacedName[1] + } + factory := params.ConfigFactory + configs, err := factory.ListConfigs(ctx, namespace, template, "", false) + if err != nil { + return nil, err + } + var contents = []map[string]interface{}{} + for _, c := range configs { + contents = append(contents, map[string]interface{}{ + "name": c.Name, + "alias": c.Alias, + "description": c.Description, + "config": c.Properties, + }) + } + return &ListResult{Configs: contents}, nil +} + +// DeleteConfig deletes a config +func DeleteConfig(ctx context.Context, params *oamprovidertypes.OAMParams[config.NamespacedName]) (*any, error) { + nn := params.Params + factory := params.ConfigFactory + return nil, factory.DeleteConfig(ctx, nn.Namespace, nn.Name) +} + +//go:embed config.cue +var template string + +// GetTemplate returns the cue template. +func GetTemplate() string { + return template +} + +// GetProviders returns the cue providers. +func GetProviders() map[string]cuexruntime.ProviderFn { + return map[string]cuexruntime.ProviderFn{ + "create-config": oamprovidertypes.OAMGenericProviderFn[CreateConfigProperties, any](CreateConfig), + "read-config": oamprovidertypes.OAMGenericProviderFn[config.NamespacedName, ReadResult](ReadConfig), + "list-config": oamprovidertypes.OAMGenericProviderFn[ListVars, ListResult](ListConfig), + "delete-config": oamprovidertypes.OAMGenericProviderFn[config.NamespacedName, any](DeleteConfig), + } +} diff --git a/pkg/config/provider/provider_test.go b/pkg/workflow/providers/legacy/config/config_test.go similarity index 67% rename from pkg/config/provider/provider_test.go rename to pkg/workflow/providers/legacy/config/config_test.go index e8da21ad1..623283532 100644 --- a/pkg/config/provider/provider_test.go +++ b/pkg/workflow/providers/legacy/config/config_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package provider +package config import ( "context" @@ -22,7 +22,6 @@ import ( "testing" "time" - monitorContext "github.com/kubevela/pkg/monitor/context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/runtime" @@ -32,17 +31,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/pkg/config" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment var scheme = runtime.NewScheme() -var p *provider +var factory config.Factory func TestProvider(t *testing.T) { RegisterFailHandler(Fail) @@ -68,9 +65,7 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) - p = &provider{ - factory: config.NewConfigFactory(k8sClient), - } + factory = config.NewConfigFactory(k8sClient) }) var _ = AfterSuite(func() { @@ -82,78 +77,94 @@ var _ = AfterSuite(func() { var _ = Describe("Test the config provider", func() { It("test creating a config", func() { - mCtx := monitorContext.NewTraceContext(context.Background(), "") - v, err := value.NewValue(` - name: "hub-kubevela" - namespace: "default" - template: "default/test-image-registry" - config: { - registry: "hub.kubevela.net" + ctx := context.Background() + params := &CreateParams{ + Params: CreateConfigProperties{ + Name: "hub-kubevela", + Namespace: "default", + Template: "default/test-image-registry", + Config: map[string]interface{}{ + "registry": "hub.kubevela.net", + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + ConfigFactory: factory, + }, } - `, nil, "") - Expect(err).ToNot(HaveOccurred()) - err = p.Create(mCtx, new(wfContext.WorkflowContext), v, nil) + _, err := CreateConfig(ctx, params) Expect(strings.Contains(err.Error(), "the template does not exist")).Should(BeTrue()) - template, err := p.factory.ParseTemplate("test-image-registry", []byte(templateContent)) + template, err := factory.ParseTemplate(ctx, "test-image-registry", []byte(templateContent)) Expect(err).ToNot(HaveOccurred()) - Expect(p.factory.CreateOrUpdateConfigTemplate(context.TODO(), "default", template)).ToNot(HaveOccurred()) + Expect(factory.CreateOrUpdateConfigTemplate(ctx, "default", template)).ToNot(HaveOccurred()) - Expect(p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred()) + _, err = CreateConfig(ctx, params) + Expect(err).ToNot(HaveOccurred()) }) It("test creating a config without the template", func() { - mCtx := monitorContext.NewTraceContext(context.Background(), "") - v, err := value.NewValue(` - name: "www-kubevela" - namespace: "default" - config: { - url: "kubevela.net" + params := &CreateParams{ + Params: CreateConfigProperties{ + Name: "www-kubevela", + Namespace: "default", + Config: map[string]interface{}{ + "url": "kubevela.net", + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + ConfigFactory: factory, + }, } - `, nil, "") + _, err := CreateConfig(context.Background(), params) Expect(err).ToNot(HaveOccurred()) - Expect(p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred()) }) It("test listing the config", func() { - mCtx := monitorContext.NewTraceContext(context.Background(), "") - v, err := value.NewValue(` - namespace: "default" - template: "test-image-registry" - `, nil, "") + ctx := context.Background() + res, err := ListConfig(ctx, &oamprovidertypes.OAMParams[ListVars]{ + Params: ListVars{ + Namespace: "default", + Template: "test-image-registry", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + ConfigFactory: factory, + }, + }) Expect(err).ToNot(HaveOccurred()) - Expect(p.List(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred()) - configs, err := v.LookupValue("configs") - Expect(err).ToNot(HaveOccurred()) - var contents []map[string]interface{} - Expect(configs.UnmarshalTo(&contents)).ToNot(HaveOccurred()) + contents := res.Configs Expect(len(contents)).To(Equal(1)) Expect(contents[0]["config"].(map[string]interface{})["registry"]).To(Equal("hub.kubevela.net")) }) It("test reading the config", func() { - mCtx := monitorContext.NewTraceContext(context.Background(), "") - v, err := value.NewValue(` - name: "hub-kubevela" - namespace: "default" - `, nil, "") + ctx := context.Background() + res, err := ReadConfig(ctx, &oamprovidertypes.OAMParams[config.NamespacedName]{ + Params: config.NamespacedName{ + Namespace: "default", + Name: "hub-kubevela", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + ConfigFactory: factory, + }, + }) Expect(err).ToNot(HaveOccurred()) - Expect(p.Read(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred()) - registry, err := v.GetString("config", "registry") - Expect(err).ToNot(HaveOccurred()) - Expect(registry).To(Equal("hub.kubevela.net")) + Expect(res.Config["registry"]).To(Equal("hub.kubevela.net")) }) It("test deleting the config", func() { - mCtx := monitorContext.NewTraceContext(context.Background(), "") - v, err := value.NewValue(` - name: "hub-kubevela" - namespace: "default" - `, nil, "") + ctx := context.Background() + _, err := DeleteConfig(ctx, &oamprovidertypes.OAMParams[config.NamespacedName]{ + Params: config.NamespacedName{ + Namespace: "default", + Name: "hub-kubevela", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + ConfigFactory: factory, + }, + }) Expect(err).ToNot(HaveOccurred()) - Expect(p.Delete(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred()) - configs, err := p.factory.ListConfigs(context.Background(), "default", "", "", false) + configs, err := factory.ListConfigs(context.Background(), "default", "", "", false) Expect(err).ToNot(HaveOccurred()) Expect(len(configs)).To(Equal(1)) Expect(configs[0].Properties["url"]).To(Equal("kubevela.net")) diff --git a/pkg/workflow/providers/legacy/legacy.go b/pkg/workflow/providers/legacy/legacy.go new file mode 100644 index 000000000..21a2ef238 --- /dev/null +++ b/pkg/workflow/providers/legacy/legacy.go @@ -0,0 +1,59 @@ +/* +Copyright 2024 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package legacy + +import ( + "strings" + + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" + + wflegacy "github.com/kubevela/workflow/pkg/providers/legacy" + + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/multicluster" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/oam" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/terraform" +) + +// nolint:unparam +func registerProviders(providers map[string]cuexruntime.ProviderFn, new map[string]cuexruntime.ProviderFn) map[string]cuexruntime.ProviderFn { + for k, v := range new { + providers[k] = v + } + return providers +} + +// GetLegacyProviders get legacy providers +func GetLegacyProviders() map[string]cuexruntime.ProviderFn { + providers := make(map[string]cuexruntime.ProviderFn, 0) + registerProviders(providers, multicluster.GetProviders()) + registerProviders(providers, oam.GetProviders()) + registerProviders(providers, terraform.GetProviders()) + registerProviders(providers, wflegacy.GetLegacyProviders()) + + return providers +} + +// GetLegacyTemplate get legacy template +func GetLegacyTemplate() string { + return strings.Join([]string{ + multicluster.GetTemplate(), + oam.GetTemplate(), + terraform.GetTemplate(), + wflegacy.GetLegacyTemplate(), + }, + "\n") +} diff --git a/pkg/workflow/providers/multicluster/deploy.go b/pkg/workflow/providers/legacy/multicluster/deploy.go similarity index 82% rename from pkg/workflow/providers/multicluster/deploy.go rename to pkg/workflow/providers/legacy/multicluster/deploy.go index 688f06534..38ca9fb52 100644 --- a/pkg/workflow/providers/multicluster/deploy.go +++ b/pkg/workflow/providers/legacy/multicluster/deploy.go @@ -22,6 +22,8 @@ import ( "strings" "sync" + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" pkgmaps "github.com/kubevela/pkg/util/maps" "github.com/kubevela/pkg/util/slices" "github.com/kubevela/workflow/pkg/cue/model/value" @@ -30,6 +32,8 @@ import ( "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" + workflowerrors "github.com/kubevela/workflow/pkg/errors" + "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" @@ -41,7 +45,7 @@ import ( "github.com/oam-dev/kubevela/pkg/resourcekeeper" "github.com/oam-dev/kubevela/pkg/utils" velaerrors "github.com/oam-dev/kubevela/pkg/utils/errors" - oamProvider "github.com/oam-dev/kubevela/pkg/workflow/providers/oam" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) // DeployParameter is the parameter of deploy workflow step @@ -62,7 +66,7 @@ type DeployWorkflowStepExecutor interface { } // NewDeployWorkflowStepExecutor . -func NewDeployWorkflowStepExecutor(cli client.Client, af *appfile.Appfile, apply oamProvider.ComponentApply, healthCheck oamProvider.ComponentHealthCheck, renderer oamProvider.WorkloadRenderer, parameter DeployParameter) DeployWorkflowStepExecutor { +func NewDeployWorkflowStepExecutor(cli client.Client, af *appfile.Appfile, apply oamprovidertypes.ComponentApply, healthCheck oamprovidertypes.ComponentHealthCheck, renderer oamprovidertypes.WorkloadRender, parameter DeployParameter) DeployWorkflowStepExecutor { return &deployWorkflowStepExecutor{ cli: cli, af: af, @@ -76,9 +80,9 @@ func NewDeployWorkflowStepExecutor(cli client.Client, af *appfile.Appfile, apply type deployWorkflowStepExecutor struct { cli client.Client af *appfile.Appfile - apply oamProvider.ComponentApply - healthCheck oamProvider.ComponentHealthCheck - renderer oamProvider.WorkloadRenderer + apply oamprovidertypes.ComponentApply + healthCheck oamprovidertypes.ComponentHealthCheck + renderer oamprovidertypes.WorkloadRender parameter DeployParameter } @@ -135,7 +139,7 @@ func fillInlinePolicyNames(policies []v1beta1.AppPolicy) []v1beta1.AppPolicy { return policies } -func loadComponents(ctx context.Context, renderer oamProvider.WorkloadRenderer, cli client.Client, af *appfile.Appfile, components []common.ApplicationComponent, ignoreTerraformComponent bool) ([]common.ApplicationComponent, error) { +func loadComponents(ctx context.Context, render oamprovidertypes.WorkloadRender, cli client.Client, af *appfile.Appfile, components []common.ApplicationComponent, ignoreTerraformComponent bool) ([]common.ApplicationComponent, error) { var loadedComponents []common.ApplicationComponent for _, comp := range components { loadedComp, err := af.LoadDynamicComponent(ctx, cli, comp.DeepCopy()) @@ -143,7 +147,7 @@ func loadComponents(ctx context.Context, renderer oamProvider.WorkloadRenderer, return nil, err } if ignoreTerraformComponent { - wl, err := renderer(ctx, comp) + wl, err := render(ctx, comp) if err != nil { return nil, errors.Wrapf(err, "failed to render component into workload") } @@ -176,7 +180,7 @@ func overrideConfiguration(policies []v1beta1.AppPolicy, components []common.App return components, nil } -type valueBuilder func(s string) (*value.Value, error) +type valueBuilder func(s string) cue.Value type applyTask struct { component common.ApplicationComponent @@ -196,36 +200,32 @@ func (t *applyTask) varKeyWithoutReplica(v string) string { return fmt.Sprintf("%s/%s/%s/%s", t.placement.Cluster, t.placement.Namespace, "", v) } -func (t *applyTask) getVar(from string, cache *pkgmaps.SyncMap[string, *value.Value]) *value.Value { +func (t *applyTask) getVar(from string, cache *pkgmaps.SyncMap[string, cue.Value]) cue.Value { key := t.varKey(from) keyWithNoReplica := t.varKeyWithoutReplica(from) - var val *value.Value + var val cue.Value var ok bool if val, ok = cache.Get(key); !ok { if val, ok = cache.Get(keyWithNoReplica); !ok { - return nil + return cue.Value{} } } return val } -func (t *applyTask) fillInputs(inputs *pkgmaps.SyncMap[string, *value.Value], build valueBuilder) error { +func (t *applyTask) fillInputs(inputs *pkgmaps.SyncMap[string, cue.Value], build valueBuilder) error { if len(t.component.Inputs) == 0 { return nil } - - x, err := component2Value(t.component, build) - if err != nil { - return err - } - + var err error + x := component2Value(t.component, build) for _, input := range t.component.Inputs { - var inputVal *value.Value - if inputVal = t.getVar(input.From, inputs); inputVal == nil { + var inputVal cue.Value + if inputVal = t.getVar(input.From, inputs); inputVal == (cue.Value{}) { return fmt.Errorf("input %s is not ready", input) } - err = x.FillValueByScript(inputVal, fieldPathToComponent(input.ParameterKey)) + x, err = value.SetValueByScript(x, inputVal, fieldPathToComponent(input.ParameterKey)) if err != nil { return errors.Wrap(err, "fill value to component") } @@ -238,7 +238,7 @@ func (t *applyTask) fillInputs(inputs *pkgmaps.SyncMap[string, *value.Value], bu return nil } -func (t *applyTask) generateOutput(output *unstructured.Unstructured, outputs []*unstructured.Unstructured, cache *pkgmaps.SyncMap[string, *value.Value], build valueBuilder) error { +func (t *applyTask) generateOutput(output *unstructured.Unstructured, outputs []*unstructured.Unstructured, cache *pkgmaps.SyncMap[string, cue.Value], build valueBuilder) error { if len(t.component.Outputs) == 0 { return nil } @@ -251,25 +251,20 @@ func (t *applyTask) generateOutput(output *unstructured.Unstructured, outputs [] } cueString += fmt.Sprintf("output:%s\n", string(outputJSON)) } - componentVal, err := build(cueString) - if err != nil { - return errors.Wrap(err, "create cue value from component") - } + componentVal := build(cueString) for _, os := range outputs { name := os.GetLabels()[oam.TraitResource] if name != "" { - if err := componentVal.FillObject(os.Object, "outputs", name); err != nil { - return errors.WithMessage(err, "FillOutputs") - } + componentVal = componentVal.FillPath(cue.ParsePath(fmt.Sprintf("outputs.%s", name)), os.Object) } } for _, o := range t.component.Outputs { pathToSetVar := t.varKey(o.Name) - actualOutput, err := componentVal.LookupValue(o.ValueFrom) - if err != nil { - return errors.Wrap(err, "lookup output") + actualOutput := componentVal.LookupPath(cue.ParsePath(o.ValueFrom)) + if !actualOutput.Exists() { + return workflowerrors.LookUpNotFoundErr(o.ValueFrom) } cache.Set(pathToSetVar, actualOutput) } @@ -287,9 +282,9 @@ func (t *applyTask) allDependsReady(healthyMap map[string]bool) bool { return true } -func (t *applyTask) allInputReady(cache *pkgmaps.SyncMap[string, *value.Value]) bool { +func (t *applyTask) allInputReady(cache *pkgmaps.SyncMap[string, cue.Value]) bool { for _, in := range t.component.Inputs { - if val := t.getVar(in.From, cache); val == nil { + if val := t.getVar(in.From, cache); val == (cue.Value{}) { return false } } @@ -304,18 +299,18 @@ type applyTaskResult struct { } // applyComponents will apply components to placements. -func applyComponents(ctx context.Context, apply oamProvider.ComponentApply, healthCheck oamProvider.ComponentHealthCheck, components []common.ApplicationComponent, placements []v1alpha1.PlacementDecision, parallelism int) (bool, string, error) { +func applyComponents(ctx context.Context, apply oamprovidertypes.ComponentApply, healthCheck oamprovidertypes.ComponentHealthCheck, components []common.ApplicationComponent, placements []v1alpha1.PlacementDecision, parallelism int) (bool, string, error) { var tasks []*applyTask - var cache = pkgmaps.NewSyncMap[string, *value.Value]() - rootValue, err := value.NewValue("{}", nil, "") - if err != nil { - return false, "", err + var cache = pkgmaps.NewSyncMap[string, cue.Value]() + rootValue := cuecontext.New().CompileString("{}") + if rootValue.Err() != nil { + return false, "", rootValue.Err() } var cueMutex sync.Mutex - var makeValue = func(s string) (*value.Value, error) { + var makeValue = func(s string) cue.Value { cueMutex.Lock() defer cueMutex.Unlock() - return rootValue.MakeValue(s) + return rootValue.Context().CompileString(s) } taskHealthyMap := map[string]bool{} @@ -417,30 +412,21 @@ func fieldPathToComponent(input string) string { return fmt.Sprintf("properties.%s", strings.TrimSpace(input)) } -func component2Value(comp common.ApplicationComponent, build valueBuilder) (*value.Value, error) { - x, err := build("") - if err != nil { - return nil, err - } - err = x.FillObject(comp, "") - if err != nil { - return nil, err - } +func component2Value(comp common.ApplicationComponent, build valueBuilder) cue.Value { + x := build("") + x = x.FillPath(cue.ParsePath(""), comp) // Component.ReplicaKey have no json tag, so we need to set it manually - err = x.FillObject(comp.ReplicaKey, "replicaKey") - if err != nil { - return nil, err - } - return x, nil + x = x.FillPath(cue.ParsePath("replicaKey"), comp.ReplicaKey) + return x } -func value2Component(v *value.Value) (*common.ApplicationComponent, error) { +func value2Component(v cue.Value) (*common.ApplicationComponent, error) { var comp common.ApplicationComponent - err := v.UnmarshalTo(&comp) + err := value.UnmarshalTo(v, &comp) if err != nil { return nil, err } - if rk, err := v.GetString("replicaKey"); err == nil { + if rk, err := v.LookupPath(cue.ParsePath("replicaKey")).String(); err == nil { comp.ReplicaKey = rk } return &comp, nil diff --git a/pkg/workflow/providers/multicluster/deploy_test.go b/pkg/workflow/providers/legacy/multicluster/deploy_test.go similarity index 91% rename from pkg/workflow/providers/multicluster/deploy_test.go rename to pkg/workflow/providers/legacy/multicluster/deploy_test.go index dc21a76fa..4289a0d94 100644 --- a/pkg/workflow/providers/multicluster/deploy_test.go +++ b/pkg/workflow/providers/legacy/multicluster/deploy_test.go @@ -24,12 +24,12 @@ import ( "testing" "time" + "cuelang.org/go/cue" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" - "github.com/kubevela/workflow/pkg/cue/model/value" apicommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common" @@ -114,12 +114,12 @@ func TestApplyComponentsDepends(t *testing.T) { } applyMap := &sync.Map{} - apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { + apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond) applyMap.Store(fmt.Sprintf("%s/%s", clusterName, comp.Name), true) return nil, nil, true, nil } - healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { + healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { _, found := applyMap.Load(fmt.Sprintf("%s/%s", clusterName, comp.Name)) return found, nil, nil, nil } @@ -158,12 +158,12 @@ func TestApplyComponentsIO(t *testing.T) { applyMap = new(sync.Map) ctx = context.Background() ) - apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { + apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond) applyMap.Store(fmt.Sprintf("%s/%s", clusterName, comp.Name), true) return nil, nil, true, nil } - healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { + healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { _, found := applyMap.Load(fmt.Sprintf("%s/%s", clusterName, comp.Name)) return found, &unstructured.Unstructured{Object: map[string]interface{}{ "spec": map[string]interface{}{ @@ -293,7 +293,7 @@ func TestApplyComponentsIO(t *testing.T) { output *unstructured.Unstructured outputs []*unstructured.Unstructured } - apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { + apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond) key := storeKey(clusterName, comp) result := applyResult{ @@ -320,7 +320,7 @@ func TestApplyComponentsIO(t *testing.T) { applyMap.Store(storeKey(clusterName, comp), result) return nil, nil, true, nil } - healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { + healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { key := storeKey(clusterName, comp) r, found := applyMap.Load(key) result, _ := r.(applyResult) diff --git a/pkg/stdlib/pkgs/multicluster.cue b/pkg/workflow/providers/legacy/multicluster/multicluster.cue similarity index 87% rename from pkg/stdlib/pkgs/multicluster.cue rename to pkg/workflow/providers/legacy/multicluster/multicluster.cue index 21d127ce2..62a784cd4 100644 --- a/pkg/stdlib/pkgs/multicluster.cue +++ b/pkg/workflow/providers/legacy/multicluster/multicluster.cue @@ -1,3 +1,64 @@ +// multicluster.cue + +#ListClusters: { + #provider: "op" + #do: "list-clusters" + + outputs: { + clusters: [...string] + } +} + +#GetPlacementsFromTopologyPolicies: { + #provider: "op" + #do: "get-placements-from-topology-policies" + policies: [...string] + placements: [...{ + cluster: string + namespace: string + }] +} + +#Deploy: { + #provider: "op" + #do: "deploy" + policies: [...string] + parallelism: int + ignoreTerraformComponent: bool + inlinePolicies: *[] | [...{...}] +} + +// deprecated +#MakePlacementDecisions: { + #provider: "op" + #do: "make-placement-decisions" + + inputs: { + policyName: string + envName: string + placement: #Placement + } + + outputs: { + decisions: [...#PlacementDecision] + } +} + +// deprecated +#PatchApplication: { + #provider: "op" + #do: "patch-application" + + inputs: { + envName: string + patch?: components: [...#Component] + selector?: components: [...string] + } + + outputs: {...} + ... +} + // deprecated #Placement: { clusterSelector?: { @@ -31,44 +92,13 @@ } // deprecated -#MakePlacementDecisions: { - #provider: "multicluster" - #do: "make-placement-decisions" - - inputs: { - policyName: string - envName: string - placement: #Placement - } - - outputs: { - decisions: [...#PlacementDecision] - } -} - -// deprecated -#PatchApplication: { - #provider: "multicluster" - #do: "patch-application" - - inputs: { - envName: string - patch?: components: [...#Component] - selector?: components: [...string] - } - - outputs: {...} - ... -} - -// deprecated -#LoadEnvBindingEnv: #Steps & { +#LoadEnvBindingEnv: { inputs: { env: string policy: string } - loadPolicies: oam.#LoadPolicies @step(1) + loadPolicies: #LoadPolicies policy_: string envBindingPolicies: [] if inputs.policy == "" && loadPolicies.value != _|_ { @@ -79,14 +109,14 @@ policy_: inputs.policy } - loadPolicy: loadPolicies.value["\(policy_)"] + loadPolicy: loadPolicies.value[(policy_)] envMap: { for ev in loadPolicy.properties.envs { - "\(ev.name)": ev + (ev.name): ev } ... } - envConfig_: envMap["\(inputs.env)"] + envConfig_: envMap[(inputs.env)] outputs: { policy: policy_ @@ -95,7 +125,7 @@ } // deprecated -#PrepareEnvBinding: #Steps & { +#PrepareEnvBinding: { inputs: { env: string policy: string @@ -108,7 +138,7 @@ env: env_ policy: policy_ } - } @step(1) + } envConfig: loadEnv.outputs.envConfig placementDecisions: #MakePlacementDecisions & { @@ -117,7 +147,7 @@ envName: env_ placement: envConfig.placement } - } @step(2) + } patchedApp: #PatchApplication & { inputs: { @@ -129,7 +159,7 @@ patch: envConfig.patch } } - } @step(3) + } outputs: { components: patchedApp.outputs.spec.components @@ -138,15 +168,15 @@ } // deprecated -#ApplyComponentsToEnv: #Steps & { +#ApplyComponentsToEnv: { inputs: { decisions: [...#PlacementDecision] components: [...#Component] env: string waitHealthy: bool - } @step(1) + } - outputs: #Steps & { + outputs: { for decision in inputs.decisions { for key, comp in inputs.components { "\(decision.cluster)-\(decision.namespace)-\(key)": #ApplyComponent & { @@ -159,16 +189,14 @@ } waitHealthy: inputs.waitHealthy env: inputs.env - } @step(1) + } } } - } @step(2) + } } // deprecated #ApplyEnvBindApp: { - #do: "steps" - env: string policy: string app: string @@ -182,7 +210,7 @@ env: env_ policy: policy_ } - } @step(1) + } apply: #ApplyComponentsToEnv & { inputs: { @@ -191,7 +219,7 @@ env: env_ waitHealthy: !parallel } - } @step(2) + } if parallel { wait: #ApplyComponentsToEnv & { @@ -201,34 +229,6 @@ env: env_ waitHealthy: true } - } @step(3) + } } } - -#ListClusters: { - #provider: "multicluster" - #do: "list-clusters" - - outputs: { - clusters: [...string] - } -} - -#GetPlacementsFromTopologyPolicies: { - #provider: "multicluster" - #do: "get-placements-from-topology-policies" - policies: [...string] - placements: [...{ - cluster: string - namespace: string - }] -} - -#Deploy: { - #provider: "multicluster" - #do: "deploy" - policies: [...string] - parallelism: int - ignoreTerraformComponent: bool - inlinePolicies: *[] | [...{...}] -} diff --git a/pkg/workflow/providers/legacy/multicluster/multicluster.go b/pkg/workflow/providers/legacy/multicluster/multicluster.go new file mode 100644 index 000000000..bf5e72e26 --- /dev/null +++ b/pkg/workflow/providers/legacy/multicluster/multicluster.go @@ -0,0 +1,227 @@ +/* +Copyright 2021 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package multicluster + +import ( + "context" + _ "embed" + "fmt" + + "github.com/pkg/errors" + + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/pkg/multicluster" + pkgpolicy "github.com/oam-dev/kubevela/pkg/policy" + "github.com/oam-dev/kubevela/pkg/policy/envbinding" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" +) + +// Inputs is the inputs for multi cluster +type Inputs[T any] struct { + Inputs T `json:"inputs"` +} + +// Outputs is the outputs for multi cluster +type Outputs[T any] struct { + Outputs T `json:"outputs"` +} + +// PlacementDecisionVars is the vars for make placement decisions +type PlacementDecisionVars struct { + PolicyName string `json:"policyName"` + EnvName string `json:"envName"` + Placement *v1alpha1.EnvPlacement `json:"placement,omitempty"` +} + +// PlacementDecisionResult is the result for make placement decisions +type PlacementDecisionResult struct { + Decisions []v1alpha1.PlacementDecision `json:"decisions"` +} + +// PlacementDecisionParams is the parameter for make placement decisions +type PlacementDecisionParams = oamprovidertypes.OAMParams[Inputs[PlacementDecisionVars]] + +// PlacementDecisionReturns is the return value for make placement decisions +type PlacementDecisionReturns = Outputs[PlacementDecisionResult] + +// MakePlacementDecisions ... +// Deprecated +func MakePlacementDecisions(ctx context.Context, params *PlacementDecisionParams) (*PlacementDecisionReturns, error) { + policy := params.Params.Inputs.PolicyName + if policy == "" { + return nil, fmt.Errorf("empty policy name") + } + env := params.Params.Inputs.EnvName + if env == "" { + return nil, fmt.Errorf("empty env name") + } + placement := params.Params.Inputs.Placement + if placement == nil { + return nil, fmt.Errorf("empty placement for policy %s in env %s", policy, env) + } + + var namespace, clusterName string + // check if namespace selector is valid + if placement.NamespaceSelector != nil { + if len(placement.NamespaceSelector.Labels) != 0 { + return nil, fmt.Errorf("invalid env %s: namespace selector in cluster-gateway does not support label selector for now", env) + } + namespace = placement.NamespaceSelector.Name + } + // check if cluster selector is valid + if placement.ClusterSelector != nil { + if len(placement.ClusterSelector.Labels) != 0 { + return nil, fmt.Errorf("invalid env %s: cluster selector does not support label selector for now", env) + } + clusterName = placement.ClusterSelector.Name + } + // set fallback cluster + if clusterName == "" { + clusterName = multicluster.ClusterLocalName + } + // check if target cluster exists + if clusterName != multicluster.ClusterLocalName { + if _, err := multicluster.GetVirtualCluster(ctx, params.KubeClient, clusterName); err != nil { + return nil, errors.Wrapf(err, "failed to get cluster %s for env %s", clusterName, env) + } + } + // write result back + decisions := []v1alpha1.PlacementDecision{{ + Cluster: clusterName, + Namespace: namespace, + }} + if err := envbinding.WritePlacementDecisions(params.App, policy, env, decisions); err != nil { + return nil, err + } + return &PlacementDecisionReturns{Outputs: PlacementDecisionResult{Decisions: decisions}}, nil +} + +// ApplicationVars is the vars for patching application +type ApplicationVars struct { + EnvName string `json:"envName"` + Patch *v1alpha1.EnvPatch `json:"patch,omitempty"` + Selector *v1alpha1.EnvSelector `json:"selector,omitempty"` +} + +// ApplicationParams is the parameter for patch application +type ApplicationParams = oamprovidertypes.OAMParams[Inputs[ApplicationVars]] + +// PatchApplication ... +// Deprecated +func PatchApplication(_ context.Context, params *ApplicationParams) (*Outputs[*v1beta1.Application], error) { + env := params.Params.Inputs.EnvName + if env == "" { + return nil, fmt.Errorf("empty env name") + } + patch := params.Params.Inputs.Patch + selector := params.Params.Inputs.Selector + + newApp, err := envbinding.PatchApplication(params.App, patch, selector) + if err != nil { + return nil, errors.Wrapf(err, "failed to patch app for env %s", env) + } + return &Outputs[*v1beta1.Application]{Outputs: newApp}, nil +} + +// ClusterParams is the parameter for list clusters +type ClusterParams struct { + Clusters []string `json:"clusters"` +} + +// ClusterReturns is the return value for list clusters +type ClusterReturns = Outputs[ClusterParams] + +// ListClusters lists clusters +func ListClusters(ctx context.Context, params *oamprovidertypes.OAMParams[any]) (*ClusterReturns, error) { + secrets, err := multicluster.ListExistingClusterSecrets(ctx, params.KubeClient) + if err != nil { + return nil, err + } + var clusters []string + for _, secret := range secrets { + clusters = append(clusters, secret.Name) + } + return &ClusterReturns{Outputs: ClusterParams{Clusters: clusters}}, nil +} + +// DeployParams is the parameter for deploy +type DeployParams = oamprovidertypes.OAMParams[DeployParameter] + +// Deploy deploys the application +func Deploy(ctx context.Context, params *DeployParams) (*any, error) { + if params.Params.Parallelism <= 0 { + return nil, errors.Errorf("parallelism cannot be smaller than 1") + } + executor := NewDeployWorkflowStepExecutor(params.KubeClient, params.Appfile, params.ComponentApply, params.ComponentHealthCheck, params.WorkloadRender, params.Params) + healthy, reason, err := executor.Deploy(ctx) + if err != nil { + return nil, err + } + if !healthy { + params.Action.Wait(reason) + } + return nil, nil +} + +// PoliciesVars is the vars for getting placements from topology policies +type PoliciesVars struct { + Policies []string `json:"policies"` +} + +// PoliciesResult is the result for getting placements from topology policies +type PoliciesResult struct { + Placements []v1alpha1.PlacementDecision `json:"placements"` +} + +// PoliciesParams is the params for getting placements from topology policies +type PoliciesParams = oamprovidertypes.OAMParams[PoliciesVars] + +// GetPlacementsFromTopologyPolicies gets placements from topology policies +func GetPlacementsFromTopologyPolicies(ctx context.Context, params *PoliciesParams) (*PoliciesResult, error) { + policyNames := params.Params.Policies + policies, err := selectPolicies(params.Appfile.Policies, policyNames) + if err != nil { + return nil, err + } + placements, err := pkgpolicy.GetPlacementsFromTopologyPolicies(ctx, params.KubeClient, params.Appfile.Namespace, policies, true) + if err != nil { + return nil, err + } + return &PoliciesResult{Placements: placements}, nil +} + +//go:embed multicluster.cue +var template string + +// GetTemplate returns the cue template. +func GetTemplate() string { + return template +} + +// GetProviders returns the cue providers. +func GetProviders() map[string]cuexruntime.ProviderFn { + return map[string]cuexruntime.ProviderFn{ + "make-placement-decisions": oamprovidertypes.OAMGenericProviderFn[Inputs[PlacementDecisionVars], Outputs[PlacementDecisionResult]](MakePlacementDecisions), + "patch-application": oamprovidertypes.OAMGenericProviderFn[Inputs[ApplicationVars], Outputs[*v1beta1.Application]](PatchApplication), + "list-clusters": oamprovidertypes.OAMGenericProviderFn[any, ClusterReturns](ListClusters), + "get-placements-from-topology-policies": oamprovidertypes.OAMGenericProviderFn[PoliciesVars, PoliciesResult](GetPlacementsFromTopologyPolicies), + "deploy": oamprovidertypes.OAMGenericProviderFn[DeployParameter, any](Deploy), + } +} diff --git a/pkg/workflow/providers/multicluster/multicluster_test.go b/pkg/workflow/providers/legacy/multicluster/multicluster_test.go similarity index 57% rename from pkg/workflow/providers/multicluster/multicluster_test.go rename to pkg/workflow/providers/legacy/multicluster/multicluster_test.go index 6b9bec4c0..09c8f0c49 100644 --- a/pkg/workflow/providers/multicluster/multicluster_test.go +++ b/pkg/workflow/providers/legacy/multicluster/multicluster_test.go @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/kubevela/workflow/pkg/mock" clusterv1alpha1 "github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1" clustercommon "github.com/oam-dev/cluster-gateway/pkg/common" @@ -38,12 +37,15 @@ import ( "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/utils/common" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) func TestMakePlacementDecisions(t *testing.T) { + cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build() + ctx := context.Background() multicluster.ClusterGatewaySecretNamespace = types.DefaultKubeVelaNS testCases := []struct { - InputVal map[string]interface{} + InputVal PlacementDecisionVars OldCluster string OldNamespace string ExpectError string @@ -51,81 +53,74 @@ func TestMakePlacementDecisions(t *testing.T) { ExpectNamespace string PreAddCluster string }{{ - InputVal: map[string]interface{}{}, - ExpectError: "var(path=inputs.policyName) not exist", + InputVal: PlacementDecisionVars{}, + ExpectError: "empty policy name", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", }, - ExpectError: "var(path=inputs.envName) not exist", + ExpectError: "empty env name", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", }, - ExpectError: "var(path=inputs.placement) not exist", + ExpectError: "empty placement for policy example-policy in env example-env", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": "example-placement", - }, - ExpectError: "failed to parse placement while making placement decision", - }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{ - "namespaceSelector": map[string]interface{}{ - "labels": map[string]string{"key": "value"}, + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{ + NamespaceSelector: &v1alpha1.NamespaceSelector{ + Labels: map[string]string{"key": "value"}, }, }, }, ExpectError: "namespace selector in cluster-gateway does not support label selector for now", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{ - "clusterSelector": map[string]interface{}{ - "labels": map[string]string{"key": "value"}, + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{ + ClusterSelector: &apicommon.ClusterSelector{ + Labels: map[string]string{"key": "value"}, }, }, }, ExpectError: "cluster selector does not support label selector for now", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{}, + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{}, }, ExpectError: "", ExpectCluster: "local", ExpectNamespace: "", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{ - "clusterSelector": map[string]interface{}{ - "name": "example-cluster", + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{ + NamespaceSelector: &v1alpha1.NamespaceSelector{ + Name: "example-namespace", }, - "namespaceSelector": map[string]interface{}{ - "name": "example-namespace", + ClusterSelector: &apicommon.ClusterSelector{ + Name: "example-cluster", }, }, }, ExpectError: "failed to get cluster", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{ - "clusterSelector": map[string]interface{}{ - "name": "example-cluster", + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{ + NamespaceSelector: &v1alpha1.NamespaceSelector{ + Name: "example-namespace", }, - "namespaceSelector": map[string]interface{}{ - "name": "example-namespace", + ClusterSelector: &apicommon.ClusterSelector{ + Name: "example-cluster", }, }, }, @@ -134,15 +129,15 @@ func TestMakePlacementDecisions(t *testing.T) { ExpectNamespace: "example-namespace", PreAddCluster: "example-cluster", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{ - "clusterSelector": map[string]interface{}{ - "name": "example-cluster", + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{ + NamespaceSelector: &v1alpha1.NamespaceSelector{ + Name: "example-namespace", }, - "namespaceSelector": map[string]interface{}{ - "name": "example-namespace", + ClusterSelector: &apicommon.ClusterSelector{ + Name: "example-cluster", }, }, }, @@ -153,15 +148,15 @@ func TestMakePlacementDecisions(t *testing.T) { ExpectNamespace: "example-namespace", PreAddCluster: "example-cluster", }, { - InputVal: map[string]interface{}{ - "policyName": "example-policy", - "envName": "example-env", - "placement": map[string]interface{}{ - "clusterSelector": map[string]interface{}{ - "name": "example-cluster", + InputVal: PlacementDecisionVars{ + PolicyName: "example-policy", + EnvName: "example-env", + Placement: &v1alpha1.EnvPlacement{ + NamespaceSelector: &v1alpha1.NamespaceSelector{ + Name: "example-namespace", }, - "namespaceSelector": map[string]interface{}{ - "name": "example-namespace", + ClusterSelector: &apicommon.ClusterSelector{ + Name: "example-cluster", }, }, }, @@ -173,24 +168,16 @@ func TestMakePlacementDecisions(t *testing.T) { r := require.New(t) for _, testCase := range testCases { - cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build() app := &v1beta1.Application{} - p := &provider{ - Client: cli, - app: app, - } act := &mock.Action{} - v, err := value.NewValue("", nil, "") - r.NoError(err) - r.NoError(v.FillObject(testCase.InputVal, "inputs")) if testCase.PreAddCluster != "" { - r.NoError(cli.Create(context.Background(), &corev1.Secret{ + _ = cli.Create(context.Background(), &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: multicluster.ClusterGatewaySecretNamespace, Name: testCase.PreAddCluster, Labels: map[string]string{clustercommon.LabelKeyClusterCredentialType: string(clusterv1alpha1.CredentialTypeX509Certificate)}, }, - })) + }) } if testCase.OldNamespace != "" || testCase.OldCluster != "" { pd := v1alpha1.PlacementDecision{ @@ -210,27 +197,33 @@ func TestMakePlacementDecisions(t *testing.T) { Status: &runtime.RawExtension{Raw: bs}, }} } - err = p.MakePlacementDecisions(nil, nil, v, act) + res, err := MakePlacementDecisions(ctx, &PlacementDecisionParams{ + Params: Inputs[PlacementDecisionVars]{ + Inputs: testCase.InputVal, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + App: app, + Action: act, + KubeClient: cli, + }, + }) if testCase.ExpectError == "" { r.NoError(err) } else { r.Contains(err.Error(), testCase.ExpectError) continue } - outputs, err := v.LookupValue("outputs") - r.NoError(err) - md := map[string][]v1alpha1.PlacementDecision{} - r.NoError(outputs.UnmarshalTo(&md)) - r.Equal(1, len(md["decisions"])) - r.Equal(testCase.ExpectCluster, md["decisions"][0].Cluster) - r.Equal(testCase.ExpectNamespace, md["decisions"][0].Namespace) + md := res.Outputs.Decisions + r.Equal(1, len(md)) + r.Equal(testCase.ExpectCluster, md[0].Cluster) + r.Equal(testCase.ExpectNamespace, md[0].Namespace) r.Equal(1, len(app.Status.PolicyStatus)) - r.Equal(testCase.InputVal["policyName"], app.Status.PolicyStatus[0].Name) + r.Equal(testCase.InputVal.PolicyName, app.Status.PolicyStatus[0].Name) r.Equal(v1alpha1.EnvBindingPolicyType, app.Status.PolicyStatus[0].Type) status := &v1alpha1.EnvBindingStatus{} r.NoError(json.Unmarshal(app.Status.PolicyStatus[0].Status.Raw, status)) r.Equal(1, len(status.Envs)) - r.Equal(testCase.InputVal["envName"], status.Envs[0].Env) + r.Equal(testCase.InputVal.EnvName, status.Envs[0].Env) r.Equal(1, len(status.Envs[0].Placements)) r.Equal(testCase.ExpectNamespace, status.Envs[0].Placements[0].Namespace) r.Equal(testCase.ExpectCluster, status.Envs[0].Placements[0].Cluster) @@ -238,6 +231,8 @@ func TestMakePlacementDecisions(t *testing.T) { } func TestPatchApplication(t *testing.T) { + ctx := context.Background() + cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build() baseApp := &v1beta1.Application{Spec: v1beta1.ApplicationSpec{ Components: []apicommon.ApplicationComponent{{ Name: "comp-1", @@ -260,67 +255,52 @@ func TestPatchApplication(t *testing.T) { }}, }} testCases := []struct { - InputVal map[string]interface{} + InputVal ApplicationVars ExpectError string ExpectComponents []apicommon.ApplicationComponent }{{ - InputVal: map[string]interface{}{}, - ExpectError: "var(path=inputs.envName) not exist", + InputVal: ApplicationVars{}, + ExpectError: "empty env name", }, { - InputVal: map[string]interface{}{ - "envName": "example-env", + InputVal: ApplicationVars{ + EnvName: "example-env", }, ExpectComponents: baseApp.Spec.Components, }, { - InputVal: map[string]interface{}{ - "envName": "example-env", - "patch": "bad patch", - }, - ExpectError: "failed to unmarshal patch for env", - }, { - InputVal: map[string]interface{}{ - "envName": "example-env", - "selector": "bad selector", - }, - ExpectError: "failed to unmarshal selector for env", - }, { - InputVal: map[string]interface{}{ - "envName": "example-env", - "patch": map[string]interface{}{ - "components": []map[string]interface{}{{ - "name": "comp-0", - "type": "webservice", - }, { - "name": "comp-1", - "type": "worker", - "properties": map[string]interface{}{ - "image": "patch", - "port": 8080, - }, - }, { - "name": "comp-3", - "type": "webservice", - "properties": map[string]interface{}{ - "image": "patch", - "port": 8090, - }, - "traits": []map[string]interface{}{{ - "type": "scaler", - "properties": map[string]interface{}{"replicas": 5}, + InputVal: ApplicationVars{ + EnvName: "example-env", + Patch: &v1alpha1.EnvPatch{ + Components: []v1alpha1.EnvComponentPatch{ + { + Name: "comp-0", + Type: "webservice", }, { - "type": "env", - "properties": map[string]interface{}{"env": map[string]string{"Key": "Value"}}, + Name: "comp-1", + Type: "worker", + Properties: &runtime.RawExtension{Raw: []byte(`{"image":"patch","port":8080}`)}, }, { - "type": "annotations", - "properties": map[string]interface{}{"aKey": "aVal"}}, + Name: "comp-3", + Type: "webservice", + Properties: &runtime.RawExtension{Raw: []byte(`{"image":"patch","port":8090}`)}, + Traits: []v1alpha1.EnvTraitPatch{ + { + Type: "scaler", + Properties: &runtime.RawExtension{Raw: []byte(`{"replicas":5}`)}, + }, { + Type: "env", + Properties: &runtime.RawExtension{Raw: []byte(`{"env":{"Key":"Value"}}`)}, + }, { + Type: "annotations", + Properties: &runtime.RawExtension{Raw: []byte(`{"aKey":"aVal"}`)}, + }, + }}, { + Name: "comp-4", + Type: "webservice", }, - }, { - "name": "comp-4", - "type": "webservice", - }}, + }, }, - "selector": map[string]interface{}{ - "components": []string{"comp-2", "comp-1", "comp-3", "comp-0"}, + Selector: &v1alpha1.EnvSelector{ + Components: []string{"comp-2", "comp-1", "comp-3", "comp-0"}, }, }, ExpectComponents: []apicommon.ApplicationComponent{{ @@ -349,28 +329,26 @@ func TestPatchApplication(t *testing.T) { Type: "webservice", }}, }} - r := require.New(t) for _, testCase := range testCases { - cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build() - p := &provider{ - Client: cli, - app: baseApp, - } + r := require.New(t) act := &mock.Action{} - v, err := value.NewValue("", nil, "") - r.NoError(err) - r.NoError(v.FillObject(testCase.InputVal, "inputs")) - err = p.PatchApplication(nil, nil, v, act) + res, err := PatchApplication(ctx, &ApplicationParams{ + Params: Inputs[ApplicationVars]{ + Inputs: testCase.InputVal, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + Action: act, + App: baseApp, + KubeClient: cli, + }, + }) if testCase.ExpectError == "" { r.NoError(err) } else { r.Contains(err.Error(), testCase.ExpectError) continue } - outputs, err := v.LookupValue("outputs") - r.NoError(err) - patchApp := &v1beta1.Application{} - r.NoError(outputs.UnmarshalTo(patchApp)) + patchApp := res.Outputs r.Equal(len(testCase.ExpectComponents), len(patchApp.Spec.Components)) for idx, comp := range testCase.ExpectComponents { _comp := patchApp.Spec.Components[idx] @@ -398,6 +376,7 @@ func TestPatchApplication(t *testing.T) { func TestListClusters(t *testing.T) { multicluster.ClusterGatewaySecretNamespace = types.DefaultKubeVelaNS r := require.New(t) + ctx := context.Background() cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build() clusterNames := []string{"cluster-a", "cluster-b"} for _, secretName := range clusterNames { @@ -407,20 +386,11 @@ func TestListClusters(t *testing.T) { secret.Labels = map[string]string{clustercommon.LabelKeyClusterCredentialType: string(clusterv1alpha1.CredentialTypeX509Certificate)} r.NoError(cli.Create(context.Background(), secret)) } - app := &v1beta1.Application{} - p := &provider{ - Client: cli, - app: app, - } - act := &mock.Action{} - v, err := value.NewValue("", nil, "") + res, err := ListClusters(ctx, &oamprovidertypes.OAMParams[any]{ + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: cli, + }, + }) r.NoError(err) - r.NoError(p.ListClusters(nil, nil, v, act)) - outputs, err := v.LookupValue("outputs") - r.NoError(err) - obj := struct { - Clusters []string `json:"clusters"` - }{} - r.NoError(outputs.UnmarshalTo(&obj)) - r.Equal(clusterNames, obj.Clusters) + r.Equal(clusterNames, res.Outputs.Clusters) } diff --git a/pkg/workflow/providers/legacy/oam/apply.go b/pkg/workflow/providers/legacy/oam/apply.go new file mode 100644 index 000000000..a4530c1be --- /dev/null +++ b/pkg/workflow/providers/legacy/oam/apply.go @@ -0,0 +1,221 @@ +/* +Copyright 2021 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oam + +import ( + "context" + _ "embed" + "fmt" + + "cuelang.org/go/cue" + "k8s.io/apimachinery/pkg/types" + + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" + "github.com/kubevela/workflow/pkg/cue/model/value" + workflowerrors "github.com/kubevela/workflow/pkg/errors" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/common" + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/pkg/oam" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" +) + +const ( + // ProviderName is provider name for install. + ProviderName = "oam" +) + +// RenderComponent render component +func RenderComponent(ctx context.Context, params *oamprovidertypes.OAMParams[cue.Value]) (cue.Value, error) { + v := params.Params + + comp, patcher, clusterName, overrideNamespace, err := lookUpCompInfo(v) + if err != nil { + return cue.Value{}, err + } + workload, traits, err := params.ComponentRender(ctx, *comp, patcher, clusterName, overrideNamespace) + if err != nil { + return cue.Value{}, err + } + + if workload != nil { + v = v.FillPath(cue.ParsePath("output"), workload.Object) + } + + for _, trait := range traits { + name := trait.GetLabels()[oam.TraitResource] + if name != "" { + v = v.FillPath(cue.ParsePath(fmt.Sprintf("outputs.%s", name)), workload.Object) + } + } + + return v, nil +} + +// ApplyComponent apply component. +func ApplyComponent(ctx context.Context, params *oamprovidertypes.OAMParams[cue.Value]) (cue.Value, error) { + v := params.Params + comp, patcher, clusterName, overrideNamespace, err := lookUpCompInfo(v) + if err != nil { + return cue.Value{}, err + } + workload, traits, healthy, err := params.ComponentApply(ctx, *comp, patcher, clusterName, overrideNamespace) + if err != nil { + return cue.Value{}, err + } + + if workload != nil { + v = v.FillPath(cue.ParsePath("output"), workload.Object) + } + + for _, trait := range traits { + name := trait.GetLabels()[oam.TraitResource] + if name != "" { + v = v.FillPath(cue.ParsePath(fmt.Sprintf("outputs.%s", name)), trait) + } + } + + waitHealthy, err := v.LookupPath(cue.ParsePath("waitHealthy")).Bool() + if err != nil { + waitHealthy = true + } + + if waitHealthy && !healthy { + params.Action.Wait("wait healthy") + } + return v, nil +} + +func lookUpCompInfo(v cue.Value) (*common.ApplicationComponent, *cue.Value, string, string, error) { + compSettings := v.LookupPath(cue.ParsePath("value")) + if !compSettings.Exists() { + return nil, nil, "", "", workflowerrors.LookUpNotFoundErr("value") + } + comp := &common.ApplicationComponent{} + + if err := value.UnmarshalTo(compSettings, comp); err != nil { + return nil, nil, "", "", err + } + var patcherValue *cue.Value + patcher := v.LookupPath(cue.ParsePath("patch")) + if patcher.Exists() { + patcherValue = &patcher + } + clusterName, err := v.LookupPath(cue.ParsePath("cluster")).String() + if err != nil { + clusterName = "" + } + overrideNamespace, err := v.LookupPath(cue.ParsePath("namespace")).String() + if err != nil { + overrideNamespace = "" + } + return comp, patcherValue, clusterName, overrideNamespace, nil +} + +// LoadVars is the load provider vars. +type LoadVars struct { + App string `json:"app,omitempty"` +} + +// LoadResult is the load provider result. +type LoadResult struct { + Value any `json:"value"` +} + +// LoadParams is the load provider params. +type LoadParams = oamprovidertypes.OAMParams[LoadVars] + +// LoadComponent load component describe info in application. +func LoadComponent(ctx context.Context, params *LoadParams) (*LoadResult, error) { + app := &v1beta1.Application{} + cli := params.KubeClient + // if specify `app`, use specified application otherwise use default application from provider + appSettings := params.Params.App + if appSettings == "" { + app = params.App + } else { + if err := cli.Get(ctx, types.NamespacedName{Name: appSettings, Namespace: params.App.Namespace}, app); err != nil { + return nil, err + } + } + comps := make(map[string]*common.ApplicationComponent, 0) + for _, _comp := range app.Spec.Components { + comp, err := params.Appfile.LoadDynamicComponent(ctx, cli, _comp.DeepCopy()) + if err != nil { + return nil, err + } + comp.Inputs = nil + comp.Outputs = nil + comps[_comp.Name] = comp + } + return &LoadResult{Value: comps}, nil +} + +// LoadComponentInOrder load component describe info in application output will be a list with order defined in application. +func LoadComponentInOrder(ctx context.Context, params *LoadParams) (*LoadResult, error) { + app := &v1beta1.Application{} + cli := params.KubeClient + // if specify `app`, use specified application otherwise use default application from provider + appSettings := params.Params.App + if appSettings == "" { + app = params.App + } else { + if err := cli.Get(ctx, types.NamespacedName{Name: appSettings, Namespace: params.App.Namespace}, app); err != nil { + return nil, err + } + } + comps := make([]common.ApplicationComponent, len(app.Spec.Components)) + for idx, _comp := range app.Spec.Components { + comp, err := params.Appfile.LoadDynamicComponent(ctx, cli, _comp.DeepCopy()) + if err != nil { + return nil, err + } + comp.Inputs = nil + comp.Outputs = nil + comps[idx] = *comp + } + return &LoadResult{Value: comps}, nil +} + +// LoadPolicies load policy describe info in application. +func LoadPolicies(_ context.Context, params *LoadParams) (*LoadResult, error) { + app := params.App + policies := make(map[string]v1beta1.AppPolicy, 0) + for _, po := range app.Spec.Policies { + policies[po.Name] = po + } + return &LoadResult{Value: policies}, nil +} + +//go:embed oam.cue +var template string + +// GetTemplate returns the cue template. +func GetTemplate() string { + return template +} + +// GetProviders returns the cue providers. +func GetProviders() map[string]cuexruntime.ProviderFn { + return map[string]cuexruntime.ProviderFn{ + "component-render": oamprovidertypes.OAMNativeProviderFn(RenderComponent), + "component-apply": oamprovidertypes.OAMNativeProviderFn(ApplyComponent), + "load": oamprovidertypes.OAMGenericProviderFn[LoadVars, LoadResult](LoadComponent), + "load-comps-in-order": oamprovidertypes.OAMGenericProviderFn[LoadVars, LoadResult](LoadComponentInOrder), + "load-policies": oamprovidertypes.OAMGenericProviderFn[LoadVars, LoadResult](LoadPolicies), + } +} diff --git a/pkg/workflow/providers/legacy/oam/apply_test.go b/pkg/workflow/providers/legacy/oam/apply_test.go new file mode 100644 index 000000000..11c03ad6f --- /dev/null +++ b/pkg/workflow/providers/legacy/oam/apply_test.go @@ -0,0 +1,205 @@ +/* +Copyright 2021 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oam + +import ( + "context" + "encoding/json" + "testing" + + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + "github.com/kubevela/workflow/pkg/mock" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/common" + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" +) + +func setupClient(ctx context.Context, t *testing.T) client.Client { + r := require.New(t) + scheme := runtime.NewScheme() + r.NoError(v1beta1.AddToScheme(scheme)) + r.NoError(appsv1.AddToScheme(scheme)) + cli := fake.NewClientBuilder().WithScheme(scheme).Build() + return cli +} + +func TestParser(t *testing.T) { + r := require.New(t) + ctx := context.Background() + act := &mock.Action{} + cuectx := cuecontext.New() + cli := setupClient(ctx, t) + + v := cuectx.CompileString("") + _, err := ApplyComponent(ctx, &oamprovidertypes.OAMParams[cue.Value]{ + Params: v, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: cli, + }, + }) + r.Equal(err.Error(), "failed to lookup value: var(path=value) not exist") + v = cuectx.CompileString(`value: { + name: "test", + type: "test", +}`) + res, err := ApplyComponent(ctx, &oamprovidertypes.OAMParams[cue.Value]{ + Params: v, + RuntimeParams: oamprovidertypes.RuntimeParams{ + Action: act, + ComponentApply: oamprovidertypes.ComponentApply(func(ctx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": comp.Name, + }, + }, + }, []*unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": "service", + "labels": map[string]interface{}{ + "trait.oam.dev/resource": "service", + }, + }, + }, + }, + }, false, nil + }), + }, + }) + r.NoError(err) + output, err := res.LookupPath(cue.ParsePath("output.metadata.name")).String() + r.NoError(err) + r.Equal(output, "test") + + outputs, err := res.LookupPath(cue.ParsePath("outputs.service.metadata.name")).String() + r.NoError(err) + r.Equal(outputs, "service") + + r.Equal(act.Phase, "Wait") +} + +func TestLoadComponent(t *testing.T) { + r := require.New(t) + ctx := context.Background() + act := &mock.Action{} + res, err := LoadComponent(ctx, &oamprovidertypes.OAMParams[LoadVars]{ + Params: LoadVars{}, + RuntimeParams: oamprovidertypes.RuntimeParams{ + Action: act, + App: &v1beta1.Application{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Spec: v1beta1.ApplicationSpec{ + Components: []common.ApplicationComponent{ + { + Name: "c1", + Type: "test", + Properties: &runtime.RawExtension{Raw: []byte(`{"image": "busybox"}`)}, + }, + }, + }, + }, + }, + }) + r.NoError(err) + b, err := json.Marshal(res.Value) + r.NoError(err) + r.Equal(string(b), `{"c1":{"name":"c1","type":"test","properties":{"image":"busybox"}}}`) + + app2 := &v1beta1.Application{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test2", + Namespace: "default", + }, + Spec: v1beta1.ApplicationSpec{ + Components: []common.ApplicationComponent{ + { + Name: "c2", + Type: "test", + Properties: &runtime.RawExtension{Raw: []byte(`{"image": "nginx"}`)}, + }, + }, + }, + } + cli := setupClient(ctx, t) + err = cli.Create(ctx, app2) + r.NoError(err) + res, err = LoadComponent(ctx, &oamprovidertypes.OAMParams[LoadVars]{ + Params: LoadVars{ + App: "test2", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + Action: act, + App: app2, + KubeClient: cli, + }, + }) + r.NoError(err) + b, err = json.Marshal(res.Value) + r.NoError(err) + r.Equal(string(b), `{"c2":{"name":"c2","type":"test","properties":{"image":"nginx"}}}`) +} + +func TestLoadComponentInOrder(t *testing.T) { + r := require.New(t) + ctx := context.Background() + act := &mock.Action{} + res, err := LoadComponentInOrder(ctx, &oamprovidertypes.OAMParams[LoadVars]{ + Params: LoadVars{}, + RuntimeParams: oamprovidertypes.RuntimeParams{ + Action: act, + App: &v1beta1.Application{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + Spec: v1beta1.ApplicationSpec{ + Components: []common.ApplicationComponent{ + { + Name: "c1", + Type: "test", + Properties: &runtime.RawExtension{Raw: []byte(`{"image": "busybox"}`)}, + }, + { + Name: "c2", + Type: "test", + Properties: &runtime.RawExtension{Raw: []byte(`{"image": "busybox"}`)}, + }, + }, + }, + }, + }, + }) + r.NoError(err) + b, err := json.Marshal(res.Value) + r.NoError(err) + r.Equal(string(b), `[{"name":"c1","type":"test","properties":{"image":"busybox"}},{"name":"c2","type":"test","properties":{"image":"busybox"}}]`) +} diff --git a/pkg/workflow/providers/legacy/oam/oam.cue b/pkg/workflow/providers/legacy/oam/oam.cue new file mode 100644 index 000000000..fc407c7a9 --- /dev/null +++ b/pkg/workflow/providers/legacy/oam/oam.cue @@ -0,0 +1,128 @@ +// oam.cue + +#ApplyComponent: { + #provider: "op" + #do: "component-apply" + + // +usage=The cluster to use + cluster: *"" | string + // +usage=The env to use + env: *"" | string + // +usage=The namespace to apply + namespace: *"" | string + // +usage=Whether to wait healthy of the applied component + waitHealthy: *true | bool + // +usage=The value of the component resource + value: {...} + // +usage=The patcher that will be applied to the resource, you can define the strategy of list merge through comments. Reference doc here: https://kubevela.io/docs/platform-engineers/traits/patch-trait#patch-in-workflow-step + patch?: {...} + ... +} + +#RenderComponent: { + #provider: "op" + #do: "component-render" + cluster: *"" | string + env: *"" | string + namespace: *"" | string + value: {...} + patch?: {...} + output?: {...} + outputs?: {...} + ... +} + +#LoadComponets: { + #provider: "op" + #do: "load" + + // +usage=If specify `app`, use specified application to load its component resources otherwise use current application + app?: string + // +usage=The value of the components will be filled in this field after the action is executed, you can use value[componentName] to refer a specified component + value?: {...} + ... +} + +#LoadPolicies: { + #provider: "op" + #do: "load-policies" + value?: {...} + ... +} + +#LoadComponetsInOrder: { + #provider: "op" + #do: "load-comps-in-order" + ... +} + +#Load: #LoadComponets + +#LoadInOrder: #LoadComponetsInOrder + +#ApplyApplication: #Steps & { + load: #LoadComponetsInOrder + components: #Steps & { + for name, c in load.value { + "\(name)": #ApplyComponent & { + value: c + } + } + } +} + +// This operator will dispatch all the components in parallel when applying an application. +// Currently it works for Addon Observability to speed up the installation. It can also works for other applications, which +// needs to skip health check for components. +#ApplyApplicationInParallel: #Steps & { + load: #LoadComponetsInOrder + components: #Steps & { + for name, c in load.value { + "\(name)": #ApplyComponent & { + value: c + waitHealthy: false + } + } + } +} + +#ApplyComponentRemaining: #Steps & { + // exceptions specify the resources not to apply. + exceptions: [...string] + exceptions_: {for c in exceptions {"\(c)": true}} + component: string + + load: #LoadComponets + render: #Steps & { + rendered: #RenderComponent & { + value: load.value[component] + } + comp: #Apply & { + value: rendered.output + } + for name, c in rendered.outputs { + if exceptions_[name] == _|_ { + "\(name)": #Apply & { + value: c + } + } + } + } +} + +#ApplyRemaining: #Steps & { + // exceptions specify the resources not to apply. + exceptions: [...string] + exceptions_: {for c in exceptions {"\(c)": true}} + + load: #LoadComponets + components: #Steps & { + for name, c in load.value { + if exceptions_[name] == _|_ { + "\(name)": #ApplyComponent & { + value: c + } + } + } + } +} diff --git a/pkg/velaql/providers/query/collector.go b/pkg/workflow/providers/legacy/query/collector.go similarity index 97% rename from pkg/velaql/providers/query/collector.go rename to pkg/workflow/providers/legacy/query/collector.go index f1a067335..ac2cdf015 100644 --- a/pkg/velaql/providers/query/collector.go +++ b/pkg/workflow/providers/legacy/query/collector.go @@ -33,7 +33,7 @@ import ( "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/resourcetracker" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" ) // AppCollector collect resource created by application @@ -80,12 +80,12 @@ func (c *AppCollector) CollectResourceFromApp(ctx context.Context) ([]Resource, } // ListApplicationResources list application applied resources from tracker -func (c *AppCollector) ListApplicationResources(ctx context.Context, app *v1beta1.Application) ([]*types.AppliedResource, error) { +func (c *AppCollector) ListApplicationResources(ctx context.Context, app *v1beta1.Application) ([]types.AppliedResource, error) { rootRT, currentRT, historyRTs, _, err := resourcetracker.ListApplicationResourceTrackers(ctx, c.k8sClient, app) if err != nil { - return nil, err + return nil, errors.WithMessage(err, "list application resource trackers") } - var managedResources []*types.AppliedResource + var managedResources []types.AppliedResource existResources := make(map[common.ClusterObjectReference]bool, len(app.Spec.Components)) if c.opt.Filter.QueryNewest { historyRTs = nil @@ -103,7 +103,7 @@ func (c *AppCollector) ListApplicationResources(ctx context.Context, app *v1beta } existResources[managedResource.ClusterObjectReference] = true } - managedResources = append(managedResources, &types.AppliedResource{ + managedResources = append(managedResources, types.AppliedResource{ Cluster: func() string { if managedResource.Cluster != "" { return managedResource.Cluster @@ -147,7 +147,7 @@ func (c *AppCollector) ListApplicationResources(ctx context.Context, app *v1beta filter := func(node types.ResourceTreeNode) bool { return isResourceMatchKindAndVersion(c.opt.Filter, node.Kind, node.APIVersion) } - var matchedResources []*types.AppliedResource + var matchedResources []types.AppliedResource // error from leaf nodes won't block the results for i := range managedResources { resource := managedResources[i] @@ -196,7 +196,7 @@ func (c *AppCollector) ListApplicationResources(ctx context.Context, app *v1beta if !rootObject.GetDeletionTimestamp().IsZero() { root.DeletionTimestamp = rootObject.GetDeletionTimestamp().Time } - root.Object = *rootObject + root.Object = rootObject resource.ResourceTree = &root matchedResources = append(matchedResources, resource) } diff --git a/pkg/velaql/providers/query/endpoint.go b/pkg/workflow/providers/legacy/query/endpoint.go similarity index 93% rename from pkg/velaql/providers/query/endpoint.go rename to pkg/workflow/providers/legacy/query/endpoint.go index 183b4e4f9..426d7dfec 100644 --- a/pkg/velaql/providers/query/endpoint.go +++ b/pkg/workflow/providers/legacy/query/endpoint.go @@ -34,40 +34,29 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - monitorContext "github.com/kubevela/pkg/monitor/context" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/types" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" apis "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/multicluster" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" ) // CollectServiceEndpoints generator service endpoints is available for common component type, // such as webservice or helm // it can not support the cloud service component currently -func (h *provider) CollectServiceEndpoints(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - val, err := v.LookupValue("app") - if err != nil { - return err - } - opt := Option{} - if err = val.UnmarshalTo(&opt); err != nil { - return err - } +func CollectServiceEndpoints(ctx context.Context, params *ListParams) (*ListResult[querytypes.ServiceEndpoint], error) { + opt := params.Params.App + cli := params.KubeClient app := new(v1beta1.Application) - err = findResource(ctx, h.cli, app, opt.Name, opt.Namespace, "") + err := findResource(ctx, cli, app, opt.Name, opt.Namespace, "") if err != nil { - return fmt.Errorf("query app failure %w", err) + return nil, fmt.Errorf("query app failure %w", err) } serviceEndpoints := make([]querytypes.ServiceEndpoint, 0) var clusterGatewayNodeIP = make(map[string]string) - collector := NewAppCollector(h.cli, opt) + collector := NewAppCollector(cli, opt) resources, err := collector.ListApplicationResources(ctx, app) if err != nil { - return err + return nil, err } for i, resource := range resources { cluster := resources[i].Cluster @@ -75,20 +64,20 @@ func (h *provider) CollectServiceEndpoints(ctx monitorContext.Context, _ wfConte if ip, exist := clusterGatewayNodeIP[cluster]; exist { return ip } - ip := selectorNodeIP(ctx, cluster, h.cli) + ip := selectorNodeIP(ctx, cluster, cli) if ip != "" { clusterGatewayNodeIP[cluster] = ip } return ip } if resource.ResourceTree != nil { - serviceEndpoints = append(serviceEndpoints, getEndpointFromNode(ctx, h.cli, resource.ResourceTree, resource.Component, cachedSelectorNodeIP)...) + serviceEndpoints = append(serviceEndpoints, getEndpointFromNode(ctx, cli, resource.ResourceTree, resource.Component, cachedSelectorNodeIP)...) } else { - serviceEndpoints = append(serviceEndpoints, getServiceEndpoints(ctx, h.cli, resource.GroupVersionKind(), resource.Name, resource.Namespace, resource.Cluster, resource.Component, cachedSelectorNodeIP)...) + serviceEndpoints = append(serviceEndpoints, getServiceEndpoints(ctx, cli, resource.GroupVersionKind(), resource.Name, resource.Namespace, resource.Cluster, resource.Component, cachedSelectorNodeIP)...) } } - return fillQueryResult(v, serviceEndpoints, "list") + return &ListResult[querytypes.ServiceEndpoint]{List: serviceEndpoints}, nil } func getEndpointFromNode(ctx context.Context, cli client.Client, node *querytypes.ResourceTreeNode, component string, cachedSelectorNodeIP func() string) []querytypes.ServiceEndpoint { diff --git a/pkg/velaql/providers/query/endpoint_test.go b/pkg/workflow/providers/legacy/query/endpoint_test.go similarity index 92% rename from pkg/velaql/providers/query/endpoint_test.go rename to pkg/workflow/providers/legacy/query/endpoint_test.go index c4c320c5d..bd4020d67 100644 --- a/pkg/velaql/providers/query/endpoint_test.go +++ b/pkg/workflow/providers/legacy/query/endpoint_test.go @@ -32,15 +32,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - monitorContext "github.com/kubevela/pkg/monitor/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) var _ = Describe("Test query endpoints", func() { @@ -236,22 +233,23 @@ var _ = Describe("Test query endpoints", func() { } } - opt := `app: { - name: "endpoints-app-2" - namespace: "default" - filter: { - cluster: "", - clusterNamespace: "default", + params := &ListParams{ + Params: ListVars{ + App: Option{ + Name: "endpoints-app-2", + Namespace: "default", + Filter: FilterOption{ + Cluster: "", + ClusterNamespace: "default", + }, + WithTree: true, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + }, } - withTree: true - }` - v, err := value.NewValue(opt, nil, "") - Expect(err).Should(BeNil()) - pr := &provider{ - cli: k8sClient, - } - logCtx := monitorContext.NewTraceContext(ctx, "") - err = pr.CollectServiceEndpoints(logCtx, nil, v, nil) + res, err := CollectServiceEndpoints(context.Background(), params) Expect(err).Should(BeNil()) urls := []string{ @@ -261,16 +259,9 @@ var _ = Describe("Test query endpoints", func() { "http://2.2.2.2:8080", "http://1.1.1.1", } - endValue, err := v.Field("list") - Expect(err).Should(BeNil()) - var endpoints []querytypes.ServiceEndpoint - err = endValue.Decode(&endpoints) - Expect(err).Should(BeNil()) - var edps []string - for _, e := range endpoints { - edps = append(edps, e.String()) + for i, e := range (*res).List { + Expect(urls[i]).Should(Equal(e.String())) } - Expect(edps).Should(BeEquivalentTo(urls)) }) It("Test select gateway IP", func() { diff --git a/pkg/velaql/providers/query/handler.go b/pkg/workflow/providers/legacy/query/handler.go similarity index 50% rename from pkg/velaql/providers/query/handler.go rename to pkg/workflow/providers/legacy/query/handler.go index 7ee251827..fdd81b601 100644 --- a/pkg/velaql/providers/query/handler.go +++ b/pkg/workflow/providers/legacy/query/handler.go @@ -19,9 +19,12 @@ package query import ( "bufio" "bytes" + "context" + _ "embed" "encoding/base64" "fmt" "io" + "strings" "time" "github.com/pkg/errors" @@ -30,19 +33,17 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" apimachinerytypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - monitorContext "github.com/kubevela/pkg/monitor/context" + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" pkgmulticluster "github.com/kubevela/pkg/multicluster" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/types" + "github.com/kubevela/workflow/pkg/providers/legacy/kube" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/multicluster" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) const ( @@ -55,11 +56,6 @@ const ( annoAmbassadorServiceNamespace = "ambassador.service/namespace" ) -type provider struct { - cli client.Client - cfg *rest.Config -} - // Resource refer to an object with cluster info type Resource struct { Cluster string `json:"cluster"` @@ -91,82 +87,82 @@ type FilterOption struct { QueryNewest bool `json:"queryNewest,omitempty"` } +// ListVars is the vars for list +type ListVars struct { + App Option `json:"app"` +} + +// ListParams is the params for list +type ListParams = oamprovidertypes.OAMParams[ListVars] + +// ListResult is the result for list +type ListResult[T any] struct { + List []T `json:"list"` + Error string `json:"err,omitempty"` +} + // ListResourcesInApp lists CRs created by Application, this provider queries the object data. -func (h *provider) ListResourcesInApp(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - val, err := v.LookupValue("app") - if err != nil { - return err - } - opt := Option{} - if err = val.UnmarshalTo(&opt); err != nil { - return err - } - collector := NewAppCollector(h.cli, opt) +func ListResourcesInApp(ctx context.Context, params *ListParams) (*ListResult[Resource], error) { + collector := NewAppCollector(params.KubeClient, params.Params.App) appResList, err := collector.CollectResourceFromApp(ctx) if err != nil { - return v.FillObject(err.Error(), "err") + // nolint:nilerr + return &ListResult[Resource]{Error: err.Error()}, nil } if appResList == nil { appResList = make([]Resource, 0) } - return fillQueryResult(v, appResList, "list") + return &ListResult[Resource]{List: appResList}, nil } // ListAppliedResources list applied resource from tracker, this provider only queries the metadata. -func (h *provider) ListAppliedResources(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - val, err := v.LookupValue("app") - if err != nil { - return err - } - opt := Option{} - if err = val.UnmarshalTo(&opt); err != nil { - return v.FillObject(err.Error(), "err") - } - collector := NewAppCollector(h.cli, opt) +func ListAppliedResources(ctx context.Context, params *ListParams) (*ListResult[querytypes.AppliedResource], error) { + opt := params.Params.App + cli := params.KubeClient + collector := NewAppCollector(cli, opt) app := new(v1beta1.Application) appKey := client.ObjectKey{Name: opt.Name, Namespace: opt.Namespace} - if err = h.cli.Get(ctx, appKey, app); err != nil { - return v.FillObject(err.Error(), "err") + if err := cli.Get(ctx, appKey, app); err != nil { + // nolint:nilerr + return &ListResult[querytypes.AppliedResource]{Error: err.Error()}, nil } appResList, err := collector.ListApplicationResources(ctx, app) if err != nil { - return v.FillObject(err.Error(), "err") + // nolint:nilerr + return &ListResult[querytypes.AppliedResource]{Error: err.Error()}, nil } if appResList == nil { - appResList = make([]*querytypes.AppliedResource, 0) + appResList = make([]querytypes.AppliedResource, 0) } - return fillQueryResult(v, appResList, "list") + return &ListResult[querytypes.AppliedResource]{List: appResList}, nil } -func (h *provider) CollectResources(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - val, err := v.LookupValue("app") - if err != nil { - return err - } - opt := Option{} - if err = val.UnmarshalTo(&opt); err != nil { - return v.FillObject(err.Error(), "err") - } - collector := NewAppCollector(h.cli, opt) +// CollectResources collects resources from the cluster +func CollectResources(ctx context.Context, params *ListParams) (*ListResult[querytypes.ResourceItem], error) { + opt := params.Params.App + cli := params.KubeClient + collector := NewAppCollector(cli, opt) app := new(v1beta1.Application) appKey := client.ObjectKey{Name: opt.Name, Namespace: opt.Namespace} - if err = h.cli.Get(ctx, appKey, app); err != nil { - return v.FillObject(err.Error(), "err") + if err := cli.Get(ctx, appKey, app); err != nil { + // nolint:nilerr + return &ListResult[querytypes.ResourceItem]{Error: err.Error()}, nil } appResList, err := collector.ListApplicationResources(ctx, app) if err != nil { - return v.FillObject(err.Error(), "err") + // nolint:nilerr + return &ListResult[querytypes.ResourceItem]{Error: err.Error()}, nil } var resources = make([]querytypes.ResourceItem, 0) for _, res := range appResList { if res.ResourceTree != nil { - resources = append(resources, buildResourceArray(*res, res.ResourceTree, res.ResourceTree, opt.Filter.Kind, opt.Filter.APIVersion)...) + resources = append(resources, buildResourceArray(res, res.ResourceTree, res.ResourceTree, opt.Filter.Kind, opt.Filter.APIVersion)...) } else if res.Kind == opt.Filter.Kind && res.APIVersion == opt.Filter.APIVersion { - var object unstructured.Unstructured + object := &unstructured.Unstructured{} object.SetAPIVersion(opt.Filter.APIVersion) object.SetKind(opt.Filter.Kind) - if err := h.cli.Get(ctx, apimachinerytypes.NamespacedName{Namespace: res.Namespace, Name: res.Name}, &object); err == nil { - resources = append(resources, buildResourceItem(*res, querytypes.Workload{ + if err := cli.Get(ctx, apimachinerytypes.NamespacedName{Namespace: res.Namespace, Name: res.Name}, object); err == nil { + resources = append(resources, buildResourceItem(res, querytypes.Workload{ APIVersion: app.APIVersion, Kind: app.Kind, Name: app.Name, @@ -177,22 +173,26 @@ func (h *provider) CollectResources(ctx monitorContext.Context, _ wfContext.Cont } } } - return fillQueryResult(v, resources, "list") + return &ListResult[querytypes.ResourceItem]{List: resources}, nil } -func (h *provider) SearchEvents(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - val, err := v.LookupValue("value") - if err != nil { - return err - } - cluster, err := v.GetString("cluster") - if err != nil { - return err - } - obj := new(unstructured.Unstructured) - if err = val.UnmarshalTo(obj); err != nil { - return err +// SearchVars is the vars for search +type SearchVars struct { + Value *unstructured.Unstructured `json:"value"` + Cluster string `json:"cluster"` +} + +// SearchParams is the params for search +type SearchParams = oamprovidertypes.OAMParams[SearchVars] + +// SearchEvents searches events +func SearchEvents(ctx context.Context, params *SearchParams) (*ListResult[corev1.Event], error) { + obj := params.Params.Value + if obj == nil { + return nil, fmt.Errorf("please provide a object value to search events") } + cluster := params.Params.Cluster + cli := params.KubeClient listCtx := multicluster.ContextWithClusterName(ctx, cluster) fieldSelector := getEventFieldSelector(obj) @@ -203,38 +203,47 @@ func (h *provider) SearchEvents(ctx monitorContext.Context, _ wfContext.Context, Selector: fieldSelector, }, } - if err := h.cli.List(listCtx, &eventList, listOpts...); err != nil { - return v.FillObject(err.Error(), "err") + if err := cli.List(listCtx, &eventList, listOpts...); err != nil { + // nolint:nilerr + return &ListResult[corev1.Event]{Error: err.Error()}, nil } - return fillQueryResult(v, eventList.Items, "list") + return &ListResult[corev1.Event]{List: eventList.Items}, nil } -func (h *provider) CollectLogsInPod(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - cluster, err := v.GetString("cluster") - if err != nil { - return errors.Wrapf(err, "invalid cluster") +// LogVars is the vars for log +type LogVars struct { + Cluster string `json:"cluster"` + Namespace string `json:"namespace"` + Pod string `json:"pod"` + Options *corev1.PodLogOptions `json:"options,omitempty"` +} + +// LogParams is the params for log +type LogParams = oamprovidertypes.OAMParams[LogVars] + +// LogResult is the result for log +type LogResult struct { + Outputs map[string]interface{} `json:"outputs"` +} + +// CollectLogsInPod collects logs in pod +func CollectLogsInPod(ctx context.Context, params *LogParams) (*LogResult, error) { + cluster := params.Params.Cluster + namespace := params.Params.Namespace + pod := params.Params.Pod + if pod == "" { + return nil, fmt.Errorf("please provide a pod name to collect logs") } - namespace, err := v.GetString("namespace") - if err != nil { - return errors.Wrapf(err, "invalid namespace") - } - pod, err := v.GetString("pod") - if err != nil { - return errors.Wrapf(err, "invalid pod name") - } - val, err := v.LookupValue("options") - if err != nil { - return errors.Wrapf(err, "invalid log options") - } - opts := &corev1.PodLogOptions{} - if err = val.UnmarshalTo(opts); err != nil { - return errors.Wrapf(err, "invalid log options content") + opts := params.Params.Options + if opts == nil || opts.Container == "" { + return nil, fmt.Errorf("please provide the container name to collect logs") } cliCtx := multicluster.ContextWithClusterName(ctx, cluster) - h.cfg.Wrap(pkgmulticluster.NewTransportWrapper()) - clientSet, err := kubernetes.NewForConfig(h.cfg) + cfg := params.KubeConfig + cfg.Wrap(pkgmulticluster.NewTransportWrapper()) + clientSet, err := kubernetes.NewForConfig(cfg) if err != nil { - return errors.Wrapf(err, "failed to create kubernetes client") + return nil, errors.Wrapf(err, "failed to create kubernetes client") } var defaultOutputs = make(map[string]interface{}) var errMsg string @@ -291,22 +300,30 @@ func (h *provider) CollectLogsInPod(ctx monitorContext.Context, _ wfContext.Cont klog.Warningf(errMsg) defaultOutputs["err"] = errMsg } - return v.FillObject(defaultOutputs, "outputs") + return &LogResult{Outputs: defaultOutputs}, nil } -// Install register handlers to provider discover. -func Install(p types.Providers, cli client.Client, cfg *rest.Config) { - prd := &provider{ - cli: cli, - cfg: cfg, +//go:embed ql.cue +var qlTemplate string + +// GetTemplate returns the cue template. +func GetTemplate() string { + return strings.Join([]string{qlTemplate, kube.GetTemplate()}, "\n") +} + +// GetProviders returns the cue providers. +func GetProviders() map[string]cuexruntime.ProviderFn { + qlProvider := map[string]cuexruntime.ProviderFn{ + "listResourcesInApp": oamprovidertypes.OAMGenericProviderFn[ListVars, ListResult[Resource]](ListResourcesInApp), + "listAppliedResources": oamprovidertypes.OAMGenericProviderFn[ListVars, ListResult[querytypes.AppliedResource]](ListAppliedResources), + "collectResources": oamprovidertypes.OAMGenericProviderFn[ListVars, ListResult[querytypes.ResourceItem]](CollectResources), + "searchEvents": oamprovidertypes.OAMGenericProviderFn[SearchVars, ListResult[corev1.Event]](SearchEvents), + "collectLogsInPod": oamprovidertypes.OAMGenericProviderFn[LogVars, LogResult](CollectLogsInPod), + "collectServiceEndpoints": oamprovidertypes.OAMGenericProviderFn[ListVars, ListResult[querytypes.ServiceEndpoint]](CollectServiceEndpoints), } - - p.Register(ProviderName, map[string]types.Handler{ - "listResourcesInApp": prd.ListResourcesInApp, - "listAppliedResources": prd.ListAppliedResources, - "collectResources": prd.CollectResources, - "searchEvents": prd.SearchEvents, - "collectLogsInPod": prd.CollectLogsInPod, - "collectServiceEndpoints": prd.CollectServiceEndpoints, - }) + kubeProviders := kube.GetProviders() + for k, v := range kubeProviders { + qlProvider[k] = v + } + return qlProvider } diff --git a/pkg/velaql/providers/query/handler_test.go b/pkg/workflow/providers/legacy/query/handler_test.go similarity index 76% rename from pkg/velaql/providers/query/handler_test.go rename to pkg/workflow/providers/legacy/query/handler_test.go index 17bcdedad..d009d2208 100644 --- a/pkg/velaql/providers/query/handler_test.go +++ b/pkg/workflow/providers/legacy/query/handler_test.go @@ -31,21 +31,15 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - monitorContext "github.com/kubevela/pkg/monitor/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/providers" - "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" helmapi "github.com/oam-dev/kubevela/pkg/appfile/helm/flux2apis" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" - verrors "github.com/oam-dev/kubevela/pkg/utils/errors" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) type AppResourcesList struct { @@ -206,31 +200,29 @@ var _ = Describe("Test Query Provider", func() { } Expect(k8sClient.Create(ctx, rt)).Should(BeNil()) - prd := provider{cli: k8sClient} - opt := `app: { - name: "test" - namespace: "test" - filter: { - cluster: "", - clusterNamespace: "test", - components: ["web"] - } - }` - v, err := value.NewValue(opt, nil, "") - Expect(err).Should(BeNil()) - logCtx := monitorContext.NewTraceContext(ctx, "") - Expect(prd.ListResourcesInApp(logCtx, nil, v, nil)).Should(BeNil()) - - appResList := new(AppResourcesList) - Expect(v.UnmarshalTo(appResList)).Should(BeNil()) - if appResList.Err != "" { - klog.Error(appResList.Err) + params := &ListParams{ + Params: ListVars{ + App: Option{ + Name: "test", + Namespace: "test", + Filter: FilterOption{ + Cluster: "", + ClusterNamespace: "test", + Components: []string{"web"}, + }, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + }, } + res, err := ListResourcesInApp(context.Background(), params) + Expect(err).Should(BeNil()) + resList := (*res).List + Expect(len(resList)).Should(Equal(2)) - Expect(len(appResList.List)).Should(Equal(2)) - - Expect(appResList.List[0].Object.GroupVersionKind()).Should(Equal(oldApp.Status.AppliedResources[0].GroupVersionKind())) - Expect(appResList.List[1].Object.GroupVersionKind()).Should(Equal(oldApp.Status.AppliedResources[1].GroupVersionKind())) + Expect(resList[0].Object.GroupVersionKind()).Should(Equal(oldApp.Status.AppliedResources[0].GroupVersionKind())) + Expect(resList[1].Object.GroupVersionKind()).Should(Equal(oldApp.Status.AppliedResources[1].GroupVersionKind())) updateApp := new(v1beta1.Application) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&app), updateApp)).Should(BeNil()) @@ -239,25 +231,12 @@ var _ = Describe("Test Query Provider", func() { oam.AnnotationKubeVelaVersion: "v1.1.0", } Expect(k8sClient.Update(ctx, updateApp)).Should(BeNil()) - newValue, err := value.NewValue(opt, nil, "") + res, err = ListResourcesInApp(context.Background(), params) Expect(err).Should(BeNil()) - Expect(prd.ListResourcesInApp(logCtx, nil, newValue, nil)).Should(BeNil()) - newAppResList := new(AppResourcesList) - Expect(v.UnmarshalTo(newAppResList)).Should(BeNil()) - Expect(len(newAppResList.List)).Should(Equal(2)) - Expect(newAppResList.List[0].Object.GroupVersionKind()).Should(Equal(updateApp.Status.AppliedResources[0].GroupVersionKind())) - Expect(newAppResList.List[1].Object.GroupVersionKind()).Should(Equal(updateApp.Status.AppliedResources[1].GroupVersionKind())) - }) - - It("Test list resource with incomplete parameter", func() { - optWithoutApp := "" - prd := provider{cli: k8sClient} - newV, err := value.NewValue(optWithoutApp, nil, "") - Expect(err).Should(BeNil()) - logCtx := monitorContext.NewTraceContext(ctx, "") - err = prd.ListResourcesInApp(logCtx, nil, newV, nil) - Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) + resList = (*res).List + Expect(len(resList)).Should(Equal(2)) + Expect(resList[0].Object.GroupVersionKind()).Should(Equal(updateApp.Status.AppliedResources[0].GroupVersionKind())) + Expect(resList[1].Object.GroupVersionKind()).Should(Equal(updateApp.Status.AppliedResources[1].GroupVersionKind())) }) }) @@ -333,178 +312,125 @@ var _ = Describe("Test Query Provider", func() { } err := k8sClient.Create(context.TODO(), rt) Expect(err).Should(BeNil()) - prd := provider{cli: k8sClient} - opt := `app: { - name: "test-applied" - namespace: "default" - filter: { - components: ["web"] - } - }` - v, err := value.NewValue(opt, nil, "") - Expect(err).Should(BeNil()) - logCtx := monitorContext.NewTraceContext(ctx, "") - Expect(prd.ListAppliedResources(logCtx, nil, v, nil)).Should(BeNil()) - type Res struct { - List []v1beta1.ManagedResource `json:"list"` + + params := &ListParams{ + Params: ListVars{ + App: Option{ + Name: "test-applied", + Namespace: "default", + Filter: FilterOption{ + Components: []string{"web"}, + }, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + }, } - var res Res - err = v.UnmarshalTo(&res) + res, err := ListAppliedResources(context.Background(), params) Expect(err).Should(BeNil()) - Expect(len(res.List)).Should(Equal(2)) + resList := (*res).List + Expect(len(resList)).Should(Equal(2)) By("test filter with the apiVersion and kind") - optWithVersion := `app: { - name: "test-applied" - namespace: "default" - filter: { - components: ["web"] - apiVersion: "apps/v1" - } - }` - valueWithVersion, err := value.NewValue(optWithVersion, nil, "") + params.Params.App.Filter.APIVersion = "apps/v1" + res2, err := ListAppliedResources(context.Background(), params) Expect(err).Should(BeNil()) - Expect(prd.ListAppliedResources(logCtx, nil, valueWithVersion, nil)).Should(BeNil()) - var res2 Res - err = valueWithVersion.UnmarshalTo(&res2) - Expect(err).Should(BeNil()) - Expect(len(res2.List)).Should(Equal(1)) - Expect(res2.List[0].Kind).Should(Equal("Deployment")) + resList2 := (*res2).List + Expect(len(resList2)).Should(Equal(1)) + Expect(resList2[0].Kind).Should(Equal("Deployment")) - optWithKind := `app: { - name: "test-applied" - namespace: "default" - filter: { - components: ["web"] - kind: "Service" - } - }` - valueWithKind, err := value.NewValue(optWithKind, nil, "") + params.Params.App.Filter.Kind = "Service" + params.Params.App.Filter.APIVersion = "" + res3, err := ListAppliedResources(context.Background(), params) Expect(err).Should(BeNil()) - Expect(prd.ListAppliedResources(logCtx, nil, valueWithKind, nil)).Should(BeNil()) - var res3 Res - err = valueWithKind.UnmarshalTo(&res3) - Expect(err).Should(BeNil()) - Expect(len(res3.List)).Should(Equal(1)) - Expect(res3.List[0].Kind).Should(Equal("Service")) + resList3 := (*res3).List + Expect(len(resList3)).Should(Equal(1)) + Expect(resList3[0].Kind).Should((Equal("Service"))) }) }) Context("Test search event from k8s object", func() { It("Test search event with incomplete parameter", func() { - emptyOpt := "" - prd := provider{cli: k8sClient} - v, err := value.NewValue(emptyOpt, nil, "") - Expect(err).Should(BeNil()) - logCtx := monitorContext.NewTraceContext(ctx, "") - err = prd.SearchEvents(logCtx, nil, v, nil) + _, err := SearchEvents(context.Background(), &SearchParams{}) Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) - optWithoutCluster := `value: {}` - v, err = value.NewValue(optWithoutCluster, nil, "") - Expect(err).Should(BeNil()) - err = prd.SearchEvents(logCtx, nil, v, nil) - Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) - - optWithWrongValue := `value: {} -cluster: "test"` - v, err = value.NewValue(optWithWrongValue, nil, "") - Expect(err).Should(BeNil()) - err = prd.SearchEvents(logCtx, nil, v, nil) + _, err = SearchEvents(context.Background(), &SearchParams{ + Params: SearchVars{ + Cluster: "test", + }, + }) Expect(err).ShouldNot(BeNil()) }) }) Context("Test CollectLogsInPod", func() { It("Test CollectLogsInPod with specified container", func() { - prd := provider{cli: k8sClient, cfg: cfg} pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "hello-world", Namespace: "default"}, Spec: corev1.PodSpec{ Containers: []corev1.Container{{Name: "main", Image: "busybox"}}, }} Expect(k8sClient.Create(ctx, pod)).Should(Succeed()) - logCtx := monitorContext.NewTraceContext(ctx, "") - v, err := value.NewValue(``, nil, "") - Expect(err).Should(Succeed()) - err = prd.CollectLogsInPod(logCtx, nil, v, nil) + _, err := CollectLogsInPod(context.Background(), &LogParams{}) Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) - v, err = value.NewValue(`cluster: "local"`, nil, "") - Expect(err).Should(Succeed()) - err = prd.CollectLogsInPod(logCtx, nil, v, nil) + _, err = CollectLogsInPod(context.Background(), &LogParams{ + Params: LogVars{ + Cluster: "local", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + KubeConfig: cfg, + }, + }) Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) - v, err = value.NewValue(`cluster: "local" -namespace: "default"`, nil, "") - Expect(err).Should(Succeed()) - err = prd.CollectLogsInPod(logCtx, nil, v, nil) + _, err = CollectLogsInPod(context.Background(), &LogParams{ + Params: LogVars{ + Cluster: "local", + Namespace: "default", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + KubeConfig: cfg, + }, + }) Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) - v, err = value.NewValue(`cluster: "local" -namespace: "default" -pod: "hello-world"`, nil, "") - Expect(err).Should(Succeed()) - err = prd.CollectLogsInPod(logCtx, nil, v, nil) + _, err = CollectLogsInPod(context.Background(), &LogParams{ + Params: LogVars{ + Cluster: "local", + Namespace: "default", + Pod: "hello-world", + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + KubeConfig: cfg, + }, + }) Expect(err).ShouldNot(BeNil()) - Expect(verrors.IsCuePathNotFound(err)).Should(BeTrue()) - v, err = value.NewValue(`cluster: "local" -namespace: "default" -pod: "hello-world" -options: { - container: 1 -}`, nil, "") - Expect(err).Should(Succeed()) - err = prd.CollectLogsInPod(logCtx, nil, v, nil) - Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(ContainSubstring("invalid log options content")) - - v, err = value.NewValue(`cluster: "local" -namespace: "default" -pod: "hello-world" -options: { - container: "main" - previous: true - sinceSeconds: 100 - tailLines: 50 -}`, nil, "") - Expect(err).Should(Succeed()) - Expect(prd.CollectLogsInPod(logCtx, nil, v, nil)).Should(Succeed()) - _, err = v.GetString("outputs", "logs") + _, err = CollectLogsInPod(context.Background(), &LogParams{ + Params: LogVars{ + Cluster: "local", + Namespace: "default", + Pod: "hello-world", + Options: &corev1.PodLogOptions{ + Container: "main", + Previous: true, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + KubeConfig: cfg, + }, + }) Expect(err).Should(Succeed()) }) }) - It("Test install provider", func() { - p := providers.NewProviders() - Install(p, k8sClient, cfg) - h, ok := p.GetHandler("query", "listResourcesInApp") - Expect(h).ShouldNot(BeNil()) - Expect(ok).Should(Equal(true)) - h, ok = p.GetHandler("query", "collectResources") - Expect(h).ShouldNot(BeNil()) - Expect(ok).Should(Equal(true)) - l, ok := p.GetHandler("query", "listAppliedResources") - Expect(l).ShouldNot(BeNil()) - Expect(ok).Should(Equal(true)) - h, ok = p.GetHandler("query", "searchEvents") - Expect(ok).Should(Equal(true)) - Expect(h).ShouldNot(BeNil()) - h, ok = p.GetHandler("query", "collectLogsInPod") - Expect(ok).Should(Equal(true)) - Expect(h).ShouldNot(BeNil()) - h, ok = p.GetHandler("query", "collectServiceEndpoints") - Expect(ok).Should(Equal(true)) - Expect(h).ShouldNot(BeNil()) - }) - It("Test generator service endpoints", func() { appsts := common.AppStatus{ AppliedResources: []common.ClusterObjectReference{ @@ -982,23 +908,25 @@ options: { Expect(k8sClient.Create(ctx, masterNode)).Should(BeNil()) Expect(k8sClient.Create(ctx, workerNode)).Should(BeNil()) - opt := `app: { - name: "endpoints-app" - namespace: "default" - filter: { - cluster: "", - clusterNamespace: "default", - } - withTree: true - }` - v, err := value.NewValue(opt, nil, "") - Expect(err).Should(BeNil()) - pr := &provider{ - cli: k8sClient, + params := &ListParams{ + Params: ListVars{ + App: Option{ + Name: "endpoints-app", + Namespace: "default", + Filter: FilterOption{ + Cluster: "", + ClusterNamespace: "default", + }, + WithTree: true, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + }, } - logCtx := monitorContext.NewTraceContext(ctx, "") - err = pr.CollectServiceEndpoints(logCtx, nil, v, nil) + res, err := CollectServiceEndpoints(context.Background(), params) Expect(err).Should(BeNil()) + gatewayIP := selectorNodeIP(ctx, "", k8sClient) Expect(gatewayIP).Should(Equal("external-ip-2")) urls := []string{ @@ -1018,14 +946,7 @@ options: { "http://gateway.domain/api", "https://demo.kubevela.net", } - endValue, err := v.Field("list") - Expect(err).Should(BeNil()) - var endpoints []querytypes.ServiceEndpoint - err = endValue.Decode(&endpoints) - Expect(err).Should(BeNil()) - Expect(len(urls)).Should(Equal(len(endpoints))) - for i, e := range endpoints { - fmt.Println(e.String()) + for i, e := range (*res).List { Expect(urls[i]).Should(Equal(e.String())) } }) diff --git a/pkg/stdlib/pkgs/query.cue b/pkg/workflow/providers/legacy/query/ql.cue similarity index 95% rename from pkg/stdlib/pkgs/query.cue rename to pkg/workflow/providers/legacy/query/ql.cue index 1200dd037..4a750d599 100644 --- a/pkg/stdlib/pkgs/query.cue +++ b/pkg/workflow/providers/legacy/query/ql.cue @@ -1,6 +1,6 @@ #ListResourcesInApp: { #do: "listResourcesInApp" - #provider: "query" + #provider: "ql" app: { name: string namespace: string @@ -24,7 +24,7 @@ #ListAppliedResources: { #do: "listAppliedResources" - #provider: "query" + #provider: "ql" app: { name: string namespace: string @@ -59,7 +59,7 @@ #CollectPods: { #do: "collectResources" - #provider: "query" + #provider: "ql" app: { name: string namespace: string @@ -78,7 +78,7 @@ #CollectServices: { #do: "collectResources" - #provider: "query" + #provider: "ql" app: { name: string namespace: string @@ -97,7 +97,7 @@ #SearchEvents: { #do: "searchEvents" - #provider: "query" + #provider: "ql" value: {...} cluster: string ... @@ -105,7 +105,7 @@ #CollectLogsInPod: { #do: "collectLogsInPod" - #provider: "query" + #provider: "ql" cluster: string namespace: string pod: string @@ -132,7 +132,7 @@ #CollectServiceEndpoints: { #do: "collectServiceEndpoints" - #provider: "query" + #provider: "ql" app: { name: string namespace: string @@ -163,7 +163,7 @@ #GetApplicationTree: { #do: "listAppliedResources" - #provider: "query" + #provider: "ql" app: { name: string namespace: string diff --git a/pkg/velaql/providers/query/suite_test.go b/pkg/workflow/providers/legacy/query/suite_test.go similarity index 97% rename from pkg/velaql/providers/query/suite_test.go rename to pkg/workflow/providers/legacy/query/suite_test.go index 18c19ac0f..930234bed 100644 --- a/pkg/velaql/providers/query/suite_test.go +++ b/pkg/workflow/providers/legacy/query/suite_test.go @@ -46,7 +46,7 @@ var _ = BeforeSuite(func() { UseExistingCluster: pointer.Bool(false), CRDDirectoryPaths: []string{ "./testdata/gateway/crds", - "../../../../charts/vela-core/crds", + "../../../../../charts/vela-core/crds", "./testdata/machinelearning.seldon.io_seldondeployments.yaml", "./testdata/helm-release-crd.yaml", }, @@ -65,7 +65,6 @@ var _ = BeforeSuite(func() { batchv1.AddToScheme(scheme) k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) - Expect(err).Should(BeNil()) Expect(k8sClient).ToNot(BeNil()) diff --git a/pkg/velaql/providers/query/testdata/gateway/crds/gateway.networking.k8s.io_gateways.yaml b/pkg/workflow/providers/legacy/query/testdata/gateway/crds/gateway.networking.k8s.io_gateways.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/gateway/crds/gateway.networking.k8s.io_gateways.yaml rename to pkg/workflow/providers/legacy/query/testdata/gateway/crds/gateway.networking.k8s.io_gateways.yaml diff --git a/pkg/velaql/providers/query/testdata/gateway/crds/gateway.networking.k8s.io_httproutes.yaml b/pkg/workflow/providers/legacy/query/testdata/gateway/crds/gateway.networking.k8s.io_httproutes.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/gateway/crds/gateway.networking.k8s.io_httproutes.yaml rename to pkg/workflow/providers/legacy/query/testdata/gateway/crds/gateway.networking.k8s.io_httproutes.yaml diff --git a/pkg/velaql/providers/query/testdata/gateway/gateway-tls.yaml b/pkg/workflow/providers/legacy/query/testdata/gateway/gateway-tls.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/gateway/gateway-tls.yaml rename to pkg/workflow/providers/legacy/query/testdata/gateway/gateway-tls.yaml diff --git a/pkg/velaql/providers/query/testdata/gateway/gateway.yaml b/pkg/workflow/providers/legacy/query/testdata/gateway/gateway.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/gateway/gateway.yaml rename to pkg/workflow/providers/legacy/query/testdata/gateway/gateway.yaml diff --git a/pkg/velaql/providers/query/testdata/gateway/http-route.yaml b/pkg/workflow/providers/legacy/query/testdata/gateway/http-route.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/gateway/http-route.yaml rename to pkg/workflow/providers/legacy/query/testdata/gateway/http-route.yaml diff --git a/pkg/velaql/providers/query/testdata/gateway/https-route.yaml b/pkg/workflow/providers/legacy/query/testdata/gateway/https-route.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/gateway/https-route.yaml rename to pkg/workflow/providers/legacy/query/testdata/gateway/https-route.yaml diff --git a/pkg/velaql/providers/query/testdata/helm-release-crd.yaml b/pkg/workflow/providers/legacy/query/testdata/helm-release-crd.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/helm-release-crd.yaml rename to pkg/workflow/providers/legacy/query/testdata/helm-release-crd.yaml diff --git a/pkg/velaql/providers/query/testdata/machinelearning.seldon.io_seldondeployments.yaml b/pkg/workflow/providers/legacy/query/testdata/machinelearning.seldon.io_seldondeployments.yaml similarity index 100% rename from pkg/velaql/providers/query/testdata/machinelearning.seldon.io_seldondeployments.yaml rename to pkg/workflow/providers/legacy/query/testdata/machinelearning.seldon.io_seldondeployments.yaml diff --git a/pkg/velaql/providers/query/tree.go b/pkg/workflow/providers/legacy/query/tree.go similarity index 99% rename from pkg/velaql/providers/query/tree.go rename to pkg/workflow/providers/legacy/query/tree.go index a7f97e328..852a812bc 100644 --- a/pkg/velaql/providers/query/tree.go +++ b/pkg/workflow/providers/legacy/query/tree.go @@ -44,7 +44,7 @@ import ( velatypes "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" helmreleaseapi "github.com/fluxcd/helm-controller/api/v2beta1" helmrepoapi "github.com/fluxcd/source-controller/api/v1beta2" @@ -969,6 +969,7 @@ func iterateListSubResources(ctx context.Context, cluster string, k8sClient clie return nil, err } for i, item := range items { + current := items[i] rtn := types.ResourceTreeNode{ APIVersion: item.GetAPIVersion(), Kind: item.GroupVersionKind().Kind, @@ -976,7 +977,7 @@ func iterateListSubResources(ctx context.Context, cluster string, k8sClient clie Name: item.GetName(), UID: item.GetUID(), Cluster: cluster, - Object: items[i], + Object: ¤t, } if _, ok := globalRule.GetRule(GroupResourceType{Group: item.GetObjectKind().GroupVersionKind().Group, Kind: item.GetObjectKind().GroupVersionKind().Kind}); ok { childrenRes, err := iterateListSubResources(ctx, cluster, k8sClient, rtn, depth+1, filter) diff --git a/pkg/velaql/providers/query/tree_test.go b/pkg/workflow/providers/legacy/query/tree_test.go similarity index 97% rename from pkg/velaql/providers/query/tree_test.go rename to pkg/workflow/providers/legacy/query/tree_test.go index 59568fe51..17642da78 100644 --- a/pkg/velaql/providers/query/tree_test.go +++ b/pkg/workflow/providers/legacy/query/tree_test.go @@ -39,15 +39,13 @@ import ( "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" - monitorContext "github.com/kubevela/pkg/monitor/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" types3 "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) func TestPodStatus(t *testing.T) { @@ -1692,23 +1690,20 @@ var _ = Describe("unit-test to e2e test", func() { Expect(k8sClient.Create(ctx, &app)).Should(BeNil()) Expect(k8sClient.Create(ctx, &rt)).Should(BeNil()) - prd := provider{cli: k8sClient} - opt := `app: { - name: "app" - namespace: "test-namespace" - withTree: true - }` - v, err := value.NewValue(opt, nil, "") + res, err := ListAppliedResources(context.Background(), &ListParams{ + Params: ListVars{ + App: Option{ + Name: "app", + Namespace: "test-namespace", + WithTree: true, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + }, + }) Expect(err).Should(BeNil()) - logCtx := monitorContext.NewTraceContext(ctx, "") - Expect(prd.ListAppliedResources(logCtx, nil, v, nil)).Should(BeNil()) - type Res struct { - List []types.AppliedResource `json:"list"` - } - var res Res - err = v.UnmarshalTo(&res) - Expect(err).Should(BeNil()) - Expect(len(res.List)).Should(Equal(2)) + Expect(len((*res).List)).Should(Equal(2)) }) It("Test not exist api don't break whole process", func() { @@ -1747,24 +1742,20 @@ var _ = Describe("unit-test to e2e test", func() { // clear after test objectList = append(objectList, &badRuleConfigMap) - prd := provider{cli: k8sClient} - opt := `app: { - name: "app" - namespace: "test-namespace" - withTree: true - }` - v, err := value.NewValue(opt, nil, "") - + res, err := ListAppliedResources(context.Background(), &ListParams{ + Params: ListVars{ + App: Option{ + Name: "app", + Namespace: "test-namespace", + WithTree: true, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + KubeClient: k8sClient, + }, + }) Expect(err).Should(BeNil()) - logCtx := monitorContext.NewTraceContext(ctx, "") - Expect(prd.ListAppliedResources(logCtx, nil, v, nil)).Should(BeNil()) - type Res struct { - List []types.AppliedResource `json:"list"` - } - var res Res - err = v.UnmarshalTo(&res) - Expect(err).Should(BeNil()) - Expect(len(res.List)).Should(Equal(2)) + Expect(len((*res).List)).Should(Equal(2)) }) }) diff --git a/pkg/velaql/providers/query/utils.go b/pkg/workflow/providers/legacy/query/utils.go similarity index 73% rename from pkg/velaql/providers/query/utils.go rename to pkg/workflow/providers/legacy/query/utils.go index ec33f1f61..1907f8a31 100644 --- a/pkg/velaql/providers/query/utils.go +++ b/pkg/workflow/providers/legacy/query/utils.go @@ -17,34 +17,12 @@ package query import ( - "encoding/json" - - cuejson "cuelang.org/go/pkg/encoding/json" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/pkg/oam" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" ) -// fillQueryResult help fill query result which contains k8s object to *value.Value -func fillQueryResult(v *value.Value, res interface{}, paths ...string) error { - b, err := json.Marshal(res) - if err != nil { - return v.FillObject(err, "err") - } - expr, err := cuejson.Unmarshal(b) - if err != nil { - return v.FillObject(err, "err") - } - err = v.FillObject(expr, paths...) - if err != nil { - return err - } - return v.Error() -} - func buildResourceArray(res querytypes.AppliedResource, parent, node *querytypes.ResourceTreeNode, kind string, apiVersion string) (pods []querytypes.ResourceItem) { if node.LeafNodes != nil { for _, subNode := range node.LeafNodes { @@ -61,7 +39,7 @@ func buildResourceArray(res querytypes.AppliedResource, parent, node *querytypes return } -func buildResourceItem(res querytypes.AppliedResource, workload querytypes.Workload, object unstructured.Unstructured) querytypes.ResourceItem { +func buildResourceItem(res querytypes.AppliedResource, workload querytypes.Workload, object *unstructured.Unstructured) querytypes.ResourceItem { return querytypes.ResourceItem{ Cluster: res.Cluster, Workload: workload, diff --git a/pkg/workflow/providers/legacy/query/utils_test.go b/pkg/workflow/providers/legacy/query/utils_test.go new file mode 100644 index 000000000..31708704c --- /dev/null +++ b/pkg/workflow/providers/legacy/query/utils_test.go @@ -0,0 +1,17 @@ +/* + Copyright 2022. The KubeVela Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package query diff --git a/pkg/stdlib/pkgs/terraform.cue b/pkg/workflow/providers/legacy/terraform/terraform.cue similarity index 81% rename from pkg/stdlib/pkgs/terraform.cue rename to pkg/workflow/providers/legacy/terraform/terraform.cue index 1e800d085..2c0b49a9a 100644 --- a/pkg/stdlib/pkgs/terraform.cue +++ b/pkg/workflow/providers/legacy/terraform/terraform.cue @@ -1,14 +1,16 @@ +// terraform.cue + #LoadTerraformComponents: { - #provider: "terraform" + #provider: "op" #do: "load-terraform-components" outputs: { - components: [...multicluster.#Component] + components: [...#Component] } } #GetConnectionStatus: { - #provider: "terraform" + #provider: "op" #do: "get-connection-status" inputs: { @@ -20,7 +22,7 @@ } } -#PrepareTerraformEnvBinding: #Steps & { +#PrepareTerraformEnvBinding: { inputs: { env: string policy: string @@ -28,20 +30,20 @@ env_: inputs.env policy_: inputs.policy - prepare: multicluster.#PrepareEnvBinding & { + prepare: #PrepareEnvBinding & { inputs: { env: env_ policy: policy_ } - } @step(1) - loadTerraformComponents: #LoadTerraformComponents @step(2) + } + loadTerraformComponents: #LoadTerraformComponents terraformComponentMap: { for _, comp in loadTerraformComponents.outputs.components { - "\(comp.name)": comp + (comp.name): comp } ... } - components_: [ for comp in prepare.outputs.components if terraformComponentMap["\(comp.name)"] != _|_ {comp}] + components_: [ for comp in prepare.outputs.components if terraformComponentMap[(comp.name)] != _|_ {comp}] outputs: { components: components_ decisions: prepare.outputs.decisions @@ -54,7 +56,7 @@ name: string namespace: string env: string - if component.properties != _|_ && component.properties.writeConnectionSecretToRef != _|_ { + if component.properties != _|_ if component.properties.writeConnectionSecretToRef != _|_ { if component.properties.writeConnectionSecretToRef.name != _|_ { name: component.properties.writeConnectionSecretToRef.name } @@ -71,17 +73,17 @@ envName: "\(name)-\(env)" } -#bindTerraformComponentToCluster: #Steps & { +#bindTerraformComponentToCluster: { comp: {...} secret: {...} env: string decisions: [...{...}] - status: terraform.#GetConnectionStatus & { + status: #GetConnectionStatus & { inputs: componentName: "\(comp.name)-\(env)" - } @step(1) + } - read: kube.#Read & { + read: #Read & { value: { apiVersion: "v1" kind: "Secret" @@ -92,16 +94,15 @@ } ... } - } @step(2) + } - wait: { - #do: "wait" + wait: #ConditionalWait & { continue: status.outputs.healthy && read.err == _|_ - } @step(3) + } - sync: #Steps & { + sync: { for decision in decisions { - "\(decision.cluster)-\(decision.namespace)": kube.#Apply & { + "\(decision.cluster)-\(decision.namespace)": #Apply & { cluster: decision.cluster value: { apiVersion: "v1" @@ -122,12 +123,10 @@ } } } - } @step(4) + } } #DeployCloudResource: { - #do: "steps" - env: string name: string policy: string @@ -140,11 +139,11 @@ env: env_ policy: policy_ } - } @step(1) + } - deploy: #Steps & { + deploy: { for comp in prepareDeploy.outputs.components { - "\(comp.name)": #Steps & { + (comp.name): { secretMeta: #loadSecretInfo & { component: comp @@ -163,7 +162,7 @@ if comp.properties != _|_ { for k, v in comp.properties { if k != "writeConnectionSecretToRef" { - "\(k)": v + (k): v } } } @@ -171,12 +170,12 @@ } for k, v in comp { if k != "name" && k != "properties" { - "\(k)": v + (k): v } } ... } - } @step(1) + } comp_: comp bind: #bindTerraformComponentToCluster & { @@ -184,16 +183,16 @@ secret: secretMeta env: env_ decisions: prepareDeploy.outputs.decisions - } @step(2) + } secret: bind.read.value - update: kube.#Apply & { + update: #Apply & { value: { metadata: { for k, v in secret.metadata { if k != "labels" { - "\(k)": v + (k): v } } labels: { @@ -205,7 +204,7 @@ if secret.metadata.labels != _|_ { for k, v in secret.metadata.labels { if k != "app.oam.dev/name" && k != "app.oam.dev/sync-alias" && k != "app.oam.dev/env-name" { - "\(k)": v + (k): v } } } @@ -214,27 +213,25 @@ } for k, v in secret { if k != "metadata" { - "\(k)": v + (k): v } } ... } - } @step(6) + } } } ... - } @step(2) + } } #ShareCloudResource: { - #do: "steps" - env: string name: string policy: string namespace: string namespace_: namespace - placements: [...multicluster.#PlacementDecision] + placements: [...#PlacementDecision] env_: env policy_: policy @@ -243,7 +240,7 @@ env: env_ policy: policy_ } - } @step(1) + } decisions_: [ for placement in placements { namespace: *"" | string @@ -259,9 +256,9 @@ } }] - deploy: #Steps & { + deploy: { for comp in prepareBind.outputs.components { - "\(comp.name)": #Steps & { + (comp.name): { secretMeta: #loadSecretInfo & { component: comp env: env_ @@ -273,8 +270,8 @@ secret: secretMeta env: env_ decisions: decisions_ - } @step(1) + } } } - } @step(2) + } } diff --git a/pkg/workflow/providers/legacy/terraform/terraform.go b/pkg/workflow/providers/legacy/terraform/terraform.go new file mode 100644 index 000000000..2fca9a5fb --- /dev/null +++ b/pkg/workflow/providers/legacy/terraform/terraform.go @@ -0,0 +1,125 @@ +/* +Copyright 2021 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package terraform + +import ( + "context" + _ "embed" + "fmt" + + "github.com/pkg/errors" + + cuexruntime "github.com/kubevela/pkg/cue/cuex/runtime" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/common" + "github.com/oam-dev/kubevela/apis/types" + + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" +) + +// Outputs is the output parameters for Terraform components. +type Outputs[T any] struct { + Outputs T `json:"outputs"` +} + +// Inputs is the input parameters for Terraform components. +type Inputs[T any] struct { + Inputs T `json:"inputs"` +} + +// ComponentVars is the input parameters for LoadTerraformComponents. +type ComponentVars struct { + Components []common.ApplicationComponent `json:"components"` +} + +// ComponentReturns is the return value for LoadTerraformComponents. +type ComponentReturns = Outputs[ComponentVars] + +// LoadTerraformComponents loads Terraform components. +func LoadTerraformComponents(ctx context.Context, params *oamprovidertypes.OAMParams[any]) (*ComponentReturns, error) { + res := &ComponentReturns{ + Outputs: ComponentVars{ + Components: make([]common.ApplicationComponent, 0), + }, + } + for _, comp := range params.App.Spec.Components { + wl, err := params.WorkloadRender(ctx, comp) + if err != nil { + return nil, errors.Wrapf(err, "failed to render component into workload") + } + if wl.CapabilityCategory != types.TerraformCategory { + continue + } + res.Outputs.Components = append(res.Outputs.Components, comp) + } + return res, nil +} + +// ComponentNameVars is the input parameters for GetConnectionStatus. +type ComponentNameVars struct { + ComponentName string `json:"componentName"` +} + +// ConnectionParams is the input parameters for GetConnectionStatus. +type ConnectionParams = oamprovidertypes.OAMParams[Inputs[ComponentNameVars]] + +// ConnectionResult is the result for connection status. +type ConnectionResult struct { + Healthy bool `json:"healthy"` +} + +// ConnectionReturns is the return value for connection status. +type ConnectionReturns = Outputs[ConnectionResult] + +// GetConnectionStatus returns the connection status of a component. +func GetConnectionStatus(_ context.Context, params *ConnectionParams) (*ConnectionReturns, error) { + app := params.RuntimeParams.App + componentName := params.Params.Inputs.ComponentName + if componentName == "" { + return nil, fmt.Errorf("componentName is required") + } + for _, svc := range app.Status.Services { + if svc.Name == componentName { + return &ConnectionReturns{ + Outputs: ConnectionResult{ + Healthy: svc.Healthy, + }, + }, nil + } + } + return &ConnectionReturns{ + Outputs: ConnectionResult{ + Healthy: false, + }, + }, nil +} + +//go:embed terraform.cue +var template string + +// GetTemplate returns the cue template. +func GetTemplate() string { + return template +} + +// GetProviders returns the cue providers. +func GetProviders() map[string]cuexruntime.ProviderFn { + return map[string]cuexruntime.ProviderFn{ + "load-terraform-components": oamprovidertypes.OAMGenericProviderFn[any, ComponentReturns](LoadTerraformComponents), + "get-connection-status": oamprovidertypes.OAMGenericProviderFn[Inputs[ComponentNameVars], ConnectionReturns](GetConnectionStatus), + } +} diff --git a/pkg/workflow/providers/terraform/terraform_test.go b/pkg/workflow/providers/legacy/terraform/terraform_test.go similarity index 56% rename from pkg/workflow/providers/terraform/terraform_test.go rename to pkg/workflow/providers/legacy/terraform/terraform_test.go index 246771723..4e55bb778 100644 --- a/pkg/workflow/providers/terraform/terraform_test.go +++ b/pkg/workflow/providers/legacy/terraform/terraform_test.go @@ -18,19 +18,20 @@ package terraform import ( "context" + "errors" "strings" "testing" - "github.com/pkg/errors" "github.com/stretchr/testify/require" - - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/mock" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" apicommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/appfile" + oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/types" ) func fakeWorkloadRenderer(_ context.Context, comp apicommon.ApplicationComponent) (*appfile.Component, error) { @@ -45,45 +46,74 @@ func fakeWorkloadRenderer(_ context.Context, comp apicommon.ApplicationComponent func TestLoadTerraformComponents(t *testing.T) { r := require.New(t) + ctx := context.Background() + scheme := runtime.NewScheme() + r.NoError(v1beta1.AddToScheme(scheme)) + cli := fake.NewClientBuilder().WithScheme(scheme).Build() + terraformCD := &v1beta1.ComponentDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "terraform"}, + Spec: v1beta1.ComponentDefinitionSpec{ + Schematic: &apicommon.Schematic{ + Terraform: &apicommon.Terraform{}, + }, + }, + } + require.NoError(t, cli.Create(ctx, terraformCD)) + cueCD := &v1beta1.ComponentDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "cue"}, + Spec: v1beta1.ComponentDefinitionSpec{ + Schematic: &apicommon.Schematic{ + CUE: &apicommon.CUE{}, + }, + }, + } + require.NoError(t, cli.Create(ctx, cueCD)) + testCases := []struct { Inputs []apicommon.ApplicationComponent HasError bool Outputs []apicommon.ApplicationComponent - }{{ - Inputs: []apicommon.ApplicationComponent{{Name: "error"}}, - HasError: true, - }, { - Inputs: []apicommon.ApplicationComponent{{Name: "terraform-1"}, {Name: "cue"}, {Name: "terraform-2"}}, - Outputs: []apicommon.ApplicationComponent{{Name: "terraform-1"}, {Name: "terraform-2"}}, - }, { - Inputs: []apicommon.ApplicationComponent{{Name: "cue"}}, - Outputs: []apicommon.ApplicationComponent{}, - }} + }{ + { + Inputs: []apicommon.ApplicationComponent{{Name: "error"}}, + HasError: true, + }, + { + Inputs: []apicommon.ApplicationComponent{ + {Name: "terraform-1", Type: "terraform"}, + {Name: "cue", Type: "cue"}, + {Name: "terraform-2", Type: "terraform"}, + }, + Outputs: []apicommon.ApplicationComponent{ + {Name: "terraform-1", Type: "terraform"}, + {Name: "terraform-2", Type: "terraform"}, + }, + }, + { + Inputs: []apicommon.ApplicationComponent{{Name: "cue", Type: "cue"}}, + Outputs: []apicommon.ApplicationComponent{}, + }, + } for _, testCase := range testCases { app := &v1beta1.Application{} app.Spec.Components = testCase.Inputs - p := &provider{ - app: app, - renderer: fakeWorkloadRenderer, - } - act := &mock.Action{} - v, err := value.NewValue("", nil, "") - r.NoError(err) - err = p.LoadTerraformComponents(nil, nil, v, act) + res, err := LoadTerraformComponents(ctx, &oamprovidertypes.OAMParams[any]{ + RuntimeParams: oamprovidertypes.RuntimeParams{ + WorkloadRender: fakeWorkloadRenderer, + App: app, + }, + }) if testCase.HasError { r.Error(err) continue } r.NoError(err) - outputs, err := v.LookupValue("outputs", "components") - r.NoError(err) - var comps []apicommon.ApplicationComponent - r.NoError(outputs.UnmarshalTo(&comps)) - r.Equal(testCase.Outputs, comps) + r.Equal(testCase.Outputs, res.Outputs.Components) } } func TestGetConnectionStatus(t *testing.T) { + ctx := context.Background() r := require.New(t) testCases := []struct { ComponentName string @@ -92,7 +122,7 @@ func TestGetConnectionStatus(t *testing.T) { Error string }{{ ComponentName: "", - Error: "failed to get component name", + Error: "componentName is required", }, { ComponentName: "comp", Services: []apicommon.ApplicationComponentStatus{{ @@ -124,25 +154,22 @@ func TestGetConnectionStatus(t *testing.T) { for _, testCase := range testCases { app := &v1beta1.Application{} app.Status.Services = testCase.Services - p := &provider{ - app: app, - renderer: fakeWorkloadRenderer, - } - act := &mock.Action{} - v, err := value.NewValue("", nil, "") - r.NoError(err) - if testCase.ComponentName != "" { - r.NoError(v.FillObject(map[string]string{"componentName": testCase.ComponentName}, "inputs")) - } - err = p.GetConnectionStatus(nil, nil, v, act) + res, err := GetConnectionStatus(ctx, &ConnectionParams{ + Params: Inputs[ComponentNameVars]{ + Inputs: ComponentNameVars{ + ComponentName: testCase.ComponentName, + }, + }, + RuntimeParams: oamprovidertypes.RuntimeParams{ + App: app, + }, + }) if testCase.Error != "" { r.Error(err) r.Contains(err.Error(), testCase.Error) continue } r.NoError(err) - healthy, err := v.GetBool("outputs", "healthy") - r.NoError(err) - r.Equal(testCase.Healthy, healthy) + r.Equal(testCase.Healthy, res.Outputs.Healthy) } } diff --git a/pkg/workflow/providers/legacy/types/types.go b/pkg/workflow/providers/legacy/types/types.go new file mode 100644 index 000000000..5c4556578 --- /dev/null +++ b/pkg/workflow/providers/legacy/types/types.go @@ -0,0 +1,180 @@ +/* +Copyright 2022 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "context" + "encoding/json" + + "cuelang.org/go/cue" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/kubevela/pkg/util/singleton" + providertypes "github.com/kubevela/workflow/pkg/providers/types" + "github.com/kubevela/workflow/pkg/types" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/common" + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/pkg/appfile" + "github.com/oam-dev/kubevela/pkg/config" +) + +// ComponentApply apply oam component. +type ComponentApply func(ctx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) + +// ComponentRender render oam component. +type ComponentRender func(ctx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) + +// ComponentHealthCheck health check oam component. +type ComponentHealthCheck func(ctx context.Context, comp common.ApplicationComponent, patcher *cue.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) + +// WorkloadRender render application component into workload +type WorkloadRender func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) + +const ( + componentApplyKey providertypes.ContextKey = "componentApply" + componentRenderKey providertypes.ContextKey = "componentRender" + componentHealthCheckKey providertypes.ContextKey = "componentHealthCheck" + workloadRenderKey providertypes.ContextKey = "workloadRender" + appKey providertypes.ContextKey = "app" + appfileKey providertypes.ContextKey = "appfile" + configFactoryKey providertypes.ContextKey = "configFactory" + kubeconfigKey providertypes.ContextKey = "kubeconfig" +) + +// RuntimeParams is the params for runtime +type RuntimeParams struct { + ComponentApply ComponentApply + ComponentRender ComponentRender + ComponentHealthCheck ComponentHealthCheck + WorkloadRender WorkloadRender + App *v1beta1.Application + AppLabels map[string]string + Appfile *appfile.Appfile + Action types.Action + ConfigFactory config.Factory + KubeHandlers *providertypes.KubeHandlers + KubeClient client.Client + KubeConfig *rest.Config +} + +// OAMParams is the legacy oam input parameters of a provider. +type OAMParams[T any] struct { + Params T + RuntimeParams +} + +// OAMGenericProviderFn is the legacy oam provider function +type OAMGenericProviderFn[T any, U any] func(context.Context, *OAMParams[T]) (*U, error) + +// Call marshal value into json and decode into underlying function input +// parameters, then fill back the returned output value +func (fn OAMGenericProviderFn[T, U]) Call(ctx context.Context, value cue.Value) (cue.Value, error) { + params := new(T) + bs, err := value.MarshalJSON() + if err != nil { + return value, err + } + if err = json.Unmarshal(bs, params); err != nil { + return value, err + } + runtimeParams := RuntimeParamsFrom(ctx) + ret, err := fn(ctx, &OAMParams[T]{Params: *params, RuntimeParams: runtimeParams}) + if err != nil { + return value, err + } + return value.FillPath(cue.ParsePath(""), ret), nil +} + +// OAMNativeProviderFn is the legacy oam native provider function +type OAMNativeProviderFn func(context.Context, *OAMParams[cue.Value]) (cue.Value, error) + +// Call marshal value into json and decode into underlying function input +// parameters, then fill back the returned output value +func (fn OAMNativeProviderFn) Call(ctx context.Context, value cue.Value) (cue.Value, error) { + runtimeParams := RuntimeParamsFrom(ctx) + return fn(ctx, &OAMParams[cue.Value]{Params: value, RuntimeParams: runtimeParams}) +} + +// WithRuntimeParams returns a copy of parent in which the runtime params value is set +func WithRuntimeParams(parent context.Context, params RuntimeParams) context.Context { + ctx := context.WithValue(parent, componentApplyKey, params.ComponentApply) + ctx = context.WithValue(ctx, componentRenderKey, params.ComponentRender) + ctx = context.WithValue(ctx, componentHealthCheckKey, params.ComponentHealthCheck) + ctx = context.WithValue(ctx, workloadRenderKey, params.WorkloadRender) + + ctx = context.WithValue(ctx, appKey, params.App) + ctx = context.WithValue(ctx, providertypes.LabelsKey, params.AppLabels) + ctx = context.WithValue(ctx, appfileKey, params.Appfile) + + ctx = context.WithValue(ctx, providertypes.KubeHandlersKey, params.KubeHandlers) + ctx = context.WithValue(ctx, providertypes.ActionKey, params.Action) + ctx = context.WithValue(ctx, configFactoryKey, params.ConfigFactory) + + ctx = context.WithValue(ctx, providertypes.KubeClientKey, params.KubeClient) + ctx = context.WithValue(ctx, kubeconfigKey, params.KubeConfig) + + return ctx +} + +// RuntimeParamsFrom returns the runtime params value stored in ctx, if any. +func RuntimeParamsFrom(ctx context.Context) RuntimeParams { + params := RuntimeParams{} + if apply, ok := ctx.Value(componentApplyKey).(ComponentApply); ok { + params.ComponentApply = apply + } + if render, ok := ctx.Value(componentRenderKey).(ComponentRender); ok { + params.ComponentRender = render + } + if healthCheck, ok := ctx.Value(componentHealthCheckKey).(ComponentHealthCheck); ok { + params.ComponentHealthCheck = healthCheck + } + if workloadRender, ok := ctx.Value(workloadRenderKey).(WorkloadRender); ok { + params.WorkloadRender = workloadRender + } + if app, ok := ctx.Value(appKey).(*v1beta1.Application); ok { + params.App = app + } + if appLabels, ok := ctx.Value(providertypes.LabelsKey).(map[string]string); ok { + params.AppLabels = appLabels + } + if appfile, ok := ctx.Value(appfileKey).(*appfile.Appfile); ok { + params.Appfile = appfile + } + if kubeHanlders, ok := ctx.Value(providertypes.KubeHandlersKey).(*providertypes.KubeHandlers); ok { + params.KubeHandlers = kubeHanlders + } + if action, ok := ctx.Value(providertypes.ActionKey).(types.Action); ok { + params.Action = action + } + if configFactory, ok := ctx.Value(configFactoryKey).(config.Factory); ok { + params.ConfigFactory = configFactory + } + if kubeClient, ok := ctx.Value(providertypes.KubeClientKey).(client.Client); ok { + params.KubeClient = kubeClient + } else { + params.KubeClient = singleton.KubeClient.Get() + } + if kubeConfig, ok := ctx.Value(kubeconfigKey).(*rest.Config); ok { + params.KubeConfig = kubeConfig + } else { + params.KubeConfig = singleton.KubeConfig.Get() + } + return params +} diff --git a/pkg/workflow/providers/multicluster/multicluster.go b/pkg/workflow/providers/multicluster/multicluster.go deleted file mode 100644 index f4ff7c3d8..000000000 --- a/pkg/workflow/providers/multicluster/multicluster.go +++ /dev/null @@ -1,198 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package multicluster - -import ( - "github.com/pkg/errors" - "sigs.k8s.io/controller-runtime/pkg/client" - - monitorContext "github.com/kubevela/pkg/monitor/context" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - wfTypes "github.com/kubevela/workflow/pkg/types" - - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/appfile" - "github.com/oam-dev/kubevela/pkg/multicluster" - pkgpolicy "github.com/oam-dev/kubevela/pkg/policy" - "github.com/oam-dev/kubevela/pkg/policy/envbinding" - oamProvider "github.com/oam-dev/kubevela/pkg/workflow/providers/oam" -) - -const ( - // ProviderName is provider name for install. - ProviderName = "multicluster" -) - -type provider struct { - client.Client - app *v1beta1.Application - af *appfile.Appfile - apply oamProvider.ComponentApply - healthCheck oamProvider.ComponentHealthCheck - renderer oamProvider.WorkloadRenderer -} - -// MakePlacementDecisions -// Deprecated -func (p *provider) MakePlacementDecisions(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - policy, err := v.GetString("inputs", "policyName") - if err != nil { - return err - } - env, err := v.GetString("inputs", "envName") - if err != nil { - return err - } - val, err := v.LookupValue("inputs", "placement") - if err != nil { - return err - } - - // TODO detect env change - placement := &v1alpha1.EnvPlacement{} - if err = val.UnmarshalTo(placement); err != nil { - return errors.Wrapf(err, "failed to parse placement while making placement decision") - } - - var namespace, clusterName string - // check if namespace selector is valid - if placement.NamespaceSelector != nil { - if len(placement.NamespaceSelector.Labels) != 0 { - return errors.Errorf("invalid env %s: namespace selector in cluster-gateway does not support label selector for now", env) - } - namespace = placement.NamespaceSelector.Name - } - // check if cluster selector is valid - if placement.ClusterSelector != nil { - if len(placement.ClusterSelector.Labels) != 0 { - return errors.Errorf("invalid env %s: cluster selector does not support label selector for now", env) - } - clusterName = placement.ClusterSelector.Name - } - // set fallback cluster - if clusterName == "" { - clusterName = multicluster.ClusterLocalName - } - // check if target cluster exists - if clusterName != multicluster.ClusterLocalName { - if _, err := multicluster.GetVirtualCluster(ctx, p.Client, clusterName); err != nil { - return errors.Wrapf(err, "failed to get cluster %s for env %s", clusterName, env) - } - } - // write result back - decisions := []v1alpha1.PlacementDecision{{ - Cluster: clusterName, - Namespace: namespace, - }} - if err = envbinding.WritePlacementDecisions(p.app, policy, env, decisions); err != nil { - return err - } - return v.FillObject(map[string]interface{}{"decisions": decisions}, "outputs") -} - -// PatchApplication -// Deprecated -func (p *provider) PatchApplication(_ monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - env, err := v.GetString("inputs", "envName") - if err != nil { - return err - } - patch := v1alpha1.EnvPatch{} - selector := &v1alpha1.EnvSelector{} - - obj, err := v.LookupValue("inputs", "patch") - if err == nil { - if err = obj.UnmarshalTo(&patch); err != nil { - return errors.Wrapf(err, "failed to unmarshal patch for env %s", env) - } - } - obj, err = v.LookupValue("inputs", "selector") - if err == nil { - if err = obj.UnmarshalTo(selector); err != nil { - return errors.Wrapf(err, "failed to unmarshal selector for env %s", env) - } - } else { - selector = nil - } - - newApp, err := envbinding.PatchApplication(p.app, &patch, selector) - if err != nil { - return errors.Wrapf(err, "failed to patch app for env %s", env) - } - return v.FillObject(newApp, "outputs") -} - -func (p *provider) ListClusters(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - secrets, err := multicluster.ListExistingClusterSecrets(ctx, p.Client) - if err != nil { - return err - } - var clusters []string - for _, secret := range secrets { - clusters = append(clusters, secret.Name) - } - return v.FillObject(clusters, "outputs", "clusters") -} - -func (p *provider) Deploy(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, act wfTypes.Action) error { - param := DeployParameter{} - if err := v.CueValue().Decode(¶m); err != nil { - return err - } - if param.Parallelism <= 0 { - return errors.Errorf("parallelism cannot be smaller than 1") - } - executor := NewDeployWorkflowStepExecutor(p.Client, p.af, p.apply, p.healthCheck, p.renderer, param) - healthy, reason, err := executor.Deploy(ctx) - if err != nil { - return err - } - if !healthy { - act.Wait(reason) - } - return nil -} - -func (p *provider) GetPlacementsFromTopologyPolicies(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - policyNames, err := v.GetStringSlice("policies") - if err != nil { - return err - } - policies, err := selectPolicies(p.af.Policies, policyNames) - if err != nil { - return err - } - placements, err := pkgpolicy.GetPlacementsFromTopologyPolicies(ctx, p.Client, p.af.Namespace, policies, true) - if err != nil { - return err - } - return v.FillObject(placements, "placements") -} - -// Install register handlers to provider discover. -func Install(p wfTypes.Providers, c client.Client, app *v1beta1.Application, af *appfile.Appfile, apply oamProvider.ComponentApply, healthCheck oamProvider.ComponentHealthCheck, renderer oamProvider.WorkloadRenderer) { - prd := &provider{Client: c, app: app, af: af, apply: apply, healthCheck: healthCheck, renderer: renderer} - p.Register(ProviderName, map[string]wfTypes.Handler{ - "make-placement-decisions": prd.MakePlacementDecisions, - "patch-application": prd.PatchApplication, - "list-clusters": prd.ListClusters, - "get-placements-from-topology-policies": prd.GetPlacementsFromTopologyPolicies, - "deploy": prd.Deploy, - }) -} diff --git a/pkg/workflow/providers/oam/apply.go b/pkg/workflow/providers/oam/apply.go deleted file mode 100644 index 30be8dec9..000000000 --- a/pkg/workflow/providers/oam/apply.go +++ /dev/null @@ -1,257 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oam - -import ( - "context" - "encoding/json" - "strings" - - "cuelang.org/go/cue/cuecontext" - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/client" - - monitorContext "github.com/kubevela/pkg/monitor/context" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/sets" - "github.com/kubevela/workflow/pkg/cue/model/value" - wfTypes "github.com/kubevela/workflow/pkg/types" - - "github.com/oam-dev/kubevela/apis/core.oam.dev/common" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/appfile" - "github.com/oam-dev/kubevela/pkg/oam" -) - -const ( - // ProviderName is provider name for install. - ProviderName = "oam" -) - -// ComponentApply apply oam component. -type ComponentApply func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) - -// ComponentRender render oam component. -type ComponentRender func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) - -// ComponentHealthCheck health check oam component. -type ComponentHealthCheck func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) - -// WorkloadRenderer renderer to render application component into workload -type WorkloadRenderer func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) - -type provider struct { - render ComponentRender - apply ComponentApply - app *v1beta1.Application - af *appfile.Appfile - cli client.Client -} - -// RenderComponent render component -func (p *provider) RenderComponent(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - comp, patcher, clusterName, overrideNamespace, err := lookUpCompInfo(v) - if err != nil { - return err - } - workload, traits, err := p.render(ctx, *comp, patcher, clusterName, overrideNamespace) - if err != nil { - return err - } - - if workload != nil { - if err := v.FillObject(workload.Object, "output"); err != nil { - return errors.WithMessage(err, "FillOutput") - } - } - - for _, trait := range traits { - name := trait.GetLabels()[oam.TraitResource] - if name != "" { - if err := v.FillObject(trait.Object, "outputs", name); err != nil { - return errors.WithMessage(err, "FillOutputs") - } - } - } - - return nil -} - -// ApplyComponent apply component. -func (p *provider) ApplyComponent(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, act wfTypes.Action) error { - comp, patcher, clusterName, overrideNamespace, err := lookUpCompInfo(v) - if err != nil { - return err - } - workload, traits, healthy, err := p.apply(ctx, *comp, patcher, clusterName, overrideNamespace) - if err != nil { - return err - } - - if workload != nil { - if err := v.FillObject(workload.Object, "output"); err != nil { - return errors.WithMessage(err, "FillOutput") - } - } - - for _, trait := range traits { - name := trait.GetLabels()[oam.TraitResource] - if name != "" { - if err := v.FillObject(trait.Object, "outputs", name); err != nil { - return errors.WithMessage(err, "FillOutputs") - } - } - } - - waitHealthy, err := v.GetBool("waitHealthy") - if err != nil { - waitHealthy = true - } - - if waitHealthy && !healthy { - act.Wait("wait healthy") - } - return nil -} - -func lookUpCompInfo(v *value.Value) (*common.ApplicationComponent, *value.Value, string, string, error) { - compSettings, err := v.LookupValue("value") - if err != nil { - return nil, nil, "", "", err - } - comp := &common.ApplicationComponent{} - - if err := compSettings.UnmarshalTo(comp); err != nil { - return nil, nil, "", "", err - } - patcher, err := v.LookupValue("patch") - if err != nil { - patcher = nil - } - clusterName, err := v.GetString("cluster") - if err != nil { - clusterName = "" - } - overrideNamespace, err := v.GetString("namespace") - if err != nil { - overrideNamespace = "" - } - return comp, patcher, clusterName, overrideNamespace, nil -} - -// LoadComponent load component describe info in application. -func (p *provider) LoadComponent(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - app := &v1beta1.Application{} - // if specify `app`, use specified application otherwise use default application from provider - appSettings, err := v.LookupValue("app") - if err != nil { - if strings.Contains(err.Error(), "not exist") { - app = p.app - } else { - return err - } - } else { - if err := appSettings.UnmarshalTo(app); err != nil { - return err - } - } - for _, _comp := range app.Spec.Components { - comp, err := p.af.LoadDynamicComponent(ctx, p.cli, _comp.DeepCopy()) - if err != nil { - return err - } - comp.Inputs = nil - comp.Outputs = nil - jt, err := json.Marshal(comp) - if err != nil { - return err - } - vs := string(jt) - cuectx := cuecontext.New() - val := cuectx.CompileString(vs) - if s, err := sets.OpenBaiscLit(val); err == nil { - v := cuectx.BuildFile(s) - str, err := sets.ToString(v) - if err != nil { - return err - } - vs = str - } - if err := v.FillRaw(vs, "value", comp.Name); err != nil { - return err - } - } - return nil -} - -// LoadComponentInOrder load component describe info in application output will be a list with order defined in application. -func (p *provider) LoadComponentInOrder(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - app := &v1beta1.Application{} - // if specify `app`, use specified application otherwise use default application from provider - appSettings, err := v.LookupValue("app") - if err != nil { - if strings.Contains(err.Error(), "not exist") { - app = p.app - } else { - return err - } - } else { - if err := appSettings.UnmarshalTo(app); err != nil { - return err - } - } - comps := make([]common.ApplicationComponent, len(app.Spec.Components)) - for idx, _comp := range app.Spec.Components { - comp, err := p.af.LoadDynamicComponent(ctx, p.cli, _comp.DeepCopy()) - if err != nil { - return err - } - comp.Inputs = nil - comp.Outputs = nil - comps[idx] = *comp - } - return v.FillObject(comps, "value") -} - -// LoadPolicies load policy describe info in application. -func (p *provider) LoadPolicies(_ monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - for _, po := range p.app.Spec.Policies { - if err := v.FillObject(po, "value", po.Name); err != nil { - return err - } - } - return nil -} - -// Install register handlers to provider discover. -func Install(p wfTypes.Providers, app *v1beta1.Application, af *appfile.Appfile, cli client.Client, apply ComponentApply, render ComponentRender) { - prd := &provider{ - render: render, - apply: apply, - app: app.DeepCopy(), - af: af, - cli: cli, - } - p.Register(ProviderName, map[string]wfTypes.Handler{ - "component-render": prd.RenderComponent, - "component-apply": prd.ApplyComponent, - "load": prd.LoadComponent, - "load-policies": prd.LoadPolicies, - "load-comps-in-order": prd.LoadComponentInOrder, - }) -} diff --git a/pkg/workflow/providers/oam/apply_test.go b/pkg/workflow/providers/oam/apply_test.go deleted file mode 100644 index b334408ec..000000000 --- a/pkg/workflow/providers/oam/apply_test.go +++ /dev/null @@ -1,222 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oam - -import ( - "context" - "strings" - "testing" - - "github.com/pkg/errors" - "github.com/stretchr/testify/require" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/mock" - - "github.com/oam-dev/kubevela/apis/core.oam.dev/common" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" -) - -func TestParser(t *testing.T) { - r := require.New(t) - p := &provider{ - apply: simpleComponentApplyForTest, - } - act := &mock.Action{} - v, err := value.NewValue("", nil, "") - r.NoError(err) - err = p.ApplyComponent(nil, nil, v, act) - r.Equal(err.Error(), "failed to lookup value: var(path=value) not exist") - v.FillObject(map[string]interface{}{}, "value") - err = p.ApplyComponent(nil, nil, v, act) - r.NoError(err) - output, err := v.LookupValue("output") - r.NoError(err) - outStr, err := output.String() - r.NoError(err) - r.Equal(outStr, `apiVersion: "v1" -kind: "Pod" -metadata: { - labels: { - app: "web" - } - name: "rss-site" -} -`) - - outputs, err := v.LookupValue("outputs") - r.NoError(err) - outsStr, err := outputs.String() - r.NoError(err) - r.Equal(outsStr, `service: { - apiVersion: "v1" - kind: "Service" - metadata: { - labels: { - "trait.oam.dev/resource": "service" - } - name: "service" - } -} -`) - - r.Equal(act.Phase, "Wait") - testHealthy = true - act = &mock.Action{} - _, err = value.NewValue("", nil, "") - r.NoError(err) - r.Equal(act.Phase, "") -} - -func TestLoadComponent(t *testing.T) { - r := require.New(t) - p := &provider{ - app: &v1beta1.Application{ - Spec: v1beta1.ApplicationSpec{ - Components: []common.ApplicationComponent{ - { - Name: "c1", - Type: "web", - Properties: &runtime.RawExtension{Raw: []byte(`{"image": "busybox"}`)}, - }, - }, - }, - }, - } - v, err := value.NewValue(``, nil, "") - r.NoError(err) - err = p.LoadComponent(nil, nil, v, nil) - r.NoError(err) - s, err := v.String() - r.NoError(err) - r.Equal(s, `value: { - c1: { - name: *"c1" | _ - type: *"web" | _ - properties: { - image: *"busybox" | _ - } - } -} -`) - overrideApp := `app: { - apiVersion: "core.oam.dev/v1beta1" - kind: "Application" - metadata: { - name: "test" - namespace: "default" - } - spec: { - components: [{ - name: "c2" - type: "web" - properties: { - image: "busybox" - } - }] - } -} -` - overrideValue, err := value.NewValue(overrideApp, nil, "") - r.NoError(err) - err = p.LoadComponent(nil, nil, overrideValue, nil) - r.NoError(err) - _, err = overrideValue.LookupValue("value", "c2") - r.NoError(err) -} - -func TestLoadComponentInOrder(t *testing.T) { - r := require.New(t) - p := &provider{ - app: &v1beta1.Application{ - Spec: v1beta1.ApplicationSpec{ - Components: []common.ApplicationComponent{ - { - Name: "c1", - Type: "web", - Properties: &runtime.RawExtension{Raw: []byte(`{"image": "busybox"}`)}, - }, - { - Name: "c2", - Type: "web2", - Properties: &runtime.RawExtension{Raw: []byte(`{"image": "busybox"}`)}, - }, - }, - }, - }, - } - v, err := value.NewValue(``, nil, "") - r.NoError(err) - err = p.LoadComponentInOrder(nil, nil, v, nil) - r.NoError(err) - s, err := v.String() - r.NoError(err) - r.Equal(s, `value: [{ - name: "c1" - type: "web" - properties: { - image: "busybox" - } -}, { - name: "c2" - type: "web2" - properties: { - image: "busybox" - } -}] -`) -} - -var testHealthy bool - -func simpleComponentApplyForTest(_ context.Context, comp common.ApplicationComponent, _ *value.Value, _, _ string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { - workload := new(unstructured.Unstructured) - workload.UnmarshalJSON([]byte(`{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "rss-site", - "labels": { - "app": "web" - } - } -}`)) - if comp.Name != "" { - workload.SetName(comp.Name) - if strings.Contains(comp.Name, "error") { - return nil, nil, false, errors.Errorf("bad component") - } - } - trait := new(unstructured.Unstructured) - trait.UnmarshalJSON([]byte(`{ - "apiVersion": "v1", - "kind": "Service", - "metadata": { - "name": "service", - "labels": { - "trait.oam.dev/resource": "service" - } - } -}`)) - if comp.Name != "" { - trait.SetName(comp.Name) - } - traits := []*unstructured.Unstructured{trait} - return workload, traits, testHealthy, nil -} diff --git a/pkg/workflow/providers/terraform/terraform.go b/pkg/workflow/providers/terraform/terraform.go deleted file mode 100644 index 8b897e13f..000000000 --- a/pkg/workflow/providers/terraform/terraform.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package terraform - -import ( - "github.com/pkg/errors" - - monitorContext "github.com/kubevela/pkg/monitor/context" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - wfTypes "github.com/kubevela/workflow/pkg/types" - - "github.com/oam-dev/kubevela/apis/core.oam.dev/common" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/apis/types" - oamProvider "github.com/oam-dev/kubevela/pkg/workflow/providers/oam" -) - -const ( - // ProviderName is provider name for install. - ProviderName = "terraform" -) - -type provider struct { - app *v1beta1.Application - renderer oamProvider.WorkloadRenderer -} - -func (p *provider) LoadTerraformComponents(ctx monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - var components []common.ApplicationComponent - for _, comp := range p.app.Spec.Components { - wl, err := p.renderer(ctx, comp) - if err != nil { - return errors.Wrapf(err, "failed to render component into workload") - } - if wl.CapabilityCategory != types.TerraformCategory { - continue - } - components = append(components, comp) - } - return v.FillObject(components, "outputs", "components") -} - -func (p *provider) GetConnectionStatus(_ monitorContext.Context, _ wfContext.Context, v *value.Value, _ wfTypes.Action) error { - componentName, err := v.GetString("inputs", "componentName") - if err != nil { - return errors.Wrapf(err, "failed to get component name") - } - for _, svc := range p.app.Status.Services { - if svc.Name == componentName { - return v.FillObject(svc.Healthy, "outputs", "healthy") - } - } - return v.FillObject(false, "outputs", "healthy") -} - -// Install register handlers to provider discover. -func Install(p wfTypes.Providers, app *v1beta1.Application, renderer oamProvider.WorkloadRenderer) { - prd := &provider{app: app, renderer: renderer} - p.Register(ProviderName, map[string]wfTypes.Handler{ - "load-terraform-components": prd.LoadTerraformComponents, - "get-connection-status": prd.GetConnectionStatus, - }) -} diff --git a/pkg/workflow/providers/time/date.go b/pkg/workflow/providers/time/date.go deleted file mode 100644 index a26379195..000000000 --- a/pkg/workflow/providers/time/date.go +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright 2021. The KubeVela Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package time - -import ( - "time" - - monitorContext "github.com/kubevela/pkg/monitor/context" - wfContext "github.com/kubevela/workflow/pkg/context" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/types" -) - -const ( - // ProviderName is provider name for install. - ProviderName = "time" -) - -type provider struct { -} - -func (h *provider) Timestamp(_ monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - date, err := v.GetString("date") - if err != nil { - return err - } - layout, err := v.GetString("layout") - if err != nil { - return err - } - if layout == "" { - layout = time.RFC3339 - } - t, err := time.Parse(layout, date) - if err != nil { - return err - } - return v.FillObject(t.Unix(), "timestamp") -} - -func (h *provider) Date(_ monitorContext.Context, _ wfContext.Context, v *value.Value, _ types.Action) error { - timestamp, err := v.GetInt64("timestamp") - if err != nil { - return err - } - layout, err := v.GetString("layout") - if err != nil { - return err - } - - if layout == "" { - layout = time.RFC3339 - } - t := time.Unix(timestamp, 0) - return v.FillObject(t.UTC().Format(layout), "date") -} - -// Install register handlers to provider discover. -func Install(p types.Providers) { - prd := &provider{} - p.Register(ProviderName, map[string]types.Handler{ - "timestamp": prd.Timestamp, - "date": prd.Date, - }) -} diff --git a/pkg/workflow/providers/time/date_test.go b/pkg/workflow/providers/time/date_test.go deleted file mode 100644 index 2c7aab665..000000000 --- a/pkg/workflow/providers/time/date_test.go +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright 2021. The KubeVela Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package time - -import ( - "testing" - - "github.com/pkg/errors" - "github.com/stretchr/testify/require" - - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/providers" -) - -func TestTimestamp(t *testing.T) { - testcases := map[string]struct { - from string - expected int64 - expectedErr error - }{ - "test convert date with default time layout": { - from: `date: "2021-11-07T01:47:51Z" -layout: ""`, - expected: 1636249671, - expectedErr: nil, - }, - "test convert date with RFC3339 layout": { - from: `date: "2021-11-07T01:47:51Z" -layout: "2006-01-02T15:04:05Z07:00"`, - expected: 1636249671, - expectedErr: nil, - }, - "test convert date with RFC1123 layout": { - from: `date: "Fri, 01 Mar 2019 15:00:00 GMT" -layout: "Mon, 02 Jan 2006 15:04:05 MST"`, - expected: 1551452400, - expectedErr: nil, - }, - "test convert date without time layout": { - from: `date: "2021-11-07T01:47:51Z"`, - expected: 0, - expectedErr: errors.New("failed to lookup value: var(path=layout) not exist"), - }, - "test convert without date": { - from: ``, - expected: 0, - expectedErr: errors.New("failed to lookup value: var(path=date) not exist"), - }, - "test convert date with wrong time layout": { - from: `date: "2021-11-07T01:47:51Z" -layout: "Mon, 02 Jan 2006 15:04:05 MST"`, - expected: 0, - expectedErr: errors.New(`parsing time "2021-11-07T01:47:51Z" as "Mon, 02 Jan 2006 15:04:05 MST": cannot parse "2021-11-07T01:47:51Z" as "Mon"`), - }, - } - - for name, tc := range testcases { - t.Run(name, func(t *testing.T) { - r := require.New(t) - v, err := value.NewValue(tc.from, nil, "") - r.NoError(err) - prd := &provider{} - err = prd.Timestamp(nil, nil, v, nil) - if tc.expectedErr != nil { - r.Equal(tc.expectedErr.Error(), err.Error()) - return - } - r.NoError(err) - expected, err := v.LookupValue("timestamp") - r.NoError(err) - ret, err := expected.CueValue().Int64() - r.NoError(err) - r.Equal(tc.expected, ret) - }) - } -} - -func TestDate(t *testing.T) { - testcases := map[string]struct { - from string - expected string - expectedErr error - }{ - "test convert timestamp to default time layout": { - from: `timestamp: 1636249671 -layout: "" -`, - expected: "2021-11-07T01:47:51Z", - expectedErr: nil, - }, - "test convert date to RFC3339 layout": { - from: `timestamp: 1636249671 -layout: "2006-01-02T15:04:05Z07:00" -`, - expected: "2021-11-07T01:47:51Z", - expectedErr: nil, - }, - "test convert date to RFC1123 layout": { - from: `timestamp: 1551452400 -layout: "Mon, 02 Jan 2006 15:04:05 MST" -`, - expected: "Fri, 01 Mar 2019 15:00:00 UTC", - expectedErr: nil, - }, - "test convert date without time layout": { - from: `timestamp: 1551452400`, - expected: "", - expectedErr: errors.New("failed to lookup value: var(path=layout) not exist"), - }, - "test convert without timestamp": { - from: ``, - expected: "", - expectedErr: errors.New("failed to lookup value: var(path=timestamp) not exist"), - }, - } - - for name, tc := range testcases { - t.Run(name, func(t *testing.T) { - r := require.New(t) - v, err := value.NewValue(tc.from, nil, "") - r.NoError(err) - prd := &provider{} - err = prd.Date(nil, nil, v, nil) - if tc.expectedErr != nil { - r.Equal(tc.expectedErr.Error(), err.Error()) - return - } - r.NoError(err) - expected, err := v.LookupValue("date") - r.NoError(err) - ret, err := expected.CueValue().String() - r.NoError(err) - r.Equal(tc.expected, ret) - }) - } -} - -func TestInstall(t *testing.T) { - p := providers.NewProviders() - Install(p) - h, ok := p.GetHandler("time", "timestamp") - r := require.New(t) - r.Equal(ok, true) - r.Equal(h != nil, true) - - h, ok = p.GetHandler("time", "date") - r.Equal(ok, true) - r.Equal(h != nil, true) -} diff --git a/pkg/workflow/template/static/builtin-apply-component.cue b/pkg/workflow/template/static/builtin-apply-component.cue index e50900efb..fc80b9ac9 100644 --- a/pkg/workflow/template/static/builtin-apply-component.cue +++ b/pkg/workflow/template/static/builtin-apply-component.cue @@ -2,9 +2,8 @@ import ( "vela/op" ) -oam: op.oam // apply component and traits -apply: oam.#ApplyComponent & { +apply: op.#ApplyComponent & { value: parameter.value cluster: parameter.cluster namespace: parameter.namespace diff --git a/references/appfile/addon.go b/references/appfile/addon.go index ec2dbf077..5e88da791 100644 --- a/references/appfile/addon.go +++ b/references/appfile/addon.go @@ -47,16 +47,11 @@ const ( ) // ApplyTerraform deploys addon resources -func ApplyTerraform(app *v1beta1.Application, k8sClient client.Client, ioStream util.IOStreams, namespace string, args common.Args) ([]commontypes.ApplicationComponent, error) { - pd, err := args.GetPackageDiscover() - if err != nil { - return nil, err - } - +func ApplyTerraform(app *v1beta1.Application, k8sClient client.Client, ioStream util.IOStreams, namespace string, _ common.Args) ([]commontypes.ApplicationComponent, error) { // TODO(zzxwill) Need to check whether authentication credentials of a specific cloud provider are exported as environment variables, like `ALICLOUD_ACCESS_KEY` var nativeVelaComponents []commontypes.ApplicationComponent // parse template - appParser := appfile.NewApplicationParser(k8sClient, pd) + appParser := appfile.NewApplicationParser(k8sClient) ctx := util2.SetNamespaceInCtx(context.Background(), namespace) appFile, err := appParser.GenerateAppFile(ctx, app) diff --git a/references/cli/config.go b/references/cli/config.go index 5c2bd1048..4b8eb9719 100644 --- a/references/cli/config.go +++ b/references/cli/config.go @@ -111,7 +111,7 @@ func NewTemplateApplyCommand(f velacmd.Factory, streams util.IOStreams) *cobra.C return err } inf := config.NewConfigFactory(f.Client()) - template, err := inf.ParseTemplate(options.Name, body) + template, err := inf.ParseTemplate(cmd.Context(), options.Name, body) if err != nil { return err } diff --git a/references/cli/debug.go b/references/cli/debug.go index 371e84622..93debae14 100644 --- a/references/cli/debug.go +++ b/references/cli/debug.go @@ -22,6 +22,7 @@ import ( "strings" "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "github.com/AlecAivazis/survey/v2" "github.com/FogDong/uitable" "github.com/fatih/color" @@ -34,10 +35,7 @@ import ( workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" "github.com/kubevela/workflow/pkg/cue/model/sets" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/kubevela/workflow/pkg/debug" - "github.com/kubevela/workflow/pkg/tasks/custom" wfTypes "github.com/kubevela/workflow/pkg/types" "github.com/oam-dev/kubevela/apis/types" @@ -108,17 +106,13 @@ func (d *debugOpts) debugApplication(ctx context.Context, wargs *WorkflowArgs, c if err != nil { return err } - pd, err := c.GetPackageDiscover() - if err != nil { - return err - } d.opts = wargs.getWorkflowSteps() d.errMap = wargs.ErrMap if app.Spec.Workflow != nil && len(app.Spec.Workflow.Steps) > 0 { - return d.debugWorkflow(ctx, wargs, cli, pd, ioStreams) + return d.debugWorkflow(ctx, wargs, cli, ioStreams) } - dryRunOpt := dryrun.NewDryRunOption(cli, config, pd, []*unstructured.Unstructured{}, false) + dryRunOpt := dryrun.NewDryRunOption(cli, config, []*unstructured.Unstructured{}, false) comps, _, err := dryRunOpt.ExecuteDryRun(ctx, app) if err != nil { ioStreams.Info(color.RedString("%s%s", emojiFail, err.Error())) @@ -127,7 +121,7 @@ func (d *debugOpts) debugApplication(ctx context.Context, wargs *WorkflowArgs, c return d.debugComponents(comps, ioStreams) } -func (d *debugOpts) debugWorkflow(ctx context.Context, wargs *WorkflowArgs, cli client.Client, pd *packages.PackageDiscover, ioStreams cmdutil.IOStreams) error { +func (d *debugOpts) debugWorkflow(ctx context.Context, wargs *WorkflowArgs, cli client.Client, ioStreams cmdutil.IOStreams) error { if d.step == "" { prompt := &survey.Select{ Message: "Select the workflow step to debug:", @@ -145,7 +139,7 @@ func (d *debugOpts) debugWorkflow(ctx context.Context, wargs *WorkflowArgs, cli } // debug workflow steps - rawValue, data, err := d.getDebugRawValue(ctx, cli, pd, wargs.WorkflowInstance) + rawValue, data, err := d.getDebugRawValue(ctx, cli, wargs.WorkflowInstance) if err != nil { if data != "" { ioStreams.Info(color.RedString("%s%s", emojiFail, err.Error())) @@ -273,37 +267,37 @@ func unwrapStepID(step string, instance *wfTypes.WorkflowInstance) string { return step } -func (d *debugOpts) getDebugRawValue(ctx context.Context, cli client.Client, pd *packages.PackageDiscover, instance *wfTypes.WorkflowInstance) (*value.Value, string, error) { +func (d *debugOpts) getDebugRawValue(ctx context.Context, cli client.Client, instance *wfTypes.WorkflowInstance) (cue.Value, string, error) { debugCM := &corev1.ConfigMap{} if err := cli.Get(ctx, client.ObjectKey{Name: debug.GenerateContextName(instance.Name, d.step, string(instance.UID)), Namespace: instance.Namespace}, debugCM); err != nil { for _, step := range instance.Status.Steps { if step.Name == d.step && (step.Type == wfTypes.WorkflowStepTypeSuspend || step.Type == wfTypes.WorkflowStepTypeStepGroup) { - return nil, "", fmt.Errorf("no debug data for a suspend or step-group step, please choose another step") + return cue.Value{}, "", fmt.Errorf("no debug data for a suspend or step-group step, please choose another step") } for _, sub := range step.SubStepsStatus { if sub.Name == d.step && sub.Type == wfTypes.WorkflowStepTypeSuspend { - return nil, "", fmt.Errorf("no debug data for a suspend step, please choose another step") + return cue.Value{}, "", fmt.Errorf("no debug data for a suspend step, please choose another step") } } } - return nil, "", fmt.Errorf("failed to get debug configmap, please make sure the you're in the debug mode`: %w", err) + return cue.Value{}, "", fmt.Errorf("failed to get debug configmap, please make sure the you're in the debug mode`: %w", err) } if debugCM.Data == nil || debugCM.Data["debug"] == "" { - return nil, "", fmt.Errorf("debug configmap is empty") + return cue.Value{}, "", fmt.Errorf("debug configmap is empty") } - v, err := value.NewValue(debugCM.Data["debug"], pd, "") - if err != nil { - return nil, debugCM.Data["debug"], fmt.Errorf("failed to parse debug configmap: %w", err) + v := cuecontext.New().CompileString(debugCM.Data["debug"]) + if v.Err() != nil { + return cue.Value{}, debugCM.Data["debug"], fmt.Errorf("failed to parse debug configmap: %w", v.Err()) } return v, debugCM.Data["debug"], nil } -func (d *debugOpts) handleCueSteps(v *value.Value, ioStreams cmdutil.IOStreams) error { +func (d *debugOpts) handleCueSteps(v cue.Value, ioStreams cmdutil.IOStreams) error { if d.focus != "" { - f, err := v.LookupValue(strings.Split(d.focus, ".")...) - if err != nil { - return err + f := v.LookupPath(cue.ParsePath(d.focus)) + if f.Err() != nil { + return f.Err() } ioStreams.Info(color.New(color.FgCyan).Sprint("\n", d.focus, "\n")) rendered, err := renderFields(f, &renderOptions{}) @@ -317,22 +311,20 @@ func (d *debugOpts) handleCueSteps(v *value.Value, ioStreams cmdutil.IOStreams) return d.separateBySteps(v, ioStreams) } -func (d *debugOpts) separateBySteps(v *value.Value, ioStreams cmdutil.IOStreams) error { - fieldMap := make(map[string]*value.Value) +func (d *debugOpts) separateBySteps(v cue.Value, ioStreams cmdutil.IOStreams) error { + fieldMap := make(map[string]cue.Value) fieldList := make([]string, 0) - if err := v.StepByFields(func(fieldName string, in *value.Value) (bool, error) { - if in.CueValue().IncompleteKind() == cue.BottomKind { - errInfo, err := sets.ToString(in.CueValue()) - if err != nil { - errInfo = "value is _|_" - } - return true, errors.New(errInfo + "value is _|_ (bottom kind)") + it, err := v.Fields(cue.Optional(true), cue.Hidden(true)) + if err != nil { + return fmt.Errorf("failed to get fields: %w", err) + } + for it.Next() { + if it.Value().IncompleteKind() == cue.BottomKind { + break } + fieldName := it.Label() fieldList = append(fieldList, fieldName) - fieldMap[fieldName] = in - return false, nil - }); err != nil { - return fmt.Errorf("failed to parse debug configmap by field: %w", err) + fieldMap[fieldName] = it.Value() } errStep := "" @@ -391,18 +383,24 @@ type renderOptions struct { filterFields []string } -func renderFields(v *value.Value, opt *renderOptions) (string, error) { +func renderFields(v cue.Value, opt *renderOptions) (string, error) { table := uitable.New() table.MaxColWidth = 200 table.Wrap = true i := 0 - if err := v.StepByFields(func(fieldName string, in *value.Value) (bool, error) { + it, err := v.Fields(cue.Optional(true), cue.Hidden(true)) + if err != nil { + return "", fmt.Errorf("failed to get fields: %w", err) + } + for it.Next() { + in := it.Value() + fieldName := in.Path().String() key := "" - if custom.OpTpy(in) != "" { + if in.LookupPath(cue.ParsePath("#do")).Exists() { rendered, err := renderFields(in, opt) if err != nil { - return false, err + continue } i++ if !opt.hideIndex { @@ -410,9 +408,9 @@ func renderFields(v *value.Value, opt *renderOptions) (string, error) { } key += fieldName if !strings.Contains(fieldName, "#") { - if err := v.FillObject(in, fieldName); err != nil { + v = v.FillPath(cue.ParsePath(fieldName), in) + if v.Err() != nil { renderValuesInRow(table, key, rendered, false) - return false, err } } if len(opt.filterFields) > 0 { @@ -424,12 +422,11 @@ func renderFields(v *value.Value, opt *renderOptions) (string, error) { } else { renderValuesInRow(table, key, rendered, true) } - return false, nil + continue } - - vStr, err := in.String() + vStr, err := sets.ToString(in) if err != nil { - return false, err + continue } i++ if !opt.hideIndex { @@ -437,9 +434,9 @@ func renderFields(v *value.Value, opt *renderOptions) (string, error) { } key += fieldName if !strings.Contains(fieldName, "#") { - if err := v.FillObject(in, fieldName); err != nil { + v = v.FillPath(cue.ParsePath(fieldName), in) + if v.Err() != nil { renderValuesInRow(table, key, vStr, false) - return false, err } } @@ -452,17 +449,7 @@ func renderFields(v *value.Value, opt *renderOptions) (string, error) { } else { renderValuesInRow(table, key, vStr, true) } - return false, nil - }); err != nil { - vStr, serr := v.String() - if serr != nil { - return "", serr - } - if strings.Contains(err.Error(), "(type string) as struct") { - return strings.TrimSpace(vStr), nil - } } - return table.String(), nil } diff --git a/references/cli/def.go b/references/cli/def.go index 01a932053..e2fa9e7fe 100644 --- a/references/cli/def.go +++ b/references/cli/def.go @@ -32,7 +32,6 @@ import ( "strings" "time" - "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/encoding/gocode/gocodec" "github.com/kubevela/workflow/pkg/cue/model/sets" @@ -149,7 +148,7 @@ func buildTemplateFromYAML(templateYAML string, def *pkgdef.Definition) error { templateObject[process.OutputsFieldName].(map[string]interface{})[name] = yamlObject } } - codec := gocodec.New((*cue.Runtime)(cuecontext.New()), &gocodec.Config{}) + codec := gocodec.New(cuecontext.New(), &gocodec.Config{}) val, err := codec.Decode(templateObject) if err != nil { return errors.Wrapf(err, "failed to decode template into cue") @@ -1115,7 +1114,7 @@ func NewDefinitionGenAPICommand(c common.Args) *cobra.Command { if err != nil { return err } - err = meta.Run() + err = meta.Run(cmd.Context()) if err != nil { return err } diff --git a/references/cli/dryrun.go b/references/cli/dryrun.go index c3d66268c..976e25b34 100644 --- a/references/cli/dryrun.go +++ b/references/cli/dryrun.go @@ -153,16 +153,12 @@ func DryRunApplication(cmdOption *DryRunCmdOptions, c common.Args, namespace str return buff, err } - pd, err := c.GetPackageDiscover() - if err != nil { - return buff, err - } config, err := c.GetConfig() if err != nil { return buff, err } - dryRunOpt := dryrun.NewDryRunOption(newClient, config, pd, objs, false) + dryRunOpt := dryrun.NewDryRunOption(newClient, config, objs, false) ctx := oamutil.SetNamespaceInCtx(context.Background(), namespace) ctx = oamutil.SetXDefinitionNamespaceInCtx(ctx, cmdOption.DefinitionNamespace) diff --git a/references/cli/exec.go b/references/cli/exec.go index c83ea0134..c3308a128 100644 --- a/references/cli/exec.go +++ b/references/cli/exec.go @@ -34,8 +34,8 @@ import ( "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/utils/common" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/pkg/utils/util" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/references/appfile" ) diff --git a/references/cli/kube.go b/references/cli/kube.go index dcb22e2ae..e2fcfaee6 100644 --- a/references/cli/kube.go +++ b/references/cli/kube.go @@ -24,6 +24,7 @@ import ( "io" "strings" + "cuelang.org/go/cue/cuecontext" "github.com/pkg/errors" "github.com/spf13/cobra" "gopkg.in/yaml.v3" @@ -39,8 +40,6 @@ import ( "k8s.io/utils/strings/slices" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/oam-dev/kubevela/apis/types" velacmd "github.com/oam-dev/kubevela/pkg/cmd" cmdutil "github.com/oam-dev/kubevela/pkg/cmd/util" @@ -151,11 +150,7 @@ func (opt *KubeApplyOptions) Validate() error { } opt.objects = append(opt.objects, obj) case strings.HasSuffix(fileData.Path, ".cue"): - val, err := value.NewValue(string(fileData.Data), nil, "") - if err != nil { - return fmt.Errorf("failed to decode object in %s: %w", fileData.Path, err) - } - data, err := val.CueValue().MarshalJSON() + data, err := cuecontext.New().CompileBytes(fileData.Data).MarshalJSON() if err != nil { return fmt.Errorf("failed to marhsal to json for CUE object in %s: %w", fileData.Path, err) } diff --git a/references/cli/livediff.go b/references/cli/livediff.go index 6010d07ac..722b089c2 100644 --- a/references/cli/livediff.go +++ b/references/cli/livediff.go @@ -108,15 +108,11 @@ func LiveDiffApplication(cmdOption *LiveDiffCmdOptions, c common.Args) (bytes.Bu return buff, err } } - pd, err := c.GetPackageDiscover() - if err != nil { - return buff, err - } config, err := c.GetConfig() if err != nil { return buff, err } - liveDiffOption := dryrun.NewLiveDiffOption(newClient, config, pd, objs) + liveDiffOption := dryrun.NewLiveDiffOption(newClient, config, objs) if cmdOption.ApplicationFile == "" { return cmdOption.renderlessDiff(newClient, liveDiffOption) } diff --git a/references/cli/logs.go b/references/cli/logs.go index 03d1bb3f6..e481e8f19 100644 --- a/references/cli/logs.go +++ b/references/cli/logs.go @@ -30,8 +30,8 @@ import ( "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/common" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/pkg/utils/util" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/references/appfile" ) diff --git a/references/cli/portforward.go b/references/cli/portforward.go index 6279f962c..b49127b51 100644 --- a/references/cli/portforward.go +++ b/references/cli/portforward.go @@ -42,8 +42,8 @@ import ( "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/utils/common" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/pkg/utils/util" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/references/appfile" ) diff --git a/references/cli/registry.go b/references/cli/registry.go index 5bbeac438..2995ee6b7 100644 --- a/references/cli/registry.go +++ b/references/cli/registry.go @@ -744,5 +744,5 @@ func ParseCapability(mapper meta.RESTMapper, data []byte) (types.Capability, err if err != nil { return types.Capability{}, err } - return docgen.ParseCapabilityFromUnstructured(mapper, nil, obj) + return docgen.ParseCapabilityFromUnstructured(mapper, obj) } diff --git a/references/cli/revision.go b/references/cli/revision.go index e3c38c894..f3d63302c 100644 --- a/references/cli/revision.go +++ b/references/cli/revision.go @@ -19,6 +19,7 @@ import ( "io" "github.com/kubevela/pkg/util/compression" + "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/pkg/errors" "github.com/spf13/cobra" apitypes "k8s.io/apimachinery/pkg/types" @@ -134,11 +135,6 @@ func getRevision(ctx context.Context, c common.Args, format string, out io.Write return err } - pd, err := c.GetPackageDiscover() - if err != nil { - return err - } - params := map[string]string{ "name": name, "namespace": namespace, @@ -149,14 +145,14 @@ func getRevision(ctx context.Context, c common.Args, format string, out io.Write return fmt.Errorf(fmt.Sprintf("Unable to get application revision %s in namespace %s", name, namespace)) } - queryValue, err := velaql.NewViewHandler(cli, kubeConfig, pd).QueryView(ctx, query) + queryValue, err := velaql.NewViewHandler(cli, kubeConfig).QueryView(ctx, query) if err != nil { klog.Errorf("fail to query the view %s", err.Error()) return fmt.Errorf(fmt.Sprintf("Unable to get application revision %s in namespace %s", name, namespace)) } apprev := v1beta1.ApplicationRevision{} - err = queryValue.UnmarshalTo(&apprev) + err = value.UnmarshalTo(queryValue, &apprev) if err != nil { return err } diff --git a/references/cli/show.go b/references/cli/show.go index 960d3121c..4164ecb7b 100644 --- a/references/cli/show.go +++ b/references/cli/show.go @@ -33,8 +33,6 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/utils/common" "github.com/oam-dev/kubevela/pkg/utils/system" @@ -196,14 +194,6 @@ func startReferenceDocsSite(ctx context.Context, ns string, c common.Args, ioStr if err != nil { return err } - config, err := c.GetConfig() - if err != nil { - return err - } - pd, err := packages.NewPackageDiscover(config) - if err != nil { - return err - } ref := &docgen.MarkdownReference{ ParseReference: docgen.ParseReference{ Client: cli, @@ -211,7 +201,7 @@ func startReferenceDocsSite(ctx context.Context, ns string, c common.Args, ioStr }, } - if err := ref.CreateMarkdown(ctx, capabilities, docsPath, true, pd); err != nil { + if err := ref.CreateMarkdown(ctx, capabilities, docsPath, true); err != nil { return err } diff --git a/references/cli/status.go b/references/cli/status.go index 9498d17e1..1e0bd8c65 100644 --- a/references/cli/status.go +++ b/references/cli/status.go @@ -24,6 +24,7 @@ import ( "strings" "time" + "cuelang.org/go/cue" "k8s.io/client-go/rest" "github.com/fatih/color" @@ -38,7 +39,6 @@ import ( pkgmulticluster "github.com/kubevela/pkg/multicluster" workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" "github.com/kubevela/workflow/pkg/cue/model/sets" - "github.com/kubevela/workflow/pkg/cue/model/value" "github.com/kubevela/workflow/pkg/utils" commontypes "github.com/oam-dev/kubevela/apis/core.oam.dev/common" @@ -50,8 +50,8 @@ import ( "github.com/oam-dev/kubevela/pkg/policy" "github.com/oam-dev/kubevela/pkg/resourcetracker" "github.com/oam-dev/kubevela/pkg/utils/common" + types2 "github.com/oam-dev/kubevela/pkg/utils/types" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" - types2 "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/references/appfile" references "github.com/oam-dev/kubevela/references/common" ) @@ -258,7 +258,7 @@ func printWorkflowStatus(c client.Client, ioStreams cmdutil.IOStreams, appName s return err } outputs := make(map[string]workflowv1alpha1.StepOutputs) - var v *value.Value + var v cue.Value if detail { for _, c := range remoteApp.Spec.Components { if c.Outputs != nil { @@ -279,7 +279,7 @@ func printWorkflowStatus(c client.Client, ioStreams cmdutil.IOStreams, appName s } if remoteApp.Status.Workflow != nil && remoteApp.Status.Workflow.ContextBackend != nil { ctxBackend := remoteApp.Status.Workflow.ContextBackend - v, err = utils.GetDataFromContext(context.Background(), c, ctxBackend.Name, remoteApp.Name, remoteApp.Namespace) + v, err = utils.GetDataFromContext(context.Background(), ctxBackend.Name, remoteApp.Name, remoteApp.Namespace) if err != nil { return err } @@ -304,7 +304,7 @@ func printWorkflowStatus(c client.Client, ioStreams cmdutil.IOStreams, appName s return nil } -func printWorkflowStepStatus(indent string, step workflowv1alpha1.StepStatus, ioStreams cmdutil.IOStreams, detail bool, outputs map[string]workflowv1alpha1.StepOutputs, v *value.Value) { +func printWorkflowStepStatus(indent string, step workflowv1alpha1.StepStatus, ioStreams cmdutil.IOStreams, detail bool, outputs map[string]workflowv1alpha1.StepOutputs, v cue.Value) { ioStreams.Infof("%s- id: %s\n", indent[0:len(indent)-2], step.ID) ioStreams.Infof("%sname: %s\n", indent, step.Name) ioStreams.Infof("%stype: %s\n", indent, step.Type) @@ -316,11 +316,11 @@ func printWorkflowStepStatus(indent string, step workflowv1alpha1.StepStatus, io if len(outputs[step.Name]) > 0 { ioStreams.Infof("%soutputs:\n", indent) for _, output := range outputs[step.Name] { - outputValue, err := v.LookupValue(output.Name) - if err != nil { + outputValue := v.LookupPath(cue.ParsePath(output.Name)) + if !outputValue.Exists() { continue } - s, err := sets.ToString(outputValue.CueValue()) + s, err := sets.ToString(outputValue) if err != nil { continue } @@ -470,10 +470,6 @@ func printApplicationTree(c common.Args, cmd *cobra.Command, appName string, app if err != nil { return err } - pd, err := c.GetPackageDiscover() - if err != nil { - return err - } app, err := loadRemoteApplication(cli, appNs, appName) if err != nil { @@ -491,7 +487,7 @@ func printApplicationTree(c common.Args, cmd *cobra.Command, appName string, app } var placements []v1alpha1.PlacementDecision - af, err := pkgappfile.NewApplicationParser(cli, pd).GenerateAppFile(context.Background(), app) + af, err := pkgappfile.NewApplicationParser(cli).GenerateAppFile(context.Background(), app) if err == nil { placements, _ = policy.GetPlacementsFromTopologyPolicies(context.Background(), cli, app.GetNamespace(), af.Policies, true) } diff --git a/references/cli/suite_test.go b/references/cli/suite_test.go index f8fc7e931..af0c4e2a4 100644 --- a/references/cli/suite_test.go +++ b/references/cli/suite_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "github.com/kubevela/pkg/util/singleton" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -68,6 +69,7 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: common.Scheme}) Expect(err).Should(BeNil()) Expect(k8sClient).ToNot(BeNil()) + singleton.KubeClient.Set(k8sClient) dc, err = discovery.NewDiscoveryClientForConfig(cfg) Expect(err).ToNot(HaveOccurred()) diff --git a/references/cli/test-data/addon/sample/Chart.yaml b/references/cli/test-data/addon/sample/Chart.yaml index e6ef11512..04264db61 100644 --- a/references/cli/test-data/addon/sample/Chart.yaml +++ b/references/cli/test-data/addon/sample/Chart.yaml @@ -1,3 +1,5 @@ +annotations: + addon.name: sample apiVersion: v2 appVersion: 1.0.1 description: This is a test sample addon diff --git a/references/cli/top/component/tree_node.go b/references/cli/top/component/tree_node.go index 86ea673b4..a5ada59e2 100644 --- a/references/cli/top/component/tree_node.go +++ b/references/cli/top/component/tree_node.go @@ -21,7 +21,7 @@ import ( "github.com/kubevela/workflow/api/v1alpha1" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/references/cli/top/config" ) diff --git a/references/cli/top/component/tree_node_test.go b/references/cli/top/component/tree_node_test.go index 4d81ef467..4a05a8bc0 100644 --- a/references/cli/top/component/tree_node_test.go +++ b/references/cli/top/component/tree_node_test.go @@ -22,7 +22,7 @@ import ( "github.com/kubevela/workflow/api/v1alpha1" "github.com/stretchr/testify/assert" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" ) func TestTopologyTreeNodeFormatter(t *testing.T) { diff --git a/references/cli/top/model/application.go b/references/cli/top/model/application.go index f62d1ee98..3848c397c 100644 --- a/references/cli/top/model/application.go +++ b/references/cli/top/model/application.go @@ -25,8 +25,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" clicommon "github.com/oam-dev/kubevela/references/common" ) @@ -85,7 +85,7 @@ func LoadApplication(c client.Client, name, ns string) (*v1beta1.Application, er } // ApplicationResourceTopology return the applied resource of the app in tree form -func ApplicationResourceTopology(c client.Client, name, ns string) ([]*types.AppliedResource, error) { +func ApplicationResourceTopology(c client.Client, name, ns string) ([]types.AppliedResource, error) { opt := query.Option{ Name: name, Namespace: ns, diff --git a/references/cli/top/model/managed_resource.go b/references/cli/top/model/managed_resource.go index aca84354d..af3a1a2b7 100644 --- a/references/cli/top/model/managed_resource.go +++ b/references/cli/top/model/managed_resource.go @@ -21,7 +21,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" "github.com/oam-dev/kubevela/references/common" ) diff --git a/references/cli/top/model/pod.go b/references/cli/top/model/pod.go index 7209f31e7..bd7026ec5 100644 --- a/references/cli/top/model/pod.go +++ b/references/cli/top/model/pod.go @@ -27,7 +27,7 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" "github.com/oam-dev/kubevela/references/cli/top/utils" clicommon "github.com/oam-dev/kubevela/references/common" ) diff --git a/references/cli/top/model/resource.go b/references/cli/top/model/resource.go index a411f5a2c..7740ab60e 100644 --- a/references/cli/top/model/resource.go +++ b/references/cli/top/model/resource.go @@ -28,8 +28,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/multicluster" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" ) // ResourceList an abstract kinds of resource list which can convert it to data of view in the form of table @@ -54,7 +54,7 @@ type GVR struct { R Resource } -func collectResource(ctx context.Context, c client.Client, opt query.Option) ([]unstructured.Unstructured, error) { +func collectResource(ctx context.Context, c client.Client, opt query.Option) ([]*unstructured.Unstructured, error) { app := new(v1beta1.Application) appKey := client.ObjectKey{Name: opt.Name, Namespace: opt.Namespace} if err := c.Get(context.Background(), appKey, app); err != nil { @@ -65,16 +65,16 @@ func collectResource(ctx context.Context, c client.Client, opt query.Option) ([] if err != nil { return nil, err } - var resources = make([]unstructured.Unstructured, 0) + var resources = make([]*unstructured.Unstructured, 0) for _, res := range appResList { if res.ResourceTree != nil { resources = append(resources, sonLeafResource(res.ResourceTree, opt.Filter.Kind, opt.Filter.APIVersion)...) } if (opt.Filter.Kind == "" && opt.Filter.APIVersion == "") || (res.Kind == opt.Filter.Kind && res.APIVersion == opt.Filter.APIVersion) { - var object unstructured.Unstructured + object := &unstructured.Unstructured{} object.SetAPIVersion(opt.Filter.APIVersion) object.SetKind(opt.Filter.Kind) - if err := c.Get(ctx, apimachinerytypes.NamespacedName{Namespace: res.Namespace, Name: res.Name}, &object); err == nil { + if err := c.Get(ctx, apimachinerytypes.NamespacedName{Namespace: res.Namespace, Name: res.Name}, object); err == nil { resources = append(resources, object) } } @@ -82,8 +82,8 @@ func collectResource(ctx context.Context, c client.Client, opt query.Option) ([] return resources, nil } -func sonLeafResource(node *querytypes.ResourceTreeNode, kind string, apiVersion string) []unstructured.Unstructured { - objects := make([]unstructured.Unstructured, 0) +func sonLeafResource(node *querytypes.ResourceTreeNode, kind string, apiVersion string) []*unstructured.Unstructured { + objects := make([]*unstructured.Unstructured, 0) if node.LeafNodes != nil { for i := 0; i < len(node.LeafNodes); i++ { objects = append(objects, sonLeafResource(node.LeafNodes[i], kind, apiVersion)...) diff --git a/references/cli/top/model/resource_test.go b/references/cli/top/model/resource_test.go index 080d886d8..fa0d4bdac 100644 --- a/references/cli/top/model/resource_test.go +++ b/references/cli/top/model/resource_test.go @@ -27,8 +27,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" ) var _ = Describe("test resource", func() { @@ -80,7 +80,7 @@ func TestSonLeafResource(t *testing.T) { node := &querytypes.ResourceTreeNode{ LeafNodes: []*querytypes.ResourceTreeNode{ { - Object: unstructured.Unstructured{}, + Object: &unstructured.Unstructured{}, }, }, } diff --git a/references/cli/top/view/application_topology_view.go b/references/cli/top/view/application_topology_view.go index 52aebf678..71a60de64 100644 --- a/references/cli/top/view/application_topology_view.go +++ b/references/cli/top/view/application_topology_view.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/references/cli/top/component" "github.com/oam-dev/kubevela/references/cli/top/model" clicommon "github.com/oam-dev/kubevela/references/common" diff --git a/references/cli/top/view/managed_resource_view.go b/references/cli/top/view/managed_resource_view.go index ca273a0d1..fb63efb5c 100644 --- a/references/cli/top/view/managed_resource_view.go +++ b/references/cli/top/view/managed_resource_view.go @@ -22,7 +22,7 @@ import ( "github.com/gdamore/tcell/v2" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/references/cli/top/component" "github.com/oam-dev/kubevela/references/cli/top/model" ) diff --git a/references/cli/utils.go b/references/cli/utils.go index 73e13b35a..64a461a14 100644 --- a/references/cli/utils.go +++ b/references/cli/utils.go @@ -35,7 +35,7 @@ import ( "sigs.k8s.io/yaml" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/utils/types" ) // UserInput user input in command diff --git a/references/cli/velaql.go b/references/cli/velaql.go index 25451915d..0eea908ad 100644 --- a/references/cli/velaql.go +++ b/references/cli/velaql.go @@ -24,16 +24,16 @@ import ( "regexp" "strings" - "github.com/spf13/cobra" - + "cuelang.org/go/cue" "github.com/kubevela/workflow/pkg/cue/model/value" + "github.com/spf13/cobra" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/common" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" "github.com/oam-dev/kubevela/pkg/utils/util" "github.com/oam-dev/kubevela/pkg/velaql" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" ) // Filter filter options @@ -212,7 +212,7 @@ func queryFromStatement(ctx context.Context, velaC common.Args, velaQLStatement // queryFromView print velaQL result from query view func queryFromView(ctx context.Context, velaC common.Args, velaQLViewPath string, cmd *cobra.Command) error { - queryView, err := velaql.ParseVelaQLFromPath(velaQLViewPath) + queryView, err := velaql.ParseVelaQLFromPath(ctx, velaQLViewPath) if err != nil { return err } @@ -223,8 +223,8 @@ func queryFromView(ctx context.Context, velaC common.Args, velaQLViewPath string return printValue(queryValue, cmd) } -func printValue(queryValue *value.Value, cmd *cobra.Command) error { - response, err := queryValue.CueValue().MarshalJSON() +func printValue(queryValue cue.Value, cmd *cobra.Command) error { + response, err := queryValue.MarshalJSON() if err != nil { return err } @@ -271,7 +271,7 @@ func GetServiceEndpoints(ctx context.Context, appName string, namespace string, Endpoints []querytypes.ServiceEndpoint `json:"endpoints"` Error string `json:"error"` }{} - if err := queryValue.UnmarshalTo(&response); err != nil { + if err := value.UnmarshalTo(queryValue, &response); err != nil { return nil, err } if response.Error != "" { @@ -301,7 +301,7 @@ func GetApplicationPods(ctx context.Context, appName string, namespace string, v Pods []querytypes.PodBase `json:"podList"` Error string `json:"error"` }{} - if err := queryValue.UnmarshalTo(&response); err != nil { + if err := value.UnmarshalTo(queryValue, &response); err != nil { return nil, err } if response.Error != "" { @@ -330,7 +330,7 @@ func GetApplicationServices(ctx context.Context, appName string, namespace strin Services []querytypes.ResourceItem `json:"services"` Error string `json:"error"` }{} - if err := queryValue.UnmarshalTo(&response); err != nil { + if err := value.UnmarshalTo(queryValue, &response); err != nil { return nil, err } if response.Error != "" { @@ -354,22 +354,18 @@ func setFilterParams(f Filter, params map[string]string) { } // QueryValue get queryValue from velaQL -func QueryValue(ctx context.Context, velaC common.Args, queryView *velaql.QueryView) (*value.Value, error) { - pd, err := velaC.GetPackageDiscover() - if err != nil { - return nil, err - } +func QueryValue(ctx context.Context, velaC common.Args, queryView *velaql.QueryView) (cue.Value, error) { config, err := velaC.GetConfig() if err != nil { - return nil, err + return cue.Value{}, err } client, err := velaC.GetClient() if err != nil { - return nil, err + return cue.Value{}, err } - queryValue, err := velaql.NewViewHandler(client, config, pd).QueryView(ctx, *queryView) + queryValue, err := velaql.NewViewHandler(client, config).QueryView(ctx, *queryView) if err != nil { - return nil, err + return cue.Value{}, err } return queryValue, nil } diff --git a/references/cli/workflow.go b/references/cli/workflow.go index c1d55acc1..b85a5d6a5 100644 --- a/references/cli/workflow.go +++ b/references/cli/workflow.go @@ -37,8 +37,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/utils/common" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/pkg/workflow/operation" ) @@ -228,17 +228,13 @@ func NewWorkflowDebugCommand(c common.Args, ioStream cmdutil.IOStreams, wargs *W if err != nil { return err } - pd, err := c.GetPackageDiscover() - if err != nil { - return err - } ctx := context.Background() if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { return err } dOpts.opts = wargs.getWorkflowSteps() dOpts.errMap = wargs.ErrMap - return dOpts.debugWorkflow(ctx, wargs, cli, pd, ioStream) + return dOpts.debugWorkflow(ctx, wargs, cli, ioStream) }, } cmd.Flags().StringVarP(&wargs.StepName, "step", "s", "", "specify the step name in the workflow") @@ -484,7 +480,7 @@ func (w *WorkflowArgs) printStepLogs(ctx context.Context, cli client.Client, ioS if w.WorkflowInstance.Status.ContextBackend == nil { return fmt.Errorf("the workflow context backend is not set") } - logConfig, err := wfUtils.GetLogConfigFromStep(ctx, cli, w.WorkflowInstance.Status.ContextBackend.Name, w.WorkflowInstance.Name, w.WorkflowInstance.Namespace, w.StepName) + logConfig, err := wfUtils.GetLogConfigFromStep(ctx, w.WorkflowInstance.Status.ContextBackend.Name, w.WorkflowInstance.Name, w.WorkflowInstance.Namespace, w.StepName) if err != nil { return errors.WithMessage(err, fmt.Sprintf("step [%s]", w.StepName)) } @@ -630,7 +626,7 @@ func (w *WorkflowArgs) checkDebugMode() func(cmd *cobra.Command, args []string) } else { msg = "please make sure your workflow have the debug annotation [workflowrun.oam.dev/debug:true] then re-run the workflow" } - cmd.Printf("workflow %s is not in debug mode, %s", w.WorkflowInstance.Name, msg) + cmd.Printf("workflow %s is not in debug mode, %s\n", w.WorkflowInstance.Name, msg) os.Exit(1) } } diff --git a/references/cmd/cli/main.go b/references/cmd/cli/main.go index 0a9bb4d69..a466cb0ae 100644 --- a/references/cmd/cli/main.go +++ b/references/cmd/cli/main.go @@ -20,9 +20,7 @@ import ( "os" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/klog/v2" - "github.com/oam-dev/kubevela/pkg/stdlib" "github.com/oam-dev/kubevela/pkg/utils/system" "github.com/oam-dev/kubevela/references/a/preimport" "github.com/oam-dev/kubevela/references/cli" @@ -38,9 +36,4 @@ func main() { if err := command.Execute(); err != nil { os.Exit(1) } - - if err := stdlib.SetupBuiltinImports(); err != nil { - klog.ErrorS(err, "Unable to set up builtin imports on package initialization") - os.Exit(1) - } } diff --git a/references/common/application.go b/references/common/application.go index 3a23603b9..6cc193d12 100644 --- a/references/common/application.go +++ b/references/common/application.go @@ -37,9 +37,9 @@ import ( "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/apply" "github.com/oam-dev/kubevela/pkg/utils/common" + querytypes "github.com/oam-dev/kubevela/pkg/utils/types" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" - querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" "github.com/oam-dev/kubevela/references/appfile" "github.com/oam-dev/kubevela/references/appfile/api" "github.com/oam-dev/kubevela/references/appfile/template" @@ -267,7 +267,7 @@ func ApplyApplication(app corev1beta1.Application, ioStream cmdutil.IOStreams, c } // CollectApplicationResource collects all resources of an application -func CollectApplicationResource(ctx context.Context, c client.Client, opt query.Option) ([]unstructured.Unstructured, error) { +func CollectApplicationResource(ctx context.Context, c client.Client, opt query.Option) ([]*unstructured.Unstructured, error) { app := new(corev1beta1.Application) appKey := client.ObjectKey{Name: opt.Name, Namespace: opt.Namespace} if err := c.Get(context.Background(), appKey, app); err != nil { @@ -278,16 +278,16 @@ func CollectApplicationResource(ctx context.Context, c client.Client, opt query. if err != nil { return nil, err } - var resources = make([]unstructured.Unstructured, 0) + var resources = make([]*unstructured.Unstructured, 0) for _, res := range appResList { if res.ResourceTree != nil { resources = append(resources, sonLeafResource(res.ResourceTree, opt.Filter.Kind, opt.Filter.APIVersion)...) } if (opt.Filter.Kind == "" && opt.Filter.APIVersion == "") || (res.Kind == opt.Filter.Kind && res.APIVersion == opt.Filter.APIVersion) { - var object unstructured.Unstructured + object := &unstructured.Unstructured{} object.SetAPIVersion(opt.Filter.APIVersion) object.SetKind(opt.Filter.Kind) - if err := c.Get(ctx, apitypes.NamespacedName{Namespace: res.Namespace, Name: res.Name}, &object); err == nil { + if err := c.Get(ctx, apitypes.NamespacedName{Namespace: res.Namespace, Name: res.Name}, object); err == nil { resources = append(resources, object) } } @@ -295,8 +295,8 @@ func CollectApplicationResource(ctx context.Context, c client.Client, opt query. return resources, nil } -func sonLeafResource(node *querytypes.ResourceTreeNode, kind string, apiVersion string) []unstructured.Unstructured { - objects := make([]unstructured.Unstructured, 0) +func sonLeafResource(node *querytypes.ResourceTreeNode, kind string, apiVersion string) []*unstructured.Unstructured { + objects := make([]*unstructured.Unstructured, 0) if node.LeafNodes != nil { for i := 0; i < len(node.LeafNodes); i++ { objects = append(objects, sonLeafResource(node.LeafNodes[i], kind, apiVersion)...) diff --git a/references/common/metrics.go b/references/common/metrics.go index 1c78d23f3..9a5e9b66e 100644 --- a/references/common/metrics.go +++ b/references/common/metrics.go @@ -34,7 +34,7 @@ import ( appv1beta1 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/multicluster" - "github.com/oam-dev/kubevela/pkg/velaql/providers/query" + "github.com/oam-dev/kubevela/pkg/workflow/providers/legacy/query" ) const ( diff --git a/references/cuegen/testdata/nullable.cue b/references/cuegen/testdata/nullable.cue index 162fa7c5b..ef662668e 100644 --- a/references/cuegen/testdata/nullable.cue +++ b/references/cuegen/testdata/nullable.cue @@ -4,7 +4,7 @@ Nullable: { field1?: null | string field2?: null | int field3?: null | bool - Field4: null | { + Field4: null | { field1: null | string field2: null | int field3: null | bool diff --git a/references/docgen/cluster.go b/references/docgen/cluster.go index 5006e2cc9..1539594a5 100644 --- a/references/docgen/cluster.go +++ b/references/docgen/cluster.go @@ -29,8 +29,6 @@ import ( "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kubevela/workflow/pkg/cue/packages" - commontypes "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" @@ -236,18 +234,9 @@ func GetWorkflowSteps(ctx context.Context, namespace string, c common.Args) ([]t return nil, nil, fmt.Errorf("list WorkflowStepDefinition err: %w", err) } - config, err := c.GetConfig() - if err != nil { - return nil, nil, err - } - pd, err := packages.NewPackageDiscover(config) - if err != nil { - return nil, nil, err - } - var templateErrors []error for _, def := range workflowStepDefs.Items { - tmp, err := GetCapabilityByWorkflowStepDefinitionObject(def, pd) + tmp, err := GetCapabilityByWorkflowStepDefinitionObject(def) if err != nil { templateErrors = append(templateErrors, errors.WithMessage(err, def.Name)) continue @@ -273,7 +262,7 @@ func GetPolicies(ctx context.Context, namespace string, c common.Args) ([]types. var templateErrors []error for _, def := range defs.Items { - tmp, err := GetCapabilityByPolicyDefinitionObject(def, nil) + tmp, err := GetCapabilityByPolicyDefinitionObject(def) if err != nil { templateErrors = append(templateErrors, err) continue @@ -299,9 +288,9 @@ func validateCapabilities(mapper meta.RESTMapper, definitionName string, referen // HandleDefinition will handle definition to capability func HandleDefinition(name, crdName string, annotation, labels map[string]string, extension *runtime.RawExtension, tp types.CapType, - applyTo []string, schematic *commontypes.Schematic, pd *packages.PackageDiscover) (types.Capability, error) { + applyTo []string, schematic *commontypes.Schematic) (types.Capability, error) { var tmp types.Capability - tmp, err := HandleTemplate(extension, schematic, name, pd) + tmp, err := HandleTemplate(extension, schematic, name) if err != nil { return types.Capability{}, err } @@ -352,7 +341,7 @@ func GetExample(annotation map[string]string) string { } // HandleTemplate will handle definition template to capability -func HandleTemplate(in *runtime.RawExtension, schematic *commontypes.Schematic, name string, pd *packages.PackageDiscover) (types.Capability, error) { +func HandleTemplate(in *runtime.RawExtension, schematic *commontypes.Schematic, name string) (types.Capability, error) { tmp, err := appfile.ConvertTemplateJSON2Object(name, in, schematic) if err != nil { return types.Capability{}, err @@ -382,7 +371,7 @@ func HandleTemplate(in *runtime.RawExtension, schematic *commontypes.Schematic, if tmp.CueTemplate == "" { return types.Capability{}, errors.New("template not exist in definition") } - tmp.Parameters, err = cue.GetParameters(tmp.CueTemplate, pd) + tmp.Parameters, err = cue.GetParameters(tmp.CueTemplate) if err != nil && !errors.Is(err, cue.ErrParameterNotExist) { return types.Capability{}, err } @@ -391,7 +380,7 @@ func HandleTemplate(in *runtime.RawExtension, schematic *commontypes.Schematic, } // GetCapabilityByName gets capability by definition name -func GetCapabilityByName(ctx context.Context, c common.Args, capabilityName string, ns string, pd *packages.PackageDiscover) (*types.Capability, error) { +func GetCapabilityByName(ctx context.Context, c common.Args, capabilityName string, ns string) (*types.Capability, error) { var ( foundCapability bool capability *types.Capability @@ -465,7 +454,7 @@ func GetCapabilityByName(ctx context.Context, c common.Args, capabilityName stri } } if foundCapability { - capability, err = GetCapabilityByWorkflowStepDefinitionObject(wfStepDef, pd) + capability, err = GetCapabilityByWorkflowStepDefinitionObject(wfStepDef) if err != nil { return nil, err } @@ -479,7 +468,7 @@ func GetCapabilityByName(ctx context.Context, c common.Args, capabilityName stri } // GetCapabilityFromDefinitionRevision gets capabilities from the underlying Definition in DefinitionRevisions -func GetCapabilityFromDefinitionRevision(ctx context.Context, c common.Args, pd *packages.PackageDiscover, ns, defName string, r int64) (*types.Capability, error) { +func GetCapabilityFromDefinitionRevision(ctx context.Context, c common.Args, ns, defName string, r int64) (*types.Capability, error) { k8sClient, err := c.GetClient() if err != nil { return nil, err @@ -524,7 +513,7 @@ func GetCapabilityFromDefinitionRevision(ctx context.Context, c common.Args, pd case commontypes.TraitType: return GetCapabilityByTraitDefinitionObject(rev.Spec.TraitDefinition) case commontypes.WorkflowStepType: - return GetCapabilityByWorkflowStepDefinitionObject(rev.Spec.WorkflowStepDefinition, pd) + return GetCapabilityByWorkflowStepDefinitionObject(rev.Spec.WorkflowStepDefinition) default: return nil, fmt.Errorf("unsupported type %s", rev.Spec.DefinitionType) } @@ -533,7 +522,7 @@ func GetCapabilityFromDefinitionRevision(ctx context.Context, c common.Args, pd // GetCapabilityByComponentDefinitionObject gets capability by ComponentDefinition object func GetCapabilityByComponentDefinitionObject(componentDef v1beta1.ComponentDefinition, referenceName string) (*types.Capability, error) { capability, err := HandleDefinition(componentDef.Name, referenceName, componentDef.Annotations, componentDef.Labels, - componentDef.Spec.Extension, types.TypeComponentDefinition, nil, componentDef.Spec.Schematic, nil) + componentDef.Spec.Extension, types.TypeComponentDefinition, nil, componentDef.Spec.Schematic) if err != nil { return nil, errors.Wrap(err, "failed to handle ComponentDefinition") } @@ -548,7 +537,7 @@ func GetCapabilityByTraitDefinitionObject(traitDef v1beta1.TraitDefinition) (*ty err error ) capability, err = HandleDefinition(traitDef.Name, traitDef.Spec.Reference.Name, traitDef.Annotations, traitDef.Labels, - traitDef.Spec.Extension, types.TypeTrait, nil, traitDef.Spec.Schematic, nil) + traitDef.Spec.Extension, types.TypeTrait, nil, traitDef.Spec.Schematic) if err != nil { return nil, errors.Wrap(err, "failed to handle TraitDefinition") } @@ -557,9 +546,9 @@ func GetCapabilityByTraitDefinitionObject(traitDef v1beta1.TraitDefinition) (*ty } // GetCapabilityByWorkflowStepDefinitionObject gets capability by WorkflowStepDefinition object -func GetCapabilityByWorkflowStepDefinitionObject(wfStepDef v1beta1.WorkflowStepDefinition, pd *packages.PackageDiscover) (*types.Capability, error) { +func GetCapabilityByWorkflowStepDefinitionObject(wfStepDef v1beta1.WorkflowStepDefinition) (*types.Capability, error) { capability, err := HandleDefinition(wfStepDef.Name, wfStepDef.Spec.Reference.Name, wfStepDef.Annotations, wfStepDef.Labels, - nil, types.TypeWorkflowStep, nil, wfStepDef.Spec.Schematic, pd) + nil, types.TypeWorkflowStep, nil, wfStepDef.Spec.Schematic) if err != nil { return nil, errors.Wrap(err, "failed to handle WorkflowStepDefinition") } @@ -568,9 +557,9 @@ func GetCapabilityByWorkflowStepDefinitionObject(wfStepDef v1beta1.WorkflowStepD } // GetCapabilityByPolicyDefinitionObject gets capability by PolicyDefinition object -func GetCapabilityByPolicyDefinitionObject(def v1beta1.PolicyDefinition, pd *packages.PackageDiscover) (*types.Capability, error) { +func GetCapabilityByPolicyDefinitionObject(def v1beta1.PolicyDefinition) (*types.Capability, error) { capability, err := HandleDefinition(def.Name, def.Spec.Reference.Name, def.Annotations, def.Labels, - nil, types.TypePolicy, nil, def.Spec.Schematic, pd) + nil, types.TypePolicy, nil, def.Spec.Schematic) if err != nil { return nil, errors.Wrap(err, "failed to handle PolicyDefinition") } diff --git a/references/docgen/cluster_test.go b/references/docgen/cluster_test.go index 7ef950bf5..3731829ec 100644 --- a/references/docgen/cluster_test.go +++ b/references/docgen/cluster_test.go @@ -188,15 +188,15 @@ var _ = Describe("test GetCapabilityByName", func() { It("get capability", func() { By("ComponentDefinition is in the current namespace") - _, err := GetCapabilityByName(ctx, c, component1, ns, nil) + _, err := GetCapabilityByName(ctx, c, component1, ns) Expect(err).Should(BeNil()) By("ComponentDefinition is in the default namespace") - _, err = GetCapabilityByName(ctx, c, component2, ns, nil) + _, err = GetCapabilityByName(ctx, c, component2, ns) Expect(err).Should(BeNil()) By("capability cloud not be found") - _, err = GetCapabilityByName(ctx, c, "a-component-definition-not-existed", ns, nil) + _, err = GetCapabilityByName(ctx, c, "a-component-definition-not-existed", ns) Expect(err).Should(HaveOccurred()) }) }) @@ -298,17 +298,17 @@ var _ = Describe("test GetCapabilityFromDefinitionRevision", func() { }) It("non-existent defrev", func() { - _, err := GetCapabilityFromDefinitionRevision(ctx, c, nil, "rev-test-custom-ns", "not-a-name", 0) + _, err := GetCapabilityFromDefinitionRevision(ctx, c, "rev-test-custom-ns", "not-a-name", 0) Expect(err).ShouldNot(Succeed()) }) It("component type", func() { - _, err := GetCapabilityFromDefinitionRevision(ctx, c, nil, "rev-test-ns", "webservice", 0) + _, err := GetCapabilityFromDefinitionRevision(ctx, c, "rev-test-ns", "webservice", 0) Expect(err).Should(Succeed()) }) It("trait type", func() { - _, err := GetCapabilityFromDefinitionRevision(ctx, c, nil, "rev-test-custom-ns", "affinity", 0) + _, err := GetCapabilityFromDefinitionRevision(ctx, c, "rev-test-custom-ns", "affinity", 0) Expect(err).Should(Succeed()) }) }) diff --git a/references/docgen/console.go b/references/docgen/console.go index 441a7a9d6..8d5306f2e 100644 --- a/references/docgen/console.go +++ b/references/docgen/console.go @@ -22,8 +22,6 @@ import ( "github.com/olekukonko/tablewriter" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/utils/common" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" @@ -47,7 +45,6 @@ type Reference interface { type FromCluster struct { Namespace string `json:"namespace"` Rev int64 `json:"revision"` - PD *packages.PackageDiscover } // FromLocal is the struct for input Definition Path @@ -94,11 +91,11 @@ type ReferenceParameterTable struct { var commonRefs []CommonReference // GenerateCUETemplateProperties get all properties of a capability -func (ref *ConsoleReference) GenerateCUETemplateProperties(capability *types.Capability, pd *packages.PackageDiscover) (string, []ConsoleReference, error) { +func (ref *ConsoleReference) GenerateCUETemplateProperties(capability *types.Capability) (string, []ConsoleReference, error) { ref.DisplayFormat = "console" capName := capability.Name - cueValue, err := common.GetCUEParameterValue(capability.CueTemplate, pd) + cueValue, err := common.GetCUEParameterValue(capability.CueTemplate) if err != nil { return "", nil, fmt.Errorf("failed to retrieve `parameters` value from %s with err: %w", capName, err) } @@ -137,11 +134,7 @@ func (ref *ConsoleReference) Show(ctx context.Context, c common.Args, ioStreams var propertyConsole []ConsoleReference switch capability.Category { case types.CUECategory: - var pd *packages.PackageDiscover - if ref.Remote != nil { - pd = ref.Remote.PD - } - _, propertyConsole, err = ref.GenerateCUETemplateProperties(capability, pd) + _, propertyConsole, err = ref.GenerateCUETemplateProperties(capability) if err != nil { return err } diff --git a/references/docgen/convert.go b/references/docgen/convert.go index 145cd25d9..a9fc95967 100644 --- a/references/docgen/convert.go +++ b/references/docgen/convert.go @@ -23,15 +23,13 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam/util" ) // ParseCapabilityFromUnstructured will convert Unstructured to Capability -func ParseCapabilityFromUnstructured(mapper meta.RESTMapper, pd *packages.PackageDiscover, obj unstructured.Unstructured) (types.Capability, error) { +func ParseCapabilityFromUnstructured(mapper meta.RESTMapper, obj unstructured.Unstructured) (types.Capability, error) { var err error switch obj.GetKind() { case "ComponentDefinition": @@ -50,28 +48,28 @@ func ParseCapabilityFromUnstructured(mapper meta.RESTMapper, pd *packages.Packag } workloadDefinitionRef = ref.Name } - return HandleDefinition(cd.Name, workloadDefinitionRef, cd.Annotations, cd.Labels, cd.Spec.Extension, types.TypeComponentDefinition, nil, cd.Spec.Schematic, pd) + return HandleDefinition(cd.Name, workloadDefinitionRef, cd.Annotations, cd.Labels, cd.Spec.Extension, types.TypeComponentDefinition, nil, cd.Spec.Schematic) case "TraitDefinition": var td v1beta1.TraitDefinition err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &td) if err != nil { return types.Capability{}, err } - return HandleDefinition(td.Name, td.Spec.Reference.Name, td.Annotations, td.Labels, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic, pd) + return HandleDefinition(td.Name, td.Spec.Reference.Name, td.Annotations, td.Labels, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic) case "PolicyDefinition": var plcd v1beta1.PolicyDefinition err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &plcd) if err != nil { return types.Capability{}, err } - return HandleDefinition(plcd.Name, plcd.Spec.Reference.Name, plcd.Annotations, plcd.Labels, nil, types.TypePolicy, nil, plcd.Spec.Schematic, pd) + return HandleDefinition(plcd.Name, plcd.Spec.Reference.Name, plcd.Annotations, plcd.Labels, nil, types.TypePolicy, nil, plcd.Spec.Schematic) case "WorkflowStepDefinition": var wfd v1beta1.WorkflowStepDefinition err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &wfd) if err != nil { return types.Capability{}, err } - return HandleDefinition(wfd.Name, wfd.Spec.Reference.Name, wfd.Annotations, wfd.Labels, nil, types.TypeWorkflowStep, nil, wfd.Spec.Schematic, pd) + return HandleDefinition(wfd.Name, wfd.Spec.Reference.Name, wfd.Annotations, wfd.Labels, nil, types.TypeWorkflowStep, nil, wfd.Spec.Schematic) } return types.Capability{}, fmt.Errorf("unknown definition Type %s", obj.GetKind()) } diff --git a/references/docgen/markdown.go b/references/docgen/markdown.go index d6bca9a9e..428d06a42 100644 --- a/references/docgen/markdown.go +++ b/references/docgen/markdown.go @@ -24,7 +24,6 @@ import ( "sort" "strings" - "github.com/kubevela/workflow/pkg/cue/packages" "github.com/pkg/errors" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -53,25 +52,11 @@ func (ref *MarkdownReference) GenerateReferenceDocs(ctx context.Context, c commo if err != nil { return err } - var pd *packages.PackageDiscover - if ref.Remote != nil { - pd = ref.Remote.PD - } - if pd == nil { - pd = func() *packages.PackageDiscover { - rpd, err := c.GetPackageDiscover() - if err != nil { - klog.Error("fail to build package discover", err) - return nil - } - return rpd - }() - } - return ref.CreateMarkdown(ctx, caps, baseRefPath, false, pd) + return ref.CreateMarkdown(ctx, caps, baseRefPath, false) } // CreateMarkdown creates markdown based on capabilities -func (ref *MarkdownReference) CreateMarkdown(ctx context.Context, caps []types.Capability, baseRefPath string, catalog bool, pd *packages.PackageDiscover) error { +func (ref *MarkdownReference) CreateMarkdown(ctx context.Context, caps []types.Capability, baseRefPath string, catalog bool) error { sort.Slice(caps, func(i, j int) bool { return caps[i].Name < caps[j].Name @@ -83,7 +68,7 @@ func (ref *MarkdownReference) CreateMarkdown(ctx context.Context, caps []types.C if ref.Filter != nil && !ref.Filter(c) { continue } - capDoc, err := ref.GenerateMarkdownForCap(ctx, c, pd, ref.AllInOne) + capDoc, err := ref.GenerateMarkdownForCap(ctx, c, ref.AllInOne) if err != nil { return err } @@ -139,7 +124,7 @@ func (ref *MarkdownReference) CreateMarkdown(ctx context.Context, caps []types.C // GenerateMarkdownForCap will generate markdown for one capability // nolint:gocyclo -func (ref *MarkdownReference) GenerateMarkdownForCap(_ context.Context, c types.Capability, pd *packages.PackageDiscover, containSuffix bool) (string, error) { +func (ref *MarkdownReference) GenerateMarkdownForCap(_ context.Context, c types.Capability, containSuffix bool) (string, error) { var ( description string base string @@ -160,7 +145,7 @@ func (ref *MarkdownReference) GenerateMarkdownForCap(_ context.Context, c types. capNameInTitle := ref.makeReadableTitle(capName) switch c.Category { case types.CUECategory: - cueValue, err := common.GetCUEParameterValue(c.CueTemplate, pd) + cueValue, err := common.GetCUEParameterValue(c.CueTemplate) if err != nil && !errors.Is(err, cue.ErrParameterNotExist) { return "", fmt.Errorf("failed to retrieve `parameters` value from %s with err: %w", c.Name, err) } @@ -171,7 +156,7 @@ func (ref *MarkdownReference) GenerateMarkdownForCap(_ context.Context, c types. } if c.Type == types.TypeComponentDefinition { var warnErr error - baseDoc, warnErr = GetBaseResourceKinds(c.CueTemplate, pd, ref.Client.RESTMapper()) + baseDoc, warnErr = GetBaseResourceKinds(c.CueTemplate, ref.Client.RESTMapper()) if warnErr != nil { klog.Warningf("failed to get base resource kinds for %s: %v", c.Name, warnErr) } diff --git a/references/docgen/markdown_test.go b/references/docgen/markdown_test.go index d77abbe3e..4e09db756 100644 --- a/references/docgen/markdown_test.go +++ b/references/docgen/markdown_test.go @@ -47,7 +47,7 @@ func TestCreateMarkdownForCUE(t *testing.T) { mr.Local = &FromLocal{Paths: []string{"./testdata/testdef.cue"}} capp, err := ParseLocalFile(mr.Local.Paths[0], common.Args{}) assert.NoError(t, err) - got, err := mr.GenerateMarkdownForCap(context.Background(), *capp, nil, false) + got, err := mr.GenerateMarkdownForCap(context.Background(), *capp, false) assert.NoError(t, err) fmt.Println(got) assert.Contains(t, got, "A test key") @@ -59,7 +59,7 @@ func TestCreateMarkdownForCUE(t *testing.T) { mr.Local = &FromLocal{Paths: []string{"./testdata/testdeftrait.cue"}} capp, err = ParseLocalFile(mr.Local.Paths[0], common.Args{}) assert.NoError(t, err) - got, err = mr.GenerateMarkdownForCap(context.Background(), *capp, nil, false) + got, err = mr.GenerateMarkdownForCap(context.Background(), *capp, false) assert.NoError(t, err) assert.Contains(t, got, "Specify the hostAliases to add") assert.Contains(t, got, "title: Testdeftrait") @@ -162,7 +162,7 @@ variable "acl" { for name, tc := range cases { t.Run(name, func(t *testing.T) { - got := tc.ref.CreateMarkdown(ctx, tc.capabilities, RefTestDir, false, nil) + got := tc.ref.CreateMarkdown(ctx, tc.capabilities, RefTestDir, false) if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { t.Errorf("\n%s\nCreateMakrdown(...): -want error, +got error:\n%s", tc.reason, diff) } diff --git a/references/docgen/parser.go b/references/docgen/parser.go index 7a803518c..b7d4a3747 100644 --- a/references/docgen/parser.go +++ b/references/docgen/parser.go @@ -29,10 +29,11 @@ import ( "cuelang.org/go/cue" "cuelang.org/go/cue/ast" + "cuelang.org/go/cue/cuecontext" "github.com/getkin/kin-openapi/openapi3" "github.com/olekukonko/tablewriter" "github.com/pkg/errors" - "github.com/rogpeppe/go-internal/modfile" + "golang.org/x/mod/modfile" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -41,9 +42,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/yaml" - "github.com/kubevela/workflow/pkg/cue/model/value" - "github.com/kubevela/workflow/pkg/cue/packages" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/controller/utils" @@ -71,7 +69,7 @@ type ParseReference struct { func (ref *ParseReference) getCapabilities(ctx context.Context, c common.Args) ([]types.Capability, error) { var ( caps []types.Capability - pd *packages.PackageDiscover + err error ) switch { case ref.Local != nil: @@ -87,15 +85,6 @@ func (ref *ParseReference) getCapabilities(ctx context.Context, c common.Args) ( caps = append(caps, *lcap) } case ref.Remote != nil: - config, err := c.GetConfig() - if err != nil { - return nil, err - } - pd, err = packages.NewPackageDiscover(config) - if err != nil { - return nil, err - } - ref.Remote.PD = pd if ref.DefinitionName == "" { caps, err = LoadAllInstalledCapability("default", c) if err != nil { @@ -104,12 +93,12 @@ func (ref *ParseReference) getCapabilities(ctx context.Context, c common.Args) ( } else { var rcap *types.Capability if ref.Remote.Rev == 0 { - rcap, err = GetCapabilityByName(ctx, c, ref.DefinitionName, ref.Remote.Namespace, pd) + rcap, err = GetCapabilityByName(ctx, c, ref.DefinitionName, ref.Remote.Namespace) if err != nil { return nil, fmt.Errorf("failed to get capability %s: %w", ref.DefinitionName, err) } } else { - rcap, err = GetCapabilityFromDefinitionRevision(ctx, c, pd, ref.Remote.Namespace, ref.DefinitionName, ref.Remote.Rev) + rcap, err = GetCapabilityFromDefinitionRevision(ctx, c, ref.Remote.Namespace, ref.DefinitionName, ref.Remote.Rev) if err != nil { return nil, fmt.Errorf("failed to get revision %v of capability %s: %w", ref.Remote.Rev, ref.DefinitionName, err) } @@ -265,7 +254,8 @@ func (ref *ParseReference) parseParameters(capName string, paraValue cue.Value, param.Type = val.IncompleteKind() switch val.IncompleteKind() { case cue.StructKind: - if subField, err := val.Struct(); err == nil && subField.Len() == 0 { // err cannot be not nil,so ignore it + subField, err := val.Struct() + if (err == nil && subField.Len() == 0) && val.IsConcrete() { // err cannot be not nil,so ignore it if mapValue, ok := val.Elem(); ok { indentName := getIndentName(mapValue) _, err := mapValue.Fields() @@ -629,10 +619,6 @@ func ParseLocalFile(localFilePath string, c common.Args) (*types.Capability, err if err = def.FromCUEString(string(data), config); err != nil { return nil, errors.Wrapf(err, "failed to parse CUE for definition") } - pd, err := c.GetPackageDiscover() - if err != nil { - klog.Warning("fail to build package discover, use local info instead", err) - } cli, err := c.GetClient() if err != nil { klog.Warning("fail to build client, use local info instead", err) @@ -641,7 +627,7 @@ func ParseLocalFile(localFilePath string, c common.Args) (*types.Capability, err if cli != nil { mapper = cli.RESTMapper() } - lcap, err := ParseCapabilityFromUnstructured(mapper, pd, def.Unstructured) + lcap, err := ParseCapabilityFromUnstructured(mapper, def.Unstructured) if err != nil { return nil, errors.Wrapf(err, "fail to parse definition to capability %s", def.GetName()) } @@ -698,13 +684,8 @@ func WalkParameterSchema(parameters *openapi3.Schema, name string, depth int) { } // GetBaseResourceKinds helps get resource.group string of components' base resource -func GetBaseResourceKinds(cueStr string, pd *packages.PackageDiscover, mapper meta.RESTMapper) (string, error) { - t, err := value.NewValue(cueStr+velacue.BaseTemplate, pd, "") - if err != nil { - return "", errors.Wrap(err, "failed to parse base template") - } - tmpl := t.CueValue() - +func GetBaseResourceKinds(cueStr string, mapper meta.RESTMapper) (string, error) { + tmpl := cuecontext.New().CompileString(cueStr + velacue.BaseTemplate) kindValue := tmpl.LookupPath(cue.ParsePath("output.kind")) kind, err := kindValue.String() if err != nil { diff --git a/references/docgen/parser_test.go b/references/docgen/parser_test.go index e516788f4..4c4a26379 100644 --- a/references/docgen/parser_test.go +++ b/references/docgen/parser_test.go @@ -596,7 +596,7 @@ func TestExtractParameter(t *testing.T) { Name | Description | Type | Required | Default ---- | ----------- | ---- | -------- | ------- - envMappings | | map[string]string | true |`, + envMappings | | map[string]string | true | `, }, "normal-map-case": { cueTemplate: `parameter: { @@ -718,7 +718,7 @@ func TestExtractParameter(t *testing.T) { ref := &MarkdownReference{} for key, ca := range testcases { - cueValue, _ := common.GetCUEParameterValue(ca.cueTemplate, nil) + cueValue, _ := common.GetCUEParameterValue(ca.cueTemplate) out, _, err := ref.parseParameters("", cueValue, key, 0, false) assert.NoError(t, err, key) assert.Contains(t, out, ca.contains, key) @@ -824,7 +824,7 @@ func TestExtractParameterFromFiles(t *testing.T) { for key, ca := range testcases { content, err := os.ReadFile(ca.path) assert.NoError(t, err, ca.path) - cueValue, _ := common.GetCUEParameterValue(string(content), nil) + cueValue, _ := common.GetCUEParameterValue(string(content)) out, _, err := ref.parseParameters("", cueValue, key, 0, false) assert.NoError(t, err, key) assert.Contains(t, out, ca.contains, key) diff --git a/vela-templates/definitions/internal/trait/gateway.cue b/vela-templates/definitions/internal/trait/gateway.cue index e3c68efcf..772d252ad 100644 --- a/vela-templates/definitions/internal/trait/gateway.cue +++ b/vela-templates/definitions/internal/trait/gateway.cue @@ -17,11 +17,11 @@ gateway: { } let ingressMetaName = context.name + nameSuffix let ig = [for i in context.outputs if (i.kind == "Ingress") && (i.metadata.name == ingressMetaName) {i}][0] - igs: *null | string + igs: *{} | {} if ig != _|_ if ig.status != _|_ if ig.status.loadbalancer != _|_ { igs: ig.status.loadbalancer.ingress[0] } - igr: *null | string + igr: *{} | {} if ig != _|_ if ig.spec != _|_ { igr: ig.spec.rules[0] } @@ -41,7 +41,7 @@ gateway: { if igr.host != _|_ { message: "Visiting URL: " + igr.host + "\n" } - if igs.host == _|_ { + if igr.host == _|_ { message: "Host not specified, visit the cluster or load balancer in front of the cluster\n" } } diff --git a/vela-templates/definitions/internal/workflowstep/collect-service-endpoints.cue b/vela-templates/definitions/internal/workflowstep/collect-service-endpoints.cue index 93d4bbbe9..517060357 100644 --- a/vela-templates/definitions/internal/workflowstep/collect-service-endpoints.cue +++ b/vela-templates/definitions/internal/workflowstep/collect-service-endpoints.cue @@ -30,7 +30,7 @@ template: { } } } - } @step(1) + } outputs: { eps_port_name_filtered: *[] | [...] @@ -69,7 +69,7 @@ template: { wait: op.#ConditionalWait & { continue: len(outputs.endpoints) > 0 - } @step(2) + } value: { if len(outputs.endpoints) > 0 { diff --git a/vela-templates/definitions/internal/workflowstep/depends-on-app.cue b/vela-templates/definitions/internal/workflowstep/depends-on-app.cue index 720594a92..6aedc7bd4 100644 --- a/vela-templates/definitions/internal/workflowstep/depends-on-app.cue +++ b/vela-templates/definitions/internal/workflowstep/depends-on-app.cue @@ -34,14 +34,14 @@ template: { namespace: parameter.namespace } } - } @step(1) + } template: configMap.value.data["application"] apply: op.#Apply & { value: yaml.Unmarshal(template) - } @step(2) + } wait: op.#ConditionalWait & { continue: apply.value.status.status == "running" - } @step(3) + } } if dependsOn.err == _|_ { diff --git a/vela-templates/definitions/internal/workflowstep/export-data.cue b/vela-templates/definitions/internal/workflowstep/export-data.cue index 98bfe2afa..4657c2205 100644 --- a/vela-templates/definitions/internal/workflowstep/export-data.cue +++ b/vela-templates/definitions/internal/workflowstep/export-data.cue @@ -32,14 +32,14 @@ template: { if parameter.kind == "Secret" { stringData: parameter.data } - } @step(1) + } getPlacements: op.#GetPlacementsFromTopologyPolicies & { policies: *[] | [...string] if parameter.topology != _|_ { policies: [parameter.topology] } - } @step(2) + } apply: op.#Steps & { for p in getPlacements.placements { @@ -48,7 +48,7 @@ template: { cluster: p.cluster } } - } @step(3) + } parameter: { // +usage=Specify the name of the export destination diff --git a/vela-templates/definitions/internal/workflowstep/export-service.cue b/vela-templates/definitions/internal/workflowstep/export-service.cue index 033bd00ea..b9b6d3adb 100644 --- a/vela-templates/definitions/internal/workflowstep/export-service.cue +++ b/vela-templates/definitions/internal/workflowstep/export-service.cue @@ -43,14 +43,14 @@ template: { addresses: [{ip: parameter.ip}] ports: [{port: parameter.targetPort}] }] - }] @step(1) + }] getPlacements: op.#GetPlacementsFromTopologyPolicies & { policies: *[] | [...string] if parameter.topology != _|_ { policies: [parameter.topology] } - } @step(2) + } apply: op.#Steps & { for p in getPlacements.placements { @@ -61,7 +61,7 @@ template: { } } } - } @step(3) + } parameter: { // +usage=Specify the name of the export destination diff --git a/vela-templates/definitions/internal/workflowstep/webhook.cue b/vela-templates/definitions/internal/workflowstep/webhook.cue index 795c6a8f7..d39d8bc08 100644 --- a/vela-templates/definitions/internal/workflowstep/webhook.cue +++ b/vela-templates/definitions/internal/workflowstep/webhook.cue @@ -24,11 +24,11 @@ template: { namespace: context.namespace } } - } @step(1) - value: json.Marshal(read.value) @step(2) + } + value: json.Marshal(read.value) } if parameter.data != _|_ { - value: json.Marshal(parameter.data) @step(3) + value: json.Marshal(parameter.data) } } webhook: op.#Steps & { @@ -39,7 +39,7 @@ template: { body: data.value header: "Content-Type": "application/json" } - } @step(4) + } } if parameter.url.secretRef != _|_ && parameter.url.value == _|_ { read: op.#Read & { @@ -51,16 +51,16 @@ template: { namespace: context.namespace } } - } @step(5) + } - stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} @step(6) + stringValue: op.#ConvertString & {bt: base64.Decode(null, read.value.data[parameter.url.secretRef.key])} http: op.#HTTPPost & { url: stringValue.str request: { body: data.value header: "Content-Type": "application/json" } - } @step(7) + } } }