Compare commits

...

48 Commits

Author SHA1 Message Date
github-actions[bot]
b1cc06b0f3 Feat: support dry-run with cue format definition (#5080)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit ce75a33633)

Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-11-16 18:11:58 +08:00
github-actions[bot]
ed9d53b448 Feat: add print message example (#5079)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit ee2b854c80)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-16 16:38:06 +08:00
github-actions[bot]
ad83e59865 [Backport release-1.6] Feat: add apply component definition for docs (#5076)
* Feat: add apply component definition for docs

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit d31dbecb76)

* Feat: add apply component definition for docs

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 454edb05ff)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-16 15:45:49 +08:00
github-actions[bot]
b62eeca3f9 [Backport release-1.6] Fix: code vulnerability (#5075)
* Fix: code vulnerability

Signed-off-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit d47019de35)

* lint

Signed-off-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 7a51a1f22a)

* imports

Signed-off-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 8040fe63ce)

* use space

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 80d16b480c)

* reuse sanitize function

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 75695440b1)

Co-authored-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2022-11-16 15:45:25 +08:00
github-actions[bot]
5d9757fcb8 Feat: support vela up --wait and --timeout (#5074)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit f81f26f66b)

Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-11-16 10:01:14 +08:00
github-actions[bot]
4d653951a1 add tests (#5068)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 7080d7ae31)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-11-15 13:17:06 +08:00
github-actions[bot]
bcda4976a9 [Backport release-1.6] Fix: Failed to get detail policy for application (#5049)
* Fix: Failed to get detail policy for application

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 50f63bf8bc)

* Fix: Failed to get detail policy for application

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 8c70f067fc)

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2022-11-10 21:50:22 +08:00
github-actions[bot]
a01d0e773a Fix: add debug for workflowrun and support debug sub steps (#5042)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 5749babe71)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-10 11:04:47 +08:00
github-actions[bot]
f0e3304c17 [Backport release-1.6] Fix: fix the stuck problem and use LRU cache to promote the speed of loading topology (#5036)
* Fix: fix the stuck problem and use lru cache to promote the speed of loading topology

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit 8395fe56b2)

* Fix: reuse existing lru golang library

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit d69018f71e)

Co-authored-by: HanMengnan <1448189829@qq.com>
2022-11-09 16:09:46 +08:00
github-actions[bot]
e9f1e21d55 Feat: support webservice containing duplicate port with different protocol (#5035)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit a8653e5d1c)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2022-11-09 13:15:17 +08:00
github-actions[bot]
de127b7311 Fix: higher version contraint in install command (#5033)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit a7b30ce104)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2022-11-09 11:26:33 +08:00
github-actions[bot]
9f0558c62e Fix: temporary fix comments in comprehesions for env trait (#5025)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit b9d380142d)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-09 11:22:41 +08:00
github-actions[bot]
0f547fa158 Feat: add scope label in workflow step defs (#5023)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 2d02a7ac20)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-09 11:21:59 +08:00
github-actions[bot]
84155d06fb [Backport release-1.6] Fix: remove the reference of v1beta1 ingress (#5028)
* try to remove the v1beta1 ingress

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit e7c1353ce3)

* fix tests

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 46fba4cc05)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-11-09 11:20:14 +08:00
github-actions[bot]
bc7e31f979 use vi as ingress's target apiVersion (#5022)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix test

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix test

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

revert test

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

add tests

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 6149fe406f)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-11-08 12:12:05 +08:00
github-actions[bot]
f406936dce Fix: vela status will always get external ip first (#5018)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit f1d81feece)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2022-11-07 18:55:07 +08:00
github-actions[bot]
c2ecc71941 Fix: vela cluster join reports 'resource name may not be empty' error (#5015)
Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit ce4cad677d)

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2022-11-07 16:14:47 +08:00
github-actions[bot]
c1efd3f056 Fix: fix problem of loading pods of cronjob (#5013)
Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit c074c558b6)

Co-authored-by: HanMengnan <1448189829@qq.com>
2022-11-07 16:12:52 +08:00
github-actions[bot]
7002182072 [Backport release-1.6] Fix: remove duplicate mock server in CI (#5012)
* Fix: not killing mock server process every time

Signed-off-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit abb13b9ab4)

* remove redundent mock server

Signed-off-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit b1672d1bf3)

Co-authored-by: qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2022-11-07 11:06:00 +08:00
github-actions[bot]
554a06e35e [Backport release-1.6] Fix: forbid 302 request to avoid SSRF (#5004)
* fix helm chart list endpoint SSRF CVE

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 8883a6219d)

* revert error log

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit e1e6972b17)

* change with const value

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix ci

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit fbeacb0a6b)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-11-04 20:17:15 +08:00
github-actions[bot]
4ffb7e6707 Chore: update the API schema (#4997)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 64eb622f12)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2022-11-04 13:10:56 +08:00
github-actions[bot]
caeb334340 [Backport release-1.6] Fix: test ci windows (#4991)
* Fix: test ci windows

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit f3dfa50514)

* Fix: rename add exe suffix for command

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit 447e91c316)

* Fix: trim extra commands

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit b23ce529d1)

Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-11-03 15:43:31 +08:00
github-actions[bot]
275b61d427 Fix: app contains app override the child app with parent app label (#4988)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit c39e6adc50)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2022-11-02 22:39:57 +08:00
github-actions[bot]
11904a6f60 [Backport release-1.6] Fix: fix filepath for windows (#4987)
* Fix: fix filepath for windows

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit ef5b4fbe38)

* test ci

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit fb367d3722)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-02 22:39:29 +08:00
github-actions[bot]
4b4e4f8530 [Backport release-1.6] Fix: enhance the default permissions (#4977)
* Fix: enhance the default permissions

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit c72b95c81e)

* Fix: unit test error

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 28683d0813)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2022-11-01 20:51:33 +08:00
github-actions[bot]
0121e8b6ef Feat: allowing restart a compeleted workflow (#4976)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 74eea5bed2)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-11-01 20:35:36 +08:00
github-actions[bot]
382510aa67 [Backport release-1.6] Fix: mongodb can not decode runtime.Object (#4974)
* Fix: mongodb can not decode runtime.Object

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit bc43762f86)

* reuse struct

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit fa8a6335dc)

* fix no output when filter

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 4b9e016b01)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2022-11-01 17:25:55 +08:00
github-actions[bot]
7ae7d2a5ef [Backport release-1.6] Fix: grant the permission to read the ConfigMap in the vela-system namesapce (#4970)
* Fix: grant the permission to read the ConfigMap in the vela-system namespace

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 643120d74c)

* Fix: change the test

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 13f3afd2f4)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2022-11-01 10:00:04 +08:00
github-actions[bot]
0736e85e07 [Backport release-1.6] Feat: implement pipeline APIs (#4969)
* add context when run pipeline

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 72f3ad792e)

* Feat: implement pipeline API

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit f560c346cc)

* Extract get log logic and implement getPipelineRunLog API

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 060c6ab9e9)

* Init and delete pipeline contexts

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 5e96bd3106)

* fix panic

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 51072f7947)

* Allow not specifying context

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 810ddcf0bd)

* change pipeline to path parameter

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 3d51c0cb2d)

* Add permission check filter

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 6883767430)

* project -> projects in route

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 1f09f3996b)

* fix route conflict

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 7eea696830)

* Add project alias

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit b07dd72338)

* Feat: change the list pipeline API

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit bd804734b0)

* Feat: filter the project

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 82eee2cc11)

* Fix: the error of the run APi

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit ac87bd3f1a)

* fix log pipeline run API

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit acde8e981e)

* Fix lint, fix the error of log api

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit b8373e6cde)

* fix error returning

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 2e9b4792b0)

* Fix: change the lable to annotation

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit bf08275fde)

* remove log config not found error

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit cdd77dfd8f)

* fix pipeline list api return no context info

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit cdcfa165d1)

* Fix: create the namespace

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit b6888dd87d)

* get pipeline lastrun info

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit a943423d22)

* allow query single step output

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit e2310bbf34)

* organize code in api layer

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 6fd53ed078)

* fix project filter, add context value when get pp run, extend lastRun

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 861f69d555)

* fix get output and implement get input api

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 61495ee70d)

* Fix: change the last run

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit aeb842a45e)

* if query sub-step outout, return it directly

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 467ba25751)

* Fix: change the run stats

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 7a90e7e310)

* Fix: change the output

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 595a871b0d)

* flatten the input/output api

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit efc9692354)

* more info for i/o vars

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 7fe0e1109c)

* fix nested i/o struct

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 201d1228bd)

* add fromStep in input api

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 2400018962)

* add e2e test skeleton

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit f20f9a1ac6)

* add more e2e test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 98b27f886b)

* use db to store pipeline

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 08962c4f2f)

* keep the last 5k lines of log

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 22b352da14)

* use stern param to keep last lines of logs

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 3eadbf91c8)

* filter, nil labels, spec check

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit bad90b3f7a)

* empty res, index, detail param

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit b12d889e97)

* Add e2e test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit ae617a928e)

* fix e2e test and unit test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 0f4e030b84)

* add context e2e test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 88879e6e43)

* goimports

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 58429978b3)

* add more test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 75760521a4)

* review

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit cc4c706466)

* remove optional tag in returned value, unify the imports name

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 658b184aef)

* fix e2e test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit a9e9c96856)

* add stop test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 58aa2e5125)

* more coverage

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 01ecb51323)

* single case selct

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit d9e8fd0342)

* optimize log color

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit be9840c3cb)

* add default permission and role

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit cf074444ac)

* fix permission ut

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 1bdcad63a2)

* change the log api implementation

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 587f745430)

* add color, add container order

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 6e7f187605)

* lint

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 64ba029031)

* fix filter nil will cut all log

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 799dfe377a)

* longer timeout and lint

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 89873f1f66)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2022-11-01 00:13:37 +08:00
github-actions[bot]
f01e6d9723 Chore: stable the version of cue and workflow (#4964)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 0defa2d53d)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-10-31 15:12:35 +08:00
github-actions[bot]
2d7d4ef99d [Backport release-1.6] Fix: do not change the workflow after the env changed (#4962)
* Fix: do not change the workflow after the env changed

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 3425c2043f)

* Fix: change the test case

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit c593fcd75b)

* Fix: check app when deleting the target from a env

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit d2d25a8f9d)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2022-10-31 11:19:49 +08:00
github-actions[bot]
6bbce07a21 Feat: add mode in workflow template (#4960)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 19a30371dd)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-10-31 11:09:54 +08:00
github-actions[bot]
12ba4631c1 [Backport release-1.6] Fix: bocde error override origin error message (#4955)
* fix bcode error

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 499b86d5c7)

* small fix

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 9020984c97)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-10-29 17:05:25 +08:00
github-actions[bot]
d5b4f9ae5d [Backport release-1.6] Fix: update namespace only if it doesn't have the env label (#4953)
* Fix: update namespace only if it doesn't have the env label

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 9cf18e94d8)

* Fix: update namespace only if it doesn't have the env label

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 4031aa25ae)

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2022-10-29 10:36:02 +08:00
github-actions[bot]
d62185315a It is unnecessary to judge that the index function is not null (#4952)
Signed-off-by: liutiangang <liutiangang@cmbchina.com>
(cherry picked from commit 2570df7e83)

Co-authored-by: liutiangang <liutiangang@cmbchina.com>
2022-10-29 09:13:48 +08:00
github-actions[bot]
12f0cebc6c more error info for apiservice and add tests (#4949)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

change the mock addon version

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 73d6f2201c)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-10-29 08:32:26 +08:00
github-actions[bot]
284a7d08b2 Feat: sync the model of api workflow with core (#4950)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 0bfa9f9143)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-10-29 08:31:13 +08:00
github-actions[bot]
c91850ce0d Fix: apiserver & vela status use multi-cluster client (#4946)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit a1a3996062)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2022-10-28 14:15:58 +08:00
github-actions[bot]
e13b31d00e [Backport release-1.6] Fix: can't obtain pods generated by Crontask component (patch of PR 4925) (#4945)
* Fix: get label selector from cronJob

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit 03be6b3f8f)

* Fix: small fix

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit b8c97411d5)

* Fix: use scheme create obj

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit fa00132e2d)

* Fix: update method of generating selector

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit d30010ec7a)

* Fix: update cron-task

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit 864c04eee6)

* Fix: add test case

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit c1cdf8f290)

* Fix: add test case

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit f977805810)

Co-authored-by: HanMengnan <1448189829@qq.com>
2022-10-28 11:34:28 +08:00
github-actions[bot]
71d0d7344f Fix: fix gen doc for container image (#4937)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 33f7c2539b)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-10-27 22:19:10 +08:00
github-actions[bot]
247845db0a fix gitlab addon registry (#4939)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit f3ee964734)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-10-27 22:17:58 +08:00
github-actions[bot]
427809cea7 Fix: update export2config and export2secret example (#4940)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit b2de4020a4)

Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-10-27 19:07:39 +08:00
github-actions[bot]
6c29b7b088 Fix: get Application status using jsonpath filter expression (#4933)
Signed-off-by: yanghaojia <yanghaojia@coding.net>
(cherry picked from commit 16272cffaa)

Co-authored-by: yanghaojia <yanghaojia@coding.net>
2022-10-27 14:45:14 +08:00
github-actions[bot]
77e85472fa [Backport release-1.6] Fix: can't get pods of CronTask component (#4930)
* Fix: get label selector from cronJob

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit a9b2c3ac88)

* Fix: update cron-task yaml

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit 188b544db0)

* Fix: small fix

Signed-off-by: HanMengnan <1448189829@qq.com>
(cherry picked from commit 9d393df2fa)

Co-authored-by: HanMengnan <1448189829@qq.com>
2022-10-27 11:22:51 +08:00
github-actions[bot]
c60df945c3 [Backport release-1.6] Feat: support operations for workflow run (#4924)
* Feat: support operations for workflow run

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 5b721ad97b)

* fix test

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 9421eb4a78)

* fix lint

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 0b2f6b46c7)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-10-27 10:26:13 +08:00
github-actions[bot]
28488a4e9b [Backport release-1.6] Feat: enhance the apply-once capability (#4919)
* Feat: enhance the apply-once capability

Signed-off-by: 朱晓兵 <596908030@qq.com>
(cherry picked from commit 43eef883d0)

* Fix: add unit-test

Signed-off-by: 朱晓兵 <596908030@qq.com>
(cherry picked from commit 514c2bc8bd)

* Fix: adjustment variable name

Signed-off-by: 朱晓兵 <596908030@qq.com>
(cherry picked from commit 70b3621ac6)

* Fix: add doc

Signed-off-by: 朱晓兵 <596908030@qq.com>
(cherry picked from commit 5506fe9cda)

* Fix: adjustment variable name

Signed-off-by: 朱晓兵 <596908030@qq.com>
(cherry picked from commit 4e5f8d9443)

Co-authored-by: 朱晓兵 <596908030@qq.com>
2022-10-26 16:36:08 +08:00
github-actions[bot]
1ae7ba1e1e [Backport release-1.6] Fix: add sub step in vela workflow logs (#4918)
* Fix: add sub step in vela workflow logs

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 81616ffd89)

* fix lint

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit d491c6c8cf)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-10-25 16:58:02 +08:00
Somefive
2076c2f937 Feat: add feature docs and controller parameters for MultiStageComponentApply (#4873) (#4917)
Signed-off-by: ZhongsJie <zhongsjie@gmail.com>

Signed-off-by: ZhongsJie <zhongsjie@gmail.com>

Signed-off-by: ZhongsJie <zhongsjie@gmail.com>
Co-authored-by: ZhongsJie <62382570+ZhongsJie96@users.noreply.github.com>
2022-10-25 15:00:23 +08:00
179 changed files with 6611 additions and 3044 deletions

View File

@@ -176,10 +176,12 @@ jobs:
make e2e-cleanup
make e2e-setup-core
bin/vela addon enable fluxcd
bin/vela addon enable vela-workflow
timeout 600s bash -c -- 'while true; do kubectl get ns flux-system; if [ $? -eq 0 ] ; then break; else sleep 5; fi;done'
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=vela-core,app.kubernetes.io/instance=kubevela -n vela-system --timeout=600s
kubectl wait --for=condition=Ready pod -l app=source-controller -n flux-system --timeout=600s
kubectl wait --for=condition=Ready pod -l app=helm-controller -n flux-system --timeout=600s
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=vela-workflow -n vela-system --timeout=600s
- name: Run api server e2e test
run: |

View File

@@ -141,3 +141,35 @@ jobs:
- name: Cleanup binary
run: make build-cleanup
check-windows:
runs-on: windows-latest
needs: detect-noop
if: needs.detect-noop.outputs.noop != 'true'
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go Dependencies
uses: actions/cache@v2
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Run Build CLI
run: make vela-cli
- name: Run CLI for version
shell: cmd
run: |
move .\bin\vela .\bin\vela.exe
.\bin\vela.exe version

View File

@@ -189,8 +189,6 @@ type Status struct {
type ApplicationPhase string
const (
// ApplicationRollingOut means the app is in the middle of rolling out
ApplicationRollingOut ApplicationPhase = "rollingOut"
// ApplicationStarting means the app is preparing for reconcile
ApplicationStarting ApplicationPhase = "starting"
// ApplicationRendering means the app is rendering
@@ -205,8 +203,6 @@ const (
ApplicationWorkflowTerminated ApplicationPhase = "workflowTerminated"
// ApplicationWorkflowFailed means the app's workflow is failed
ApplicationWorkflowFailed ApplicationPhase = "workflowFailed"
// ApplicationWorkflowFinished means the app's workflow is finished
ApplicationWorkflowFinished ApplicationPhase = "workflowFinished"
// ApplicationRunning means the app finished rendering and applied result to the cluster
ApplicationRunning ApplicationPhase = "running"
// ApplicationUnhealthy means the app finished rendering and applied result to the cluster, but still unhealthy

View File

@@ -23,8 +23,17 @@ import (
const (
// ApplyOncePolicyType refers to the type of configuration drift policy
ApplyOncePolicyType = "apply-once"
// ApplyOnceStrategyOnAppUpdate policy takes effect on application updating
ApplyOnceStrategyOnAppUpdate ApplyOnceAffectStrategy = "onUpdate"
// ApplyOnceStrategyOnAppStateKeep policy takes effect on application state keep
ApplyOnceStrategyOnAppStateKeep ApplyOnceAffectStrategy = "onStateKeep"
// ApplyOnceStrategyAlways policy takes effect always
ApplyOnceStrategyAlways ApplyOnceAffectStrategy = "always"
)
// ApplyOnceAffectStrategy is a string that mark the policy effective stage
type ApplyOnceAffectStrategy string
// ApplyOncePolicySpec defines the spec of preventing configuration drift
type ApplyOncePolicySpec struct {
Enable bool `json:"enable"`
@@ -45,6 +54,9 @@ type ApplyOnceStrategy struct {
// Path the specified path that allow configuration drift
// like 'spec.template.spec.containers[0].resources' and '*' means the whole target allow configuration drift
Path []string `json:"path"`
// ApplyOnceAffectStrategy Decide when the strategy will take effect
// like affect:onUpdate/onStateKeep/always
ApplyOnceAffectStrategy ApplyOnceAffectStrategy `json:"affect"`
}
// FindStrategy find apply-once strategy for target resource

View File

@@ -64,6 +64,8 @@ const (
LabelDefinitionDeprecated = "custom.definition.oam.dev/deprecated"
// LabelDefinitionHidden is the label which describe whether the capability is hidden by UI
LabelDefinitionHidden = "custom.definition.oam.dev/ui-hidden"
// LabelDefinitionScope is the label which describe whether the capability's scope
LabelDefinitionScope = "custom.definition.oam.dev/scope"
// LabelNodeRoleGateway gateway role of node
LabelNodeRoleGateway = "node-role.kubernetes.io/gateway"
// LabelNodeRoleWorker worker role of node

View File

@@ -97,6 +97,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
| `featureGates.gzipResourceTracker` | if enabled, resourceTracker will be compressed using gzip before being stored | `false` |
| `featureGates.zstdResourceTracker` | if enabled, resourceTracker will be compressed using zstd before being stored. It is much faster and more efficient than gzip. If both gzip and zstd are enabled, zstd will be used. | `false` |
| `featureGates.applyOnce` | if enabled, the apply-once feature will be applied to all applications, no state-keep and no resource data storage in ResourceTracker | `false` |
| `featureGates.multiStageComponentApply` | if enabled, the multiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply. | `false` |
### MultiCluster parameters

View File

@@ -2209,10 +2209,11 @@ spec:
execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
description: SubSteps is the mode of workflow sub
steps execution
type: string
type: object
ref:
@@ -4008,6 +4009,17 @@ spec:
namespace:
type: string
type: object
mode:
description: WorkflowExecuteMode defines the mode of workflow
execution
properties:
steps:
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow

View File

@@ -1020,10 +1020,10 @@ spec:
execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
ref:

View File

@@ -1,10 +1,10 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
controller-gen.kubebuilder.io/version: v0.9.0
creationTimestamp: null
name: workflows.core.oam.dev
spec:
group: core.oam.dev
@@ -34,6 +34,16 @@ spec:
type: string
metadata:
type: object
mode:
description: WorkflowExecuteMode defines the mode of workflow execution
properties:
steps:
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
@@ -161,153 +171,3 @@ spec:
type: object
served: true
storage: true
- name: v1beta1
schema:
openAPIV3Schema:
description: Workflow defines workflow steps and other attributes
properties:
mode:
description: WorkflowExecuteMode defines the mode of workflow execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
type: string
type: object
ref:
type: string
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
x-kubernetes-preserve-unknown-fields: true
subSteps:
items:
description: WorkflowStepBase defines the workflow step base
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
x-kubernetes-preserve-unknown-fields: true
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
type: object
served: true
storage: false
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Apply components of an application in parallel for your workflow steps
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-application-in-parallel
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Apply application for your workflow steps, it has no arguments, should be used for custom steps before or after application applied.
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-application
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -0,0 +1,23 @@
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
# Definition source cue file: vela-templates/definitions/internal/apply-component.cue
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Apply a specific component and its corresponding traits in application
labels:
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-component
namespace: {{ include "systemDefinitionNamespace" . }}
spec:
schematic:
cue:
template: |
parameter: {
// +usage=Specify the component name to apply
component: string
// +usage=Specify the cluster
cluster: *"" | string
}

View File

@@ -12,6 +12,8 @@ spec:
cue:
template: |
#ApplyOnceStrategy: {
// +usage=When the strategy takes effect,e.g. onUpdate、onStateKeep
affect?: string
// +usage=Specify the path of the resource that allow configuration drift
path: [...string]
}

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Apply remaining components and traits
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-remaining
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -5,6 +5,8 @@ kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Deploy cloud resource and deliver secret to multi clusters.
labels:
custom.definition.oam.dev/scope: Application
name: deploy-cloud-resource
namespace: {{ include "systemDefinitionNamespace" . }}
spec:

View File

@@ -5,6 +5,8 @@ kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: A powerful and unified deploy step for components multi-cluster delivery with policies.
labels:
custom.definition.oam.dev/scope: Application
name: deploy
namespace: {{ include "systemDefinitionNamespace" . }}
spec:

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Deploy env binding component to target env
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: deploy2env
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Deploy application to runtime clusters
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: deploy2runtime
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -4,7 +4,7 @@ apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: pring message in workflow status
definition.oam.dev/description: print message in workflow step status
labels:
custom.definition.oam.dev/ui-hidden: "true"
name: print-message-in-status

View File

@@ -5,6 +5,8 @@ kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Sync secrets created by terraform component to runtime clusters so that runtime clusters can share the created cloud resource.
labels:
custom.definition.oam.dev/scope: Application
name: share-cloud-resource
namespace: {{ include "systemDefinitionNamespace" . }}
spec:

View File

@@ -13,6 +13,7 @@ spec:
template: |
import (
"strconv"
"strings"
)
mountsArray: [
@@ -167,7 +168,11 @@ spec:
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
_name: "port-" + strconv.FormatInt(v.port, 10)
name: *_name | string
if v.protocol != "TCP" {
name: _name + "-" + strings.ToLower(v.protocol)
}
}
}}]
}
@@ -283,11 +288,18 @@ spec:
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
_name: "port-" + strconv.FormatInt(v.port, 10)
name: *_name | string
if v.protocol != "TCP" {
name: _name + "-" + strings.ToLower(v.protocol)
}
}
if v.nodePort != _|_ && parameter.exposeType == "NodePort" {
nodePort: v.nodePort
}
if v.protocol != _|_ {
protocol: v.protocol
}
},
]
outputs: {

View File

@@ -116,6 +116,39 @@ subjects:
name: {{ include "kubevela.serviceAccountName" . }}
---
# permissions to read the view of VelaQL, schemas, and templates.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "kubevela.fullname" . }}:template-reader-role
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "kubevela.fullname" . }}:template-reader-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "kubevela.fullname" . }}:template-reader-role
subjects:
- kind: Group
name: template-reader
---
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -221,6 +254,7 @@ spec:
- "--feature-gates=GzipResourceTracker={{- .Values.featureGates.gzipResourceTracker | toString -}}"
- "--feature-gates=ZstdResourceTracker={{- .Values.featureGates.zstdResourceTracker | toString -}}"
- "--feature-gates=ApplyOnce={{- .Values.featureGates.applyOnce | toString -}}"
- "--feature-gates=MultiStageComponentApply= {{- .Values.featureGates.multiStageComponentApply | toString -}}"
{{ if .Values.authentication.enabled }}
{{ if .Values.authentication.withUser }}
- "--authentication-with-user"

View File

@@ -113,11 +113,13 @@ optimize:
##@param featureGates.gzipResourceTracker if enabled, resourceTracker will be compressed using gzip before being stored
##@param featureGates.zstdResourceTracker if enabled, resourceTracker will be compressed using zstd before being stored. It is much faster and more efficient than gzip. If both gzip and zstd are enabled, zstd will be used.
##@param featureGates.applyOnce if enabled, the apply-once feature will be applied to all applications, no state-keep and no resource data storage in ResourceTracker
##@param featureGates.multiStageComponentApply if enabled, the multiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply.
featureGates:
enableLegacyComponentRevision: false
gzipResourceTracker: false
zstdResourceTracker: false
applyOnce: false
multiStageComponentApply: false
## @section MultiCluster parameters

View File

@@ -2209,10 +2209,11 @@ spec:
execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
description: SubSteps is the mode of workflow sub
steps execution
type: string
type: object
ref:
@@ -4008,6 +4009,17 @@ spec:
namespace:
type: string
type: object
mode:
description: WorkflowExecuteMode defines the mode of workflow
execution
properties:
steps:
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow

View File

@@ -1020,10 +1020,10 @@ spec:
execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
ref:

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Apply components of an application in parallel for your workflow steps
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-application-in-parallel
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Apply application for your workflow steps, it has no arguments, should be used for custom steps before or after application applied.
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-application
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -0,0 +1,23 @@
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
# Definition source cue file: vela-templates/definitions/internal/apply-component.cue
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Apply a specific component and its corresponding traits in application
labels:
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-component
namespace: {{ include "systemDefinitionNamespace" . }}
spec:
schematic:
cue:
template: |
parameter: {
// +usage=Specify the component name to apply
component: string
// +usage=Specify the cluster
cluster: *"" | string
}

View File

@@ -12,6 +12,8 @@ spec:
cue:
template: |
#ApplyOnceStrategy: {
// +usage=When the strategy takes effect,e.g. onUpdate、onStateKeep
affect?: string
// +usage=Specify the path of the resource that allow configuration drift
path: [...string]
}

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Apply remaining components and traits
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: apply-remaining
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -5,6 +5,8 @@ kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Deploy cloud resource and deliver secret to multi clusters.
labels:
custom.definition.oam.dev/scope: Application
name: deploy-cloud-resource
namespace: {{ include "systemDefinitionNamespace" . }}
spec:

View File

@@ -5,6 +5,8 @@ kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: A powerful and unified deploy step for components multi-cluster delivery with policies.
labels:
custom.definition.oam.dev/scope: Application
name: deploy
namespace: {{ include "systemDefinitionNamespace" . }}
spec:

View File

@@ -7,6 +7,7 @@ metadata:
definition.oam.dev/description: Deploy application to runtime clusters
labels:
custom.definition.oam.dev/deprecated: "true"
custom.definition.oam.dev/scope: Application
custom.definition.oam.dev/ui-hidden: "true"
name: deploy2runtime
namespace: {{ include "systemDefinitionNamespace" . }}

View File

@@ -4,7 +4,7 @@ apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: pring message in workflow status
definition.oam.dev/description: print message in workflow step status
labels:
custom.definition.oam.dev/ui-hidden: "true"
name: print-message-in-status

View File

@@ -5,6 +5,8 @@ kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Sync secrets created by terraform component to runtime clusters so that runtime clusters can share the created cloud resource.
labels:
custom.definition.oam.dev/scope: Application
name: share-cloud-resource
namespace: {{ include "systemDefinitionNamespace" . }}
spec:

View File

@@ -13,6 +13,7 @@ spec:
template: |
import (
"strconv"
"strings"
)
mountsArray: [
@@ -167,7 +168,11 @@ spec:
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
_name: "port-" + strconv.FormatInt(v.port, 10)
name: *_name | string
if v.protocol != "TCP" {
name: _name + "-" + strings.ToLower(v.protocol)
}
}
}}]
}
@@ -283,11 +288,18 @@ spec:
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
_name: "port-" + strconv.FormatInt(v.port, 10)
name: *_name | string
if v.protocol != "TCP" {
name: _name + "-" + strings.ToLower(v.protocol)
}
}
if v.nodePort != _|_ && parameter.exposeType == "NodePort" {
nodePort: v.nodePort
}
if v.protocol != _|_ {
protocol: v.protocol
}
},
]
outputs: {

File diff suppressed because it is too large Load Diff

View File

@@ -120,4 +120,61 @@ EOF
In the `apply-once-app-3` case, any changes of `hello-cosmos` deployment will not be brought back and any changes
of `hello-cosmos` service will be brought back in the next reconcile loop. In the same time, any changes
of `hello-world` component will be brought back in the next reconcile loop.
of `hello-world` component will be brought back in the next reconcile loop.
```shell
$ cat <<EOF | kubectl apply -f -
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: apply-once-app-4
spec:
components:
- name: hello-world
type: webservice
properties:
image: crccheck/hello-world
port: 8080
traits:
- type: scaler
properties:
replicas: 1
- name: hello-cosmos
type: webservice
properties:
image: crccheck/hello-world
port: 8080
traits:
- type: scaler
properties:
replicas: 1
policies:
- name: apply-once
type: apply-once
properties:
enable: true
rules:
- selector:
componentNames: [ "hello-cosmos" ]
resourceTypes: [ "Deployment" ]
strategy:
affect: onStateKeep
path: [ "spec.replicas"]
EOF
```
By default, KubeVela executes the apply-once policy in two phases: application update and cycle state maintenance,
allowing configuration drift depending on the policy configuration.
If you have special requirements, you can set the affect to determine the phase of policy execution .
affect supported configurations: onUpdate/onStateKeep/always (default)
When affect=always, or not set, the policy is executed in two phase.
When affect=onStateKeep, the policy is executed only during the stateKeep phase. In the case of `apply-once-app-4`, any
changes to the deployed copy of `hello-cosmos` will not be brought back to the next state keeping loop, but will be
brought back to the next application update.
When affect=onUpdate, the policy is only executed when the application is updated. In the case of `
apply-once-app-4`, if affect=onUpdate is set, any changes to the deployed copy of `hello-cosmos` will not be brought
back in the next application update, but will be brought back in the next state keeping loop.

View File

@@ -0,0 +1,43 @@
# MultiStageComponentApply
This example shows how to enable MultiStageComponentApply, the MultiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply. Currently, the stage field in TraitDefinition is an optional parameter, which provides `PreDispatch` and `PostDispatch`.
## How to use multi-stage
> The future-gate is still in alpha stage, and it is recommended to use it only in short-term test clusters.
The `MultiStageComponentApply` is not enabled by default, you need some extra works to use it.
1. Add an args `--feature-gates=MultiStageComponentApply=ture` in KubeVela controller's deployment like:
```yaml
spec:
containers:
- args:
- --feature-gates=MultiStageComponentApply=true
...
```
2. Sometime, you have multi-stage apply requirements inside the component, and it is the `outputs` resource defined in the trait. In this case, you can use the `stage` with the value `PreDispatch` or `PostDispatch` like:
```yaml
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: Add storages on K8s pod for your workload which follows the pod spec in path 'spec.template'.
name: storage
namespace: vela-system
spec:
appliesToWorkloads:
- deployments.apps
- statefulsets.apps
- daemonsets.apps
- jobs.batch
podDisruptive: true
stage: PreDispatch
schematic:
cue:
template: |
...
```

View File

@@ -0,0 +1,19 @@
name: not-match-addon
version: 1.0.0
description: Extended workload to do continuous and progressive delivery
icon: https://raw.githubusercontent.com/fluxcd/flux/master/docs/_files/weave-flux.png
url: https://fluxcd.io
tags:
- mock
dependencies: []
#- name: addon_name
# set invisible means this won't be list and will be enabled when depended on
# for example, terraform-alibaba depends on terraform which is invisible,
# when terraform-alibaba is enabled, terraform will be enabled automatically
# default: false
invisible: false
system:
kubernetes: "<=v1.3.0"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -23,4 +23,41 @@ entries:
annotations:
system.vela: ">=1.5.0"
system.kubernetes: ">=1.30.0"
vela-workflow:
- annotations:
system.vela: '>=v1.6.0-beta.1'
created: "2022-10-29T09:11:16.865230605Z"
description: vela-workflow provides the capability to run a standalone workflow
home: https://github.com/kubevela/workflow
icon: https://static.kubevela.net/images/logos/KubeVela%20-03.png
name: vela-workflow
urls:
- http://127.0.0.1:9098/helm/vela-workflow-v0.3.1.tgz
version: v0.3.1
foo:
- created: "2022-10-29T09:11:16.865230605Z"
description: Vela test addon named foo
home: https://www.foo.com/icon
icon: https://www.foo.com
name: foo
urls:
- http://127.0.0.1:9098/helm/foo-v1.0.0.tgz
version: v1.0.0
bar:
- created: "2022-10-29T09:11:16.865230605Z"
description: Vela test addon named bar
home: https://www.bar.com/icon
icon: https://www.bar.com
name: foo
urls:
- http://127.0.0.1:9098/helm/bar-v1.0.0.tgz
version: v1.0.0
- created: "2022-10-29T09:11:16.865230605Z"
description: Vela test addon named bar
home: https://www.bar.com/icon
icon: https://www.bar.com
name: foo
urls:
- http://127.0.0.1:9098/helm/bar-v2.0.0.tgz
version: v2.0.0
generated: "2022-06-15T13:17:04.733573+08:00"

View File

@@ -22,9 +22,9 @@ import (
"fmt"
"html/template"
"io/fs"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"strings"
@@ -108,24 +108,49 @@ var ossHandler http.HandlerFunc = func(rw http.ResponseWriter, req *http.Request
var helmHandler http.HandlerFunc = func(rw http.ResponseWriter, req *http.Request) {
switch {
case strings.Contains(req.URL.Path, "index.yaml"):
file, err := ioutil.ReadFile("./e2e/addon/mock/testrepo/helm-repo/index.yaml")
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/index.yaml")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
case strings.Contains(req.URL.Path, "fluxcd-test-version-1.0.0.tgz"):
file, err := ioutil.ReadFile("./e2e/addon/mock/testrepo/helm-repo/fluxcd-test-version-1.0.0.tgz")
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/fluxcd-test-version-1.0.0.tgz")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
case strings.Contains(req.URL.Path, "fluxcd-test-version-2.0.0.tgz"):
file, err := ioutil.ReadFile("./e2e/addon/mock/testrepo/helm-repo/fluxcd-test-version-2.0.0.tgz")
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/fluxcd-test-version-2.0.0.tgz")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
case strings.Contains(req.URL.Path, "vela-workflow-v0.3.1.tgz"):
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/vela-workflow-v0.3.1.tgz")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
case strings.Contains(req.URL.Path, "foo-v1.0.0.tgz"):
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/foo-v1.0.0.tgz")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
case strings.Contains(req.URL.Path, "bar-v1.0.0.tgz"):
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/bar-v1.0.0.tgz")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
case strings.Contains(req.URL.Path, "bar-v2.0.0.tgz"):
file, err := os.ReadFile("./e2e/addon/mock/testrepo/helm-repo/bar-v2.0.0.tgz")
if err != nil {
_, _ = rw.Write([]byte(err.Error()))
}
rw.Write(file)
}
}
func init() {

View File

@@ -47,6 +47,9 @@ var (
appbasicJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
appbasicAddTraitJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}],"scaler":{"replicas":2}}}}`
velaQL = "test-component-pod-view{appNs=default,appName=nginx-vela,name=nginx}"
waitAppfileToSuccess = `{"name":"app-wait-success","services":{"app-basic1":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
waitAppfileToFail = `{"name":"app-wait-fail","services":{"app-basic2":{"type":"webservice","image":"nginx:fail","ports":[{port: 80, expose: true}]}}}`
)
var _ = ginkgo.Describe("Test Vela Application", func() {
@@ -75,6 +78,9 @@ var _ = ginkgo.Describe("Test Vela Application", func() {
e2e.JsonAppFileContext("json appfile apply", testDeleteJsonAppFile)
VelaQLPodListContext("ql", velaQL)
e2e.JsonAppFileContextWithWait("json appfile apply with wait", waitAppfileToSuccess)
e2e.JsonAppFileContextWithTimeout("json appfile apply with wait but timeout", waitAppfileToFail, "3s")
})
var ApplicationStatusContext = func(context string, applicationName string, workloadType string) bool {
@@ -182,7 +188,7 @@ var ApplicationInitIntercativeCliContext = func(context string, appName string,
c.ExpectEOF()
})
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("Checking Status"))
gomega.Expect(output).To(gomega.ContainSubstring("Waiting app to be healthy"))
})
})
}

View File

@@ -84,6 +84,30 @@ var (
})
}
JsonAppFileContextWithWait = func(context, jsonAppFile string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("Start the application through the app file in JSON format.", func() {
writeStatus := os.WriteFile("vela.json", []byte(jsonAppFile), 0644)
gomega.Expect(writeStatus).NotTo(gomega.HaveOccurred())
output, err := Exec("vela up -f vela.json --wait")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("Application Deployed Successfully!"))
})
})
}
JsonAppFileContextWithTimeout = func(context, jsonAppFile, duration string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("Start the application through the app file in JSON format.", func() {
writeStatus := os.WriteFile("vela.json", []byte(jsonAppFile), 0644)
gomega.Expect(writeStatus).NotTo(gomega.HaveOccurred())
output, err := Exec("vela up -f vela.json --wait --timeout=" + duration)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("Timeout waiting Application to be healthy!"))
})
})
}
DeleteEnvFunc = func(context string, envName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should print env does not exist message", func() {

20
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/oam-dev/kubevela
go 1.19
require (
cuelang.org/go v0.4.4-0.20220915174651-ad253ed099e9
cuelang.org/go v0.5.0-alpha.1
github.com/AlecAivazis/survey/v2 v2.1.1
github.com/FogDong/uitable v0.0.5
github.com/Masterminds/semver/v3 v3.1.1
@@ -50,16 +50,18 @@ require (
github.com/gosuri/uilive v0.0.4
github.com/gosuri/uitable v0.0.4
github.com/hashicorp/go-version v1.3.0
github.com/hashicorp/golang-lru v0.5.4
github.com/hashicorp/hcl/v2 v2.9.1
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/imdario/mergo v0.3.12
github.com/klauspost/compress v1.15.9
github.com/klauspost/compress v1.15.11
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/kubevela/pkg v0.0.0-20221024115939-a103acee6db2
github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f
github.com/kubevela/workflow v0.0.0-20221019093241-b5b7a0d79051
github.com/kubevela/workflow v0.3.3
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/oam-dev/cluster-gateway v1.4.0
github.com/oam-dev/cluster-register v1.0.4-0.20220928064144-5f76a9d7ca8c
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
@@ -77,7 +79,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.7.1
github.com/tidwall/gjson v1.9.3
github.com/wercker/stern v0.0.0-20190705090245-4fa46dd6987f
github.com/wonderflow/cert-manager-api v1.0.4-0.20210304051430-e08aa76f6c5f
@@ -85,7 +87,7 @@ require (
github.com/xlab/treeprint v1.1.0
go.mongodb.org/mongo-driver v1.5.1
go.uber.org/zap v1.21.0
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/text v0.3.8
@@ -239,7 +241,6 @@ require (
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
@@ -292,12 +293,12 @@ require (
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9 // indirect
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.48.0 // indirect
@@ -341,6 +342,7 @@ require (
)
replace (
cuelang.org/go => github.com/kubevela/cue v0.4.4-0.20221107123854-a976b0e340be
github.com/docker/cli => github.com/docker/cli v20.10.9+incompatible
github.com/docker/docker => github.com/moby/moby v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible
github.com/wercker/stern => github.com/oam-dev/stern v1.13.2

30
go.sum
View File

@@ -73,8 +73,6 @@ cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
cuelang.org/go v0.4.4-0.20220915174651-ad253ed099e9 h1:4mfDNgtdb398g0bekqiW8J8tw+JN3/U/3wh+Jw/I4Yk=
cuelang.org/go v0.4.4-0.20220915174651-ad253ed099e9/go.mod h1:nxWFAPWKYvZJ+eYayxArWqKKjdBTeU1N52vJpML/c6w=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AlecAivazis/survey/v2 v2.1.1 h1:LEMbHE0pLj75faaVEKClEX1TM4AJmmnOh9eimREzLWI=
github.com/AlecAivazis/survey/v2 v2.1.1/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
@@ -1182,6 +1180,7 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@@ -1304,8 +1303,8 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@@ -1330,12 +1329,14 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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/cue v0.4.4-0.20221107123854-a976b0e340be h1:0xj/Rh4yVy54mUD2nLmAuN1AYgBkkHxBh4PoLGbIg5g=
github.com/kubevela/cue v0.4.4-0.20221107123854-a976b0e340be/go.mod h1:Ya12qn7FZc+LSN0qgEhzEpnzQsvnGHVgoDrqe9i3eNg=
github.com/kubevela/pkg v0.0.0-20221024115939-a103acee6db2 h1:C3cAfrxst1+dIWgLLhUQt1TQvEEpp1UTq9ZQB2xKbeI=
github.com/kubevela/pkg v0.0.0-20221024115939-a103acee6db2/go.mod h1:TgIGEB/r0NOy63Jzem7WsL3AIr34l+ClH9dmPqcZ4d4=
github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f h1:1lUtU1alPThdcsn4MI6XjPb7eJLuZPpmlEdgjtnUMKw=
github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f/go.mod h1:m724/7ANnB/iukyHW20+DicpeJMEC/JA0ZhgsHY10MA=
github.com/kubevela/workflow v0.0.0-20221019093241-b5b7a0d79051 h1:ET01t1GCjbERb+uwgGZnLHoLo4ceE1+gHnmgM/9or5g=
github.com/kubevela/workflow v0.0.0-20221019093241-b5b7a0d79051/go.mod h1:1XyGmfIkD6gPAegUkeDBXXModeiu8NVUWIgersTqwr8=
github.com/kubevela/workflow v0.3.3 h1:NSbQGcABWJIzUV5wfWFJsrO/ffZ4mCVfofUtUHCTojQ=
github.com/kubevela/workflow v0.3.3/go.mod h1:5jfZ8T1m/En44wDGRf2YqCSlODfEnAV+9PnzoLoDlFs=
github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U=
github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4=
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
@@ -1923,8 +1924,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -2137,8 +2139,9 @@ go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -2198,8 +2201,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A=
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -2517,8 +2520,8 @@ golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -2550,8 +2553,9 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -2209,10 +2209,11 @@ spec:
execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
description: SubSteps is the mode of workflow sub
steps execution
type: string
type: object
ref:
@@ -4008,6 +4009,17 @@ spec:
namespace:
type: string
type: object
mode:
description: WorkflowExecuteMode defines the mode of workflow
execution
properties:
steps:
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow

View File

@@ -1021,10 +1021,10 @@ spec:
execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
ref:

View File

@@ -1,10 +1,9 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
controller-gen.kubebuilder.io/version: v0.9.0
name: workflows.core.oam.dev
spec:
group: core.oam.dev
@@ -34,6 +33,16 @@ spec:
type: string
metadata:
type: object
mode:
description: WorkflowExecuteMode defines the mode of workflow execution
properties:
steps:
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
@@ -161,297 +170,3 @@ spec:
type: object
served: true
storage: true
- name: v1alpha1
schema:
openAPIV3Schema:
description: Workflow is the Schema for the workflow API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
subSteps:
items:
description: WorkflowStepBase defines the workflow step base
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
type: object
served: true
storage: false
- name: v1beta1
schema:
openAPIV3Schema:
description: Workflow defines workflow steps and other attributes
properties:
mode:
description: WorkflowExecuteMode defines the mode of workflow execution
properties:
steps:
description: WorkflowMode describes the mode of workflow
type: string
subSteps:
description: WorkflowMode describes the mode of workflow
type: string
type: object
ref:
type: string
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
subSteps:
items:
description: WorkflowStepBase defines the workflow step base
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
type: object
served: true
storage: false
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -6,8 +6,8 @@ e2e-setup-core-pre-hook:
e2e-setup-core-post-hook:
kubectl wait --for=condition=Available deployment/kubevela-vela-core -n vela-system --timeout=180s
helm install kruise https://github.com/openkruise/charts/releases/download/kruise-1.1.0/kruise-1.1.0.tgz --set featureGates="PreDownloadImageForInPlaceUpdate=true" --set daemon.socketLocation=/run/k3s/containerd/
kill -9 $(lsof -it:9098) || true
go run ./e2e/addon/mock &
sleep 15
bin/vela addon enable ./e2e/addon/mock/testdata/fluxcd
bin/vela addon enable ./e2e/addon/mock/testdata/rollout
bin/vela addon enable ./e2e/addon/mock/testdata/terraform
@@ -82,14 +82,9 @@ e2e-api-test:
ginkgo -v -skipPackage capability,setup,application -r e2e
ginkgo -v -r e2e/application
ADDONSERVER = $(shell pgrep vela_addon_mock_server)
.PHONY: e2e-apiserver-test
e2e-apiserver-test:
pkill vela_addon_mock_server || true
go run ./e2e/addon/mock/vela_addon_mock_server.go &
sleep 15
go test -v -coverpkg=./... -coverprofile=/tmp/e2e_apiserver_test.out ./test/e2e-apiserver-test
@$(OK) tests pass

View File

@@ -612,7 +612,7 @@ func unmarshalToContent(content []byte) (fileContent *github.RepositoryContent,
}
func genAddonAPISchema(addonRes *UIData) error {
cueScript := script.CUE([]byte(addonRes.Parameters))
cueScript := script.CUE(addonRes.Parameters)
schema, err := cueScript.ParsePropertiesToSchema()
if err != nil {
return err
@@ -1043,7 +1043,7 @@ func (h *Installer) installDependency(addon *InstallPackage) error {
continue
}
// always install addon's latest version
depAddon, err := h.loadInstallPackage(dep.Name, "")
depAddon, err := h.loadInstallPackage(dep.Name, dep.Version)
if err != nil {
return err
}

View File

@@ -105,7 +105,8 @@ type DeployTo struct {
// Dependency defines the other addons it depends on
type Dependency struct {
Name string `json:"name,omitempty"`
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
// ElementFile can be addon's definition or addon's component

View File

@@ -23,6 +23,7 @@ import (
"sort"
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/repo"
@@ -146,7 +147,7 @@ func (i versionedRegistry) loadAddon(ctx context.Context, name, version string)
sort.Sort(sort.Reverse(versions))
addonVersion, availableVersions := chooseVersion(version, versions)
if addonVersion == nil {
return nil, fmt.Errorf("specified version %s not exist", version)
return nil, errors.Errorf("specified version %s not exist", utils.Sanitize(version))
}
for _, chartURL := range addonVersion.URLs {
if !utils.IsValidURL(chartURL) {

View File

@@ -247,6 +247,9 @@ var RevisionStatusTerminated = "terminated"
// RevisionStatusRollback event status rollback
var RevisionStatusRollback = "rollback"
// WorkflowStepPhaseStopped is the stopped phase
var WorkflowStepPhaseStopped workflowv1alpha1.WorkflowStepPhase = "stopped"
// ApplicationRevision be created when an application initiates deployment and describes the phased version of the application.
type ApplicationRevision struct {
BaseModel

View File

@@ -16,10 +16,60 @@ limitations under the License.
package model
import "fmt"
import (
"fmt"
"github.com/kubevela/workflow/api/v1alpha1"
)
func init() {
RegisterModel(&PipelineContext{})
RegisterModel(&Pipeline{})
}
// Structs copied from workflow/api/v1alpha1/types.go
// WorkflowSpec defines workflow steps and other attributes
type WorkflowSpec struct {
Mode *v1alpha1.WorkflowExecuteMode `json:"mode,omitempty"`
Steps []WorkflowStep `json:"steps,omitempty"`
}
// Pipeline is the model of pipeline
type Pipeline struct {
BaseModel
Spec WorkflowSpec
Name string `json:"name"`
Project string `json:"project"`
Alias string `json:"alias"`
Description string `json:"description"`
}
// PrimaryKey return custom primary key
func (p Pipeline) PrimaryKey() string {
return fmt.Sprintf("%s-%s", p.Project, p.Name)
}
// TableName return custom table name
func (p Pipeline) TableName() string {
return tableNamePrefix + "pipeline"
}
// ShortTableName is the compressed version of table name for kubeapi storage and others
func (p Pipeline) ShortTableName() string {
return "pipeline"
}
// Index return custom index
func (p Pipeline) Index() map[string]string {
var index = make(map[string]string)
if p.Project != "" {
index["project"] = p.Project
}
if p.Name != "" {
index["name"] = p.Name
}
return index
}
// Value is a k-v pair

View File

@@ -16,8 +16,6 @@ limitations under the License.
package model
import "fmt"
func init() {
RegisterModel(&Project{})
}
@@ -29,11 +27,15 @@ type Project struct {
Alias string `json:"alias"`
Owner string `json:"owner"`
Description string `json:"description,omitempty"`
Namespace string `json:"namespace"`
}
// GetNamespace get the namespace name of this project.
func (p *Project) GetNamespace() string {
return fmt.Sprintf("project-%s", p.Name)
if p.Namespace != "" {
return p.Namespace
}
return p.Name
}
// TableName return custom table name

View File

@@ -50,16 +50,25 @@ type Workflow struct {
// WorkflowStep defines how to execute a workflow step.
type WorkflowStep struct {
WorkflowStepBase `json:",inline"`
SubSteps []WorkflowStepBase `json:"subSteps,omitempty"`
}
// WorkflowStepBase is the step base of workflow
type WorkflowStepBase struct {
// Name is the unique name of the workflow step.
Name string `json:"name"`
Alias string `json:"alias"`
Type string `json:"type"`
Description string `json:"description"`
OrderIndex int `json:"orderIndex"`
Inputs workflowv1alpha1.StepInputs `json:"inputs,omitempty"`
Outputs workflowv1alpha1.StepOutputs `json:"outputs,omitempty"`
DependsOn []string `json:"dependsOn"`
Properties *JSONStruct `json:"properties,omitempty"`
Name string `json:"name"`
Alias string `json:"alias"`
Type string `json:"type"`
Description string `json:"description"`
OrderIndex int `json:"orderIndex"`
Inputs workflowv1alpha1.StepInputs `json:"inputs,omitempty"`
Outputs workflowv1alpha1.StepOutputs `json:"outputs,omitempty"`
DependsOn []string `json:"dependsOn"`
Properties *JSONStruct `json:"properties,omitempty"`
Meta *workflowv1alpha1.WorkflowStepMeta `json:"meta,omitempty"`
If string `json:"if,omitempty"`
Timeout string `json:"timeout,omitempty"`
}
// TableName return custom table name
@@ -114,6 +123,12 @@ type WorkflowRecord struct {
// WorkflowStepStatus is the workflow step status database model
type WorkflowStepStatus struct {
StepStatus `json:",inline"`
SubStepsStatus []StepStatus `json:"subSteps,omitempty"`
}
// StepStatus is the workflow step status database model
type StepStatus struct {
ID string `json:"id"`
Name string `json:"name"`
Alias string `json:"alias"`

View File

@@ -24,6 +24,7 @@ import (
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/log"
"github.com/oam-dev/kubevela/pkg/utils"
)
// ListApplicationPolicies query the application policies
@@ -83,7 +84,7 @@ func ListApplicationCommonPolicies(ctx context.Context, store datastore.DataStor
// DeleteApplicationEnvPolicies delete the policies via app name and env name
func DeleteApplicationEnvPolicies(ctx context.Context, store datastore.DataStore, app *model.Application, envName string) error {
log.Logger.Debugf("clear the policies via app name %s and env name %s", app.PrimaryKey(), envName)
log.Logger.Debugf("clear the policies via app name %s and env name %s", app.PrimaryKey(), utils.Sanitize(envName))
policies, err := ListApplicationEnvPolicies(ctx, store, app, envName)
if err != nil {
return err

View File

@@ -32,6 +32,7 @@ import (
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
"github.com/oam-dev/kubevela/pkg/apiserver/event/sync/convert"
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
@@ -599,25 +600,20 @@ func GenEnvWorkflowStepsAndPolicies(ctx context.Context, kubeClient client.Clien
}
var steps []model.WorkflowStep
for _, step := range workflowSteps {
base, err := convert.FromCRWorkflowStepBase(step.WorkflowStepBase)
if err != nil {
log.Logger.Errorf("workflow %s step %s properties is invalid %s", pkgUtils.Sanitize(app.Name), pkgUtils.Sanitize(step.Name), err.Error())
continue
}
targetName := strings.Replace(step.Name, "-cloud-resource", "", 1)
s := model.WorkflowStep{
Name: step.Name,
Type: step.Type,
Alias: fmt.Sprintf("Deploy To %s", targetName),
Description: fmt.Sprintf("deploy app to delivery target %s", targetName),
DependsOn: step.DependsOn,
Inputs: step.Inputs,
Outputs: step.Outputs,
base.Alias = fmt.Sprintf("Deploy To %s", targetName)
base.Description = fmt.Sprintf("deploy app to delivery target %s", targetName)
ws := model.WorkflowStep{
WorkflowStepBase: *base,
SubSteps: make([]model.WorkflowStepBase, 0),
}
if step.Properties != nil {
properties, err := model.NewJSONStruct(step.Properties)
if err != nil {
log.Logger.Errorf("workflow %s step %s properties is invalid %s", pkgUtils.Sanitize(app.Name), pkgUtils.Sanitize(step.Name), err.Error())
continue
}
s.Properties = properties
}
steps = append(steps, s)
// no sub steps handle here
steps = append(steps, ws)
}
return steps, policies
}

View File

@@ -40,54 +40,70 @@ import (
func TestCompareWorkflowSteps(t *testing.T) {
existSteps := []model.WorkflowStep{
{
Name: "step1",
Type: "deploy2env",
Properties: &model.JSONStruct{
"policy": "env-policy",
"env": "target1",
WorkflowStepBase: model.WorkflowStepBase{
Name: "step1",
Type: "deploy2env",
Properties: &model.JSONStruct{
"policy": "env-policy",
"env": "target1",
},
},
},
{
Name: "suspend",
Type: "suspend",
},
{
Name: "step2",
Type: "deploy2env",
Properties: &model.JSONStruct{
"policy": "env-policy",
"env": "target2",
WorkflowStepBase: model.WorkflowStepBase{
Name: "suspend",
Type: "suspend",
},
},
{
Name: "step3",
Type: "deploy2env",
Properties: &model.JSONStruct{
"policy": "env-policy",
"env": "target3",
WorkflowStepBase: model.WorkflowStepBase{
Name: "step2",
Type: "deploy2env",
Properties: &model.JSONStruct{
"policy": "env-policy",
"env": "target2",
},
},
},
{
Name: "notify",
Type: "notify",
Properties: &model.JSONStruct{"message": "dddd"},
WorkflowStepBase: model.WorkflowStepBase{
Name: "step3",
Type: "deploy2env",
Properties: &model.JSONStruct{
"policy": "env-policy",
"env": "target3",
},
},
},
{
WorkflowStepBase: model.WorkflowStepBase{
Name: "notify",
Type: "notify",
Properties: &model.JSONStruct{"message": "dddd"},
},
},
}
newSteps := []model.WorkflowStep{
{
Name: "step1",
Type: "deploy",
Properties: &model.JSONStruct{"policies": []string{"target1"}},
WorkflowStepBase: model.WorkflowStepBase{
Name: "step1",
Type: "deploy",
Properties: &model.JSONStruct{"policies": []string{"target1"}},
},
},
{
Name: "step2",
Type: "deploy",
Properties: &model.JSONStruct{"policies": []string{"target2"}},
WorkflowStepBase: model.WorkflowStepBase{
Name: "step2",
Type: "deploy",
Properties: &model.JSONStruct{"policies": []string{"target2"}},
},
},
{
Name: "step4",
Type: "deploy",
Properties: &model.JSONStruct{"policies": []string{"target4"}},
WorkflowStepBase: model.WorkflowStepBase{
Name: "step4",
Type: "deploy",
Properties: &model.JSONStruct{"policies": []string{"target4"}},
},
},
}
exist := createWorkflowSteps(existSteps, []datastore.Entity{
@@ -368,11 +384,15 @@ var _ = Describe("Test workflow model", func() {
workflow.Steps = []model.WorkflowStep{
workflow.Steps[0], {
Type: "suspend",
Name: "suspend",
WorkflowStepBase: model.WorkflowStepBase{
Type: "suspend",
Name: "suspend",
},
}, workflow.Steps[1], {
Type: "notification",
Name: "notification",
WorkflowStepBase: model.WorkflowStepBase{
Type: "notification",
Name: "notification",
},
},
}

View File

@@ -412,14 +412,12 @@ func (u *addonServiceImpl) EnableAddon(ctx context.Context, name string, args ap
continue
}
if strings.Contains(err.Error(), "specified version") {
berr := bcode.ErrAddonInvalidVersion
berr.Message = err.Error()
return berr
return bcode.ErrAddonInvalidVersion.SetMessage(err.Error())
}
// wrap this error with special bcode
if errors.As(err, &pkgaddon.VersionUnMatchError{}) {
return bcode.ErrAddonSystemVersionMismatch
return bcode.ErrAddonSystemVersionMismatch.SetMessage(err.Error())
}
// except `addon not found`, other errors should return directly
return err

View File

@@ -533,7 +533,7 @@ var _ = Describe("Test application service function", func() {
Expect(cmp.Diff(compareResponse.TargetAppYAML, "")).Should(BeEmpty())
Expect(cmp.Diff(compareResponse.BaseAppYAML, "")).ShouldNot(BeEmpty())
By("compare when app's env add target, should return true")
By("compare when app's env add target, should return false")
_, err = targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{Name: "dev-target1", Project: appModel.Project, Cluster: &v1.ClusterTarget{ClusterName: "local", Namespace: "dev-target1"}})
Expect(err).Should(BeNil())
_, err = envService.UpdateEnv(context.TODO(), "app-dev",
@@ -548,7 +548,8 @@ var _ = Describe("Test application service function", func() {
},
})
Expect(err).Should(BeNil())
check(compareResponse, true)
// Existing applications are not affected after update env.
check(compareResponse, false)
By("compare when update app's trait, should return true")
// reset app config
@@ -846,19 +847,25 @@ var _ = Describe("Test apiserver policy rest api", func() {
EnvName: "default",
Steps: []v1.WorkflowStep{
{
Name: "default",
Type: "deploy",
Properties: `{"policies":["local"]}`,
WorkflowStepBase: v1.WorkflowStepBase{
Name: "default",
Type: "deploy",
Properties: `{"policies":["local"]}`,
},
},
{
Name: "suspend",
Type: "suspend",
Properties: `{"duration": "10m"}`,
WorkflowStepBase: v1.WorkflowStepBase{
Name: "suspend",
Type: "suspend",
Properties: `{"duration": "10m"}`,
},
},
{
Name: "second",
Type: "deploy",
Properties: `{"policies":["cluster1"]}`,
WorkflowStepBase: v1.WorkflowStepBase{
Name: "second",
Type: "deploy",
Properties: `{"policies":["cluster1"]}`,
},
},
},
}
@@ -870,9 +877,11 @@ var _ = Describe("Test apiserver policy rest api", func() {
EnvName: "default",
Steps: []v1.WorkflowStep{
{
Name: "second",
Type: "deploy",
Properties: `{"policies":["cluster3"]}`,
WorkflowStepBase: v1.WorkflowStepBase{
Name: "second",
Type: "deploy",
Properties: `{"policies":["cluster3"]}`,
},
},
},
}

View File

@@ -231,6 +231,7 @@ func (c *cloudShellServiceImpl) prepareKubeConfig(ctx context.Context) error {
var groups []string
for _, p := range projects {
permissions, err := c.RBACService.GetUserPermissions(ctx, user, p.Name, false)
// The kubernetes permission set is generated based on simple rules, but this is not completely strict.
var readOnly bool
if err != nil {
log.Logger.Errorf("failed to get the user permissions %s", err.Error())
@@ -239,7 +240,7 @@ func (c *cloudShellServiceImpl) prepareKubeConfig(ctx context.Context) error {
readOnly = checkReadOnly(p.Name, permissions)
}
if readOnly {
groupName, err := c.managePrivilegesForProjectRead(ctx, p.Name, true)
groupName, err := c.managePrivilegesForProject(ctx, p, true)
if err != nil {
log.Logger.Errorf("failed to privileges the user %s", err.Error())
}
@@ -247,9 +248,16 @@ func (c *cloudShellServiceImpl) prepareKubeConfig(ctx context.Context) error {
groups = append(groups, groupName)
}
} else {
groups = append(groups, utils.KubeVelaProjectGroupPrefix+p.Name)
groupName, err := c.managePrivilegesForProject(ctx, p, false)
if err != nil {
log.Logger.Errorf("failed to privileges the user %s", err.Error())
}
if groupName != "" {
groups = append(groups, groupName)
}
}
}
groups = append(groups, utils.TemplateReaderGroup)
if utils.StringsContain(user.UserRoles, "admin") {
groups = append(groups, utils.KubeVelaAdminGroupPrefix+"admin")
@@ -375,8 +383,9 @@ func checkReadOnly(projectName string, permissions []*model.Permission) bool {
return !ra.Match(permissions)
}
// managePrivilegesForProjectRead grant the read privileges for a project
func (c *cloudShellServiceImpl) managePrivilegesForProjectRead(ctx context.Context, projectName string, readOnly bool) (string, error) {
// managePrivilegesForProject grant the privileges for a project
func (c *cloudShellServiceImpl) managePrivilegesForProject(ctx context.Context, project *apisv1.ProjectBase, readOnly bool) (string, error) {
projectName := project.Name
targets, err := c.TargetService.ListTargets(ctx, 0, 0, projectName)
if err != nil {
log.Logger.Infof("failed to list the targets by the project name %s :%s", projectName, err.Error())
@@ -392,7 +401,14 @@ func (c *cloudShellServiceImpl) managePrivilegesForProjectRead(ctx context.Conte
for _, e := range envs.Envs {
authPDs = append(authPDs, &auth.ApplicationPrivilege{Cluster: kubevelatypes.ClusterLocalName, Namespace: e.Namespace, ReadOnly: readOnly})
}
// The namespace of the environment: Application and WorkflowRun
authPDs = append(authPDs, &auth.ApplicationPrivilege{Cluster: kubevelatypes.ClusterLocalName, Namespace: project.Namespace, ReadOnly: readOnly})
groupName := utils.KubeVelaProjectReadGroupPrefix + projectName
if !readOnly {
groupName = utils.KubeVelaProjectGroupPrefix + projectName
}
identity := &auth.Identity{Groups: []string{groupName}}
writer := &bytes.Buffer{}
if err := auth.GrantPrivileges(ctx, c.KubeClient, authPDs, identity, writer, auth.WithReplace); err != nil {

View File

@@ -48,6 +48,7 @@ var _ = Describe("Test cloudshell service function", func() {
cloudShellService *cloudShellServiceImpl
userService *userServiceImpl
projectService *projectServiceImpl
envService *envServiceImpl
err error
database string
)
@@ -56,7 +57,7 @@ var _ = Describe("Test cloudshell service function", func() {
database = "cloudshell-test-kubevela"
ds, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: database})
Expect(err).Should(Succeed())
envService := &envServiceImpl{
envService = &envServiceImpl{
Store: ds,
KubeClient: k8sClient,
}
@@ -66,7 +67,8 @@ var _ = Describe("Test cloudshell service function", func() {
ProjectService: projectService,
}
projectService = &projectServiceImpl{
Store: ds,
Store: ds,
K8sClient: k8sClient,
RbacService: &rbacServiceImpl{
Store: ds,
},
@@ -99,14 +101,13 @@ var _ = Describe("Test cloudshell service function", func() {
}
})
It("test prepareKubeConfig", func() {
It("Test prepareKubeConfig", func() {
err = userService.Init(context.TODO())
Expect(err).Should(BeNil())
err = projectService.Init(context.TODO())
Expect(err).Should(BeNil())
By("test the developer users")
_, err = userService.CreateUser(context.TODO(), apisv1.CreateUserRequest{Name: "test-dev", Password: "test"})
Expect(err).Should(BeNil())
@@ -170,17 +171,37 @@ var _ = Describe("Test cloudshell service function", func() {
err = cloudShellService.prepareKubeConfig(ctx)
Expect(err).Should(BeNil())
var cm corev1.ConfigMap
err = k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: kubevelatypes.DefaultKubeVelaNS, Name: makeUserConfigName("admin-test")}, &cm)
checkConfig := func() {
var cm corev1.ConfigMap
err = k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: kubevelatypes.DefaultKubeVelaNS, Name: makeUserConfigName("admin-test")}, &cm)
Expect(err).Should(BeNil())
Expect(len(cm.Data["identity"]) > 0).Should(BeTrue())
var identity auth.Identity
err = yaml.Unmarshal([]byte(cm.Data["identity"]), &identity)
Expect(err).Should(BeNil())
Expect(utils.StringsContain(identity.Groups, utils.KubeVelaAdminGroupPrefix+"admin")).Should(BeTrue())
Expect(utils.StringsContain(identity.Groups, utils.TemplateReaderGroup)).Should(BeTrue())
}
checkConfig()
By("Test other projects")
_, err = projectService.CreateProject(ctx, apisv1.CreateProjectRequest{Name: "cloudshell"})
Expect(err).Should(BeNil())
Expect(len(cm.Data["identity"]) > 0).Should(BeTrue())
var identity auth.Identity
err = yaml.Unmarshal([]byte(cm.Data["identity"]), &identity)
_, err = envService.CreateEnv(ctx, apisv1.CreateEnvRequest{Name: "cloudshell-env", Project: "cloudshell"})
Expect(err).Should(BeNil())
Expect(utils.StringsContain(identity.Groups, utils.KubeVelaAdminGroupPrefix+"admin")).Should(BeTrue())
err = cloudShellService.prepareKubeConfig(ctx)
Expect(err).Should(BeNil())
err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "kubevela:writer:application:binding", Namespace: "cloudshell-env"}, &rb)
Expect(err).Should(BeNil())
Expect(rb.Subjects[0].Name).Should(Equal(utils.KubeVelaProjectGroupPrefix + "cloudshell"))
checkConfig()
})
It("test prepare", func() {
It("Test prepare", func() {
By("Test with not CRD")
_, err = userService.CreateUser(context.TODO(), apisv1.CreateUserRequest{Name: "test", Password: "test"})
Expect(err).Should(BeNil())

View File

@@ -69,6 +69,7 @@ type DefinitionQueryOption struct {
AppliedWorkloads string `json:"appliedWorkloads"`
OwnerAddon string `json:"sourceAddon"`
QueryAll bool `json:"queryAll"`
Scope string `json:"scope"`
}
// String return cache key string
@@ -109,6 +110,19 @@ func (d *definitionServiceImpl) listDefinitions(ctx context.Context, list *unstr
},
},
}
if ops.Scope != "" {
var filterScope string
if ops.Scope == "Application" {
filterScope = "WorkflowRun"
} else {
filterScope = "Application"
}
matchLabels.MatchExpressions = append(matchLabels.MatchExpressions, metav1.LabelSelectorRequirement{
Key: types.LabelDefinitionScope,
Operator: metav1.LabelSelectorOpNotIn,
Values: []string{filterScope},
})
}
if !ops.QueryAll {
matchLabels.MatchExpressions = append(matchLabels.MatchExpressions, metav1.LabelSelectorRequirement{
Key: types.LabelDefinitionHidden,

View File

@@ -112,6 +112,11 @@ var _ = Describe("Test namespace service functions", func() {
Expect(wfstep[0].WorkflowStep.Schematic).ShouldNot(BeNil())
Expect(wfstep[0].Alias).Should(Equal("test-alias"))
wfstep, err = definitionService.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep", Scope: "WorkflowRun"})
Expect(err).Should(BeNil())
// the definition should be filtered
Expect(cmp.Diff(len(wfstep), 1)).Should(BeEmpty())
step, err = ioutil.ReadFile("./testdata/apply-application-hide.yaml")
Expect(err).Should(Succeed())
var sd2 v1beta1.WorkflowStepDefinition

View File

@@ -26,6 +26,7 @@ import (
apierror "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/repository"
@@ -184,23 +185,6 @@ func checkEqual(old, new []string) bool {
return reflect.DeepEqual(old, new)
}
func (p *envServiceImpl) updateAppWithNewEnv(ctx context.Context, envName string, env *model.Env) error {
// List all apps inside the env
apps, err := listApp(ctx, p.Store, apisv1.ListApplicationOptions{Env: envName})
if err != nil {
return err
}
for _, app := range apps {
err = repository.UpdateEnvWorkflow(ctx, p.KubeClient, p.Store, app, env)
if err != nil {
return err
}
}
return nil
}
// UpdateEnv update an env for request
func (p *envServiceImpl) UpdateEnv(ctx context.Context, name string, req apisv1.UpdateEnvRequest) (*apisv1.Env, error) {
env := &model.Env{}
@@ -221,25 +205,33 @@ func (p *envServiceImpl) UpdateEnv(ctx context.Context, name string, req apisv1.
if err != nil || !pass {
return nil, bcode.ErrEnvTargetConflict
}
var targetChanged bool
if len(req.Targets) > 0 && !checkEqual(env.Targets, req.Targets) {
targetChanged = true
env.Targets = req.Targets
}
targets, err := repository.ListTarget(ctx, p.Store, "", nil)
if err != nil {
return nil, err
}
var targetMap = make(map[string]*model.Target, len(targets))
for i, existTarget := range targets {
targetMap[existTarget.Name] = targets[i]
}
for _, target := range req.Targets {
if _, exist := targetMap[target]; !exist {
var targets []*model.Target
if len(req.Targets) > 0 {
_, _, deleted := util.ThreeWaySliceCompare(req.Targets, env.Targets)
if len(deleted) > 0 {
count, err := p.GetAppCountInEnv(ctx, env)
if err != nil {
return nil, err
}
if count > 0 {
return nil, bcode.ErrEnvTargetNotAllowDelete
}
}
targets, err = repository.ListTarget(ctx, p.Store, "", &datastore.ListOptions{
FilterOptions: datastore.FilterOptions{
In: []datastore.InQueryOption{{
Key: "name",
Values: req.Targets,
}},
},
})
if err != nil {
return nil, err
}
if len(targets) != len(req.Targets) {
return nil, bcode.ErrTargetNotExist
}
env.Targets = req.Targets
}
// create namespace at first
@@ -247,13 +239,6 @@ func (p *envServiceImpl) UpdateEnv(ctx context.Context, name string, req apisv1.
return nil, err
}
if targetChanged {
if err = p.updateAppWithNewEnv(ctx, name, env); err != nil {
log.Logger.Errorf("update envbinding failure %s", err.Error())
return nil, err
}
}
if err := managePrivilegesForEnvironment(ctx, p.KubeClient, env, false); err != nil {
return nil, err
}
@@ -262,6 +247,14 @@ func (p *envServiceImpl) UpdateEnv(ctx context.Context, name string, req apisv1.
return resp, nil
}
func (p *envServiceImpl) GetAppCountInEnv(ctx context.Context, env *model.Env) (int, error) {
var appList v1beta1.ApplicationList
if err := p.KubeClient.List(ctx, &appList, client.InNamespace(env.Namespace), client.MatchingLabels{model.LabelSourceOfTruth: model.FromUX}); err != nil {
return 0, err
}
return len(appList.Items), nil
}
// CreateEnv create an env for request
func (p *envServiceImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequest) (*apisv1.Env, error) {
newEnv := &model.Env{
@@ -344,14 +337,23 @@ func convertEnvModel2Base(env *model.Env, targets []*model.Target) *apisv1.Env {
UpdateTime: env.UpdateTime,
}
for _, dt := range env.Targets {
var t *model.Target
for _, tg := range targets {
if dt == tg.Name {
data.Targets = append(data.Targets, apisv1.NameAlias{
Name: dt,
Alias: tg.Alias,
})
t = tg
break
}
}
if t != nil {
data.Targets = append(data.Targets, apisv1.NameAlias{
Name: dt,
Alias: t.Alias,
})
} else {
data.Targets = append(data.Targets, apisv1.NameAlias{
Name: dt,
})
}
}
return &data
}

View File

@@ -25,8 +25,11 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/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/apiserver/domain/model"
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
@@ -53,6 +56,8 @@ var _ = Describe("Test env service functions", func() {
// create target
err := ds.Add(context.TODO(), &model.Target{Name: "env-test"})
Expect(err).Should(BeNil())
err = ds.Add(context.TODO(), &model.Target{Name: "env-test-2"})
Expect(err).Should(BeNil())
req := apisv1.CreateEnvRequest{
Name: "test-env",
@@ -113,6 +118,35 @@ var _ = Describe("Test env service functions", func() {
Expect(err).Should(BeNil())
Expect(cmp.Diff(env.Description, req5.Description)).Should(BeEmpty())
By("Test update the targets of the env")
req6 := apisv1.UpdateEnvRequest{
Description: "this is a env description update",
Targets: []string{"env-test", "env-test-2"},
}
env, err = envService.UpdateEnv(context.TODO(), "test-env-2", req6)
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(env.Targets), len(req6.Targets))).Should(BeEmpty())
Expect(k8sClient.Create(context.TODO(), &v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "env-app",
Namespace: env.Namespace,
Labels: map[string]string{
model.LabelSourceOfTruth: model.FromUX,
},
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{},
},
})).Should(BeNil())
req7 := apisv1.UpdateEnvRequest{
Description: "this is a env description update",
Targets: []string{"env-test"},
}
_, err = envService.UpdateEnv(context.TODO(), "test-env-2", req7)
Expect(err).Should(Equal(bcode.ErrEnvTargetNotAllowDelete))
// clean up the env
err = envService.DeleteEnv(context.TODO(), "test-env")
Expect(err).Should(BeNil())

View File

@@ -83,7 +83,7 @@ var _ = Describe("Test helm repo list", func() {
pSec = v1.Secret{}
gSec = v1.Secret{}
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "project-my-project"}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "my-project"}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
Expect(yaml.Unmarshal([]byte(projectSecret), &pSec)).Should(BeNil())
Expect(yaml.Unmarshal([]byte(globalSecret), &gSec)).Should(BeNil())
Expect(k8sClient.Create(ctx, &pSec)).Should(BeNil())
@@ -390,7 +390,7 @@ apiVersion: v1
kind: Secret
metadata:
name: project-helm-repo
namespace: project-my-project
namespace: my-project
labels:
config.oam.dev/type: helm-repository
config.oam.dev/catalog: velacore-config

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,142 @@
/*
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 service
import (
"context"
"github.com/kubevela/workflow/api/v1alpha1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
"github.com/oam-dev/kubevela/pkg/oam/util"
)
var (
// defaultNamespace = "project-default-ns1-test"
pipelineService *pipelineServiceImpl
pipelineRunService *pipelineRunServiceImpl
userService *userServiceImpl
contextService *contextServiceImpl
projectService *projectServiceImpl
ctx context.Context
pipelineName = "test-pipeline"
projectName = "test-project"
)
var _ = Describe("Test pipeline service functions", func() {
It("Init services and project", func() {
ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: "pipeline-test-kubevela"})
Expect(ds).ToNot(BeNil())
Expect(err).Should(BeNil())
Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
pipelineService = NewTestPipelineService(ds, k8sClient, cfg).(*pipelineServiceImpl)
pipelineRunService = pipelineService.PipelineRunService.(*pipelineRunServiceImpl)
contextService = pipelineService.ContextService.(*contextServiceImpl)
projectService = pipelineService.ProjectService.(*projectServiceImpl)
userService = &userServiceImpl{Store: ds, K8sClient: k8sClient}
ctx = context.WithValue(context.TODO(), &apisv1.CtxKeyUser, "admin")
err = userService.Init(context.TODO())
Expect(err).Should(BeNil())
_, err = projectService.CreateProject(ctx, apisv1.CreateProjectRequest{
Name: projectName,
Owner: "admin",
})
Expect(err).Should(BeNil())
projModel, err := projectService.GetProject(context.TODO(), projectName)
Expect(err).Should(BeNil())
ctx = context.WithValue(ctx, &apisv1.CtxKeyProject, projModel)
})
It("Test create pipeline", func() {
props := model.JSONStruct{
"url": "https://api.github.com/repos/kubevela/kubevela",
}
testPipelineSteps := []model.WorkflowStep{
{
SubSteps: []model.WorkflowStepBase{
{
Name: "request",
Type: "request",
Outputs: v1alpha1.StepOutputs{
{
ValueFrom: "import \"strconv\"\n\"Current star count: \" + strconv.FormatInt(response[\"stargazers_count\"], 10)\n",
Name: "stars",
},
},
Properties: &props,
},
},
WorkflowStepBase: model.WorkflowStepBase{
Name: "step-group",
Type: "step-group",
},
},
}
By("create pipeline with sub-steps")
pipeline, err := pipelineService.CreatePipeline(ctx, apisv1.CreatePipelineRequest{
Name: pipelineName,
Spec: model.WorkflowSpec{
Steps: testPipelineSteps,
},
})
Expect(err).Should(BeNil())
Expect(pipeline.Name).Should(Equal(pipelineName))
Expect(pipeline.Spec.Steps[0].Name).Should(Equal("step-group"))
})
It("list pipeline", func() {
pipelines, err := pipelineService.ListPipelines(ctx, apisv1.ListPipelineRequest{
Detailed: true,
})
Expect(err).Should(BeNil())
Expect(pipelines).ShouldNot(BeNil())
Expect(pipelines.Total).Should(Equal(1))
Expect(len(pipelines.Pipelines)).Should(Equal(1))
Expect(pipelines.Pipelines[0].Info).ShouldNot(BeNil())
})
It("get pipeline contexts", func() {
By("no context")
contexts, err := contextService.ListContexts(ctx, projectName, pipelineName)
Expect(err).Should(BeNil())
Expect(contexts.Total).Should(Equal(0))
Expect(len(contexts.Contexts)).Should(Equal(0))
By("create context")
contextName := "test-context"
contextKey := "test-key"
contextVal := "test-val"
ppCtx := apisv1.Context{
Name: contextName,
Values: []model.Value{
{
Key: contextKey,
Value: contextVal,
},
},
}
context, err := contextService.CreateContext(ctx, projectName, pipelineName, ppCtx)
Expect(err).Should(BeNil())
Expect(len(context.Contexts)).Should(Equal(1))
})
})

View File

@@ -22,6 +22,7 @@ import (
"fmt"
terraformapi "github.com/oam-dev/terraform-controller/api/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/types"
@@ -31,6 +32,7 @@ import (
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/log"
"github.com/oam-dev/kubevela/pkg/multicluster"
"github.com/oam-dev/kubevela/pkg/utils"
)
// ProjectService project manage service.
@@ -73,29 +75,19 @@ func (p *projectServiceImpl) Init(ctx context.Context) error {
// the default env and default target both using the `default` namespace in control plane cluster
func (p *projectServiceImpl) InitDefaultProjectEnvTarget(ctx context.Context, defaultNamespace string) error {
var project = model.Project{}
entities, err := p.Store.List(ctx, &project, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{
IsNotExist: []datastore.IsNotExistQueryOption{
{
Key: "owner",
},
},
}})
entities, err := p.Store.List(ctx, &project, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{}})
if err != nil {
return fmt.Errorf("initialize project failed %w", err)
}
if len(entities) > 0 {
for _, project := range entities {
pro := project.(*model.Project)
var init = pro.Owner == ""
pro.Owner = model.DefaultAdminUserName
if err := p.Store.Put(ctx, pro); err != nil {
return err
}
// owner is empty, it is old data
if init {
if err := p.RbacService.InitDefaultRoleAndUsersForProject(ctx, pro); err != nil {
return fmt.Errorf("init default role and users for project %s failure %w", pro.Name, err)
}
if err := p.RbacService.SyncDefaultRoleAndUsersForProject(ctx, pro); err != nil {
return fmt.Errorf("fail to sync the default role and users for the project %s %w", pro.Name, err)
}
}
return nil
@@ -159,6 +151,13 @@ func (p *projectServiceImpl) GetProject(ctx context.Context, projectName string)
}
return nil, err
}
if _, err := utils.GetNamespace(ctx, p.K8sClient, project.GetNamespace()); err != nil {
if apierrors.IsNotFound(err) {
if err := utils.CreateNamespace(ctx, p.K8sClient, projectName); err != nil && !apierrors.IsAlreadyExists(err) {
return nil, bcode.ErrProjectNamespaceFail
}
}
}
return project, nil
}
@@ -296,7 +295,6 @@ func (p *projectServiceImpl) DeleteProject(ctx context.Context, name string) err
// CreateProject create project
func (p *projectServiceImpl) CreateProject(ctx context.Context, req apisv1.CreateProjectRequest) (*apisv1.ProjectBase, error) {
exist, err := p.Store.IsExist(ctx, &model.Project{Name: req.Name})
if err != nil {
log.Logger.Errorf("check project name is exist failure %s", err.Error())
@@ -319,19 +317,24 @@ func (p *projectServiceImpl) CreateProject(ctx context.Context, req apisv1.Creat
}
}
if err := utils.CreateNamespace(ctx, p.K8sClient, req.Name); err != nil && !apierrors.IsAlreadyExists(err) {
return nil, bcode.ErrProjectNamespaceFail
}
newProject := &model.Project{
Name: req.Name,
Description: req.Description,
Alias: req.Alias,
Owner: owner,
Namespace: req.Name,
}
if err := p.Store.Add(ctx, newProject); err != nil {
return nil, err
}
if err := p.RbacService.InitDefaultRoleAndUsersForProject(ctx, newProject); err != nil {
log.Logger.Errorf("init default role and users for project failure %s", err.Error())
if err := p.RbacService.SyncDefaultRoleAndUsersForProject(ctx, newProject); err != nil {
log.Logger.Errorf("fail to sync the default role and users for the project: %s", err.Error())
}
return ConvertProjectModel2Base(newProject, user), nil
@@ -526,6 +529,7 @@ func ConvertProjectModel2Base(project *model.Project, owner *model.User) *apisv1
CreateTime: project.CreateTime,
UpdateTime: project.UpdateTime,
Owner: apisv1.NameAlias{Name: project.Owner},
Namespace: project.GetNamespace(),
}
if owner != nil && owner.Name == project.Owner {
base.Owner = apisv1.NameAlias{Name: owner.Name, Alias: owner.Alias}

View File

@@ -59,6 +59,7 @@ var defaultProjectPermissionTemplate = []*model.PermissionTemplate{
"project:{projectName}/permission:*",
"project:{projectName}/environment:*",
"project:{projectName}/application:*/*",
"project:{projectName}/pipeline:*/*",
},
Actions: []string{"detail", "list"},
Effect: "Allow",
@@ -89,13 +90,23 @@ var defaultProjectPermissionTemplate = []*model.PermissionTemplate{
Scope: "project",
},
{
Name: "configuration-read",
Alias: "Environment Management",
Name: "config-management",
Alias: "Config Management",
Resources: []string{"project:{projectName}/config:*", "project:{projectName}/provider:*"},
Actions: []string{"list", "detail"},
Actions: []string{"*"},
Effect: "Allow",
Scope: "project",
},
{
Name: "pipeline-management",
Alias: "Pipeline Management",
Resources: []string{
"project:{projectName}/pipeline:*",
},
Actions: []string{"*"},
Effect: "Allow",
Scope: "project",
},
}
var defaultPlatformPermission = []*model.PermissionTemplate{
@@ -234,6 +245,17 @@ var ResourceMaps = map[string]resourceMetadata{
pathName: "configName",
},
"provider": {},
"pipeline": {
pathName: "pipelineName",
subResources: map[string]resourceMetadata{
"context": {
pathName: "contextName",
},
"pipelineRun": {
pathName: "pipelineRunName",
},
},
},
},
pathName: "projectName",
},
@@ -276,7 +298,7 @@ var ResourceMaps = map[string]resourceMetadata{
"configTemplate": {},
}
var existResourcePaths = convert(ResourceMaps)
var existResourcePaths = convertSources(ResourceMaps)
type resourceMetadata struct {
subResources map[string]resourceMetadata
@@ -320,11 +342,11 @@ func checkResourcePath(resource string) (string, error) {
return path, fmt.Errorf("there is no resource %s", resource)
}
func convert(sources map[string]resourceMetadata) map[string]string {
func convertSources(sources map[string]resourceMetadata) map[string]string {
list := make(map[string]string)
for k, v := range sources {
if len(v.subResources) > 0 {
for sub, subWithPathName := range convert(v.subResources) {
for sub, subWithPathName := range convertSources(v.subResources) {
if subWithPathName != "" {
withPathname := fmt.Sprintf("/%s:*%s", k, subWithPathName)
if v.pathName != "" {
@@ -383,7 +405,7 @@ type RBACService interface {
ListPermissions(ctx context.Context, projectName string) ([]apisv1.PermissionBase, error)
CreatePermission(ctx context.Context, projectName string, req apisv1.CreatePermissionRequest) (*apisv1.PermissionBase, error)
DeletePermission(ctx context.Context, projectName, permName string) error
InitDefaultRoleAndUsersForProject(ctx context.Context, project *model.Project) error
SyncDefaultRoleAndUsersForProject(ctx context.Context, project *model.Project) error
Init(ctx context.Context) error
}
@@ -835,7 +857,17 @@ func (p *rbacServiceImpl) CreatePermission(ctx context.Context, projectName stri
return assembler.ConvertPermission2DTO(&permission), nil
}
func (p *rbacServiceImpl) InitDefaultRoleAndUsersForProject(ctx context.Context, project *model.Project) error {
func (p *rbacServiceImpl) SyncDefaultRoleAndUsersForProject(ctx context.Context, project *model.Project) error {
permissions, err := p.ListPermissions(ctx, project.Name)
if err != nil {
return err
}
var permissionMap = map[string]apisv1.PermissionBase{}
for i, per := range permissions {
permissionMap[per.Name] = permissions[i]
}
var batchData []datastore.Entity
for _, permissionTemp := range defaultProjectPermissionTemplate {
var rra = RequestResourceAction{}
@@ -849,39 +881,52 @@ func (p *rbacServiceImpl) InitDefaultRoleAndUsersForProject(ctx context.Context,
})
formattedResource = append(formattedResource, rra.GetResource().String())
}
batchData = append(batchData, &model.Permission{
permission := &model.Permission{
Name: permissionTemp.Name,
Alias: permissionTemp.Alias,
Project: project.Name,
Resources: formattedResource,
Actions: permissionTemp.Actions,
Effect: permissionTemp.Effect,
})
}
batchData = append(batchData, &model.Role{
Name: "app-developer",
Alias: "App Developer",
Permissions: []string{"project-view", "app-management", "env-management", "configuration-read"},
Project: project.Name,
}, &model.Role{
Name: "project-admin",
Alias: "Project Admin",
Permissions: []string{"project-view", "app-management", "env-management", "role-management", "configuration-read"},
Project: project.Name,
}, &model.Role{
Name: "project-viewer",
Alias: "Project Viewer",
Permissions: []string{"project-view"},
Project: project.Name,
})
if project.Owner != "" {
var projectUser = &model.ProjectUser{
ProjectName: project.Name,
UserRoles: []string{"project-admin"},
Username: project.Owner,
}
batchData = append(batchData, projectUser)
if perm, exist := permissionMap[permissionTemp.Name]; exist {
if !utils.EqualSlice(perm.Resources, permissionTemp.Resources) || utils.EqualSlice(perm.Actions, permissionTemp.Actions) {
if err := p.Store.Put(ctx, permission); err != nil {
return err
}
}
continue
}
batchData = append(batchData, permission)
}
if len(permissions) == 0 {
batchData = append(batchData, &model.Role{
Name: "app-developer",
Alias: "App Developer",
Permissions: []string{"project-view", "app-management", "env-management", "config-management", "pipeline-management"},
Project: project.Name,
}, &model.Role{
Name: "project-admin",
Alias: "Project Admin",
Permissions: []string{"project-view", "app-management", "env-management", "pipeline-management", "config-management", "role-management"},
Project: project.Name,
}, &model.Role{
Name: "project-viewer",
Alias: "Project Viewer",
Permissions: []string{"project-view"},
Project: project.Name,
})
if project.Owner != "" {
var projectUser = &model.ProjectUser{
ProjectName: project.Name,
UserRoles: []string{"project-admin"},
Username: project.Owner,
}
batchData = append(batchData, projectUser)
}
}
return p.Store.BatchAdd(ctx, batchData)
}

View File

@@ -189,7 +189,7 @@ var _ = Describe("Test rbac service", func() {
err = ds.Add(context.TODO(), &model.Project{Name: "init-test", Owner: "test-user"})
Expect(err).Should(BeNil())
err = rbacService.InitDefaultRoleAndUsersForProject(context.TODO(), &model.Project{Name: "init-test"})
err = rbacService.SyncDefaultRoleAndUsersForProject(context.TODO(), &model.Project{Name: "init-test"})
Expect(err).Should(BeNil())
roles, err := rbacService.ListRole(context.TODO(), "init-test", 0, 0)
@@ -198,7 +198,7 @@ var _ = Describe("Test rbac service", func() {
policies, err := rbacService.ListPermissions(context.TODO(), "init-test")
Expect(err).Should(BeNil())
Expect(len(policies)).Should(BeEquivalentTo(int64(5)))
Expect(len(policies)).Should(BeEquivalentTo(int64(6)))
})
It("Test UpdatePermission", func() {

View File

@@ -25,6 +25,7 @@ import (
"testing"
"time"
"github.com/kubevela/workflow/api/v1alpha1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
@@ -74,7 +75,10 @@ var _ = BeforeSuite(func(done Done) {
By("new kube client")
cfg.Timeout = time.Minute * 2
k8sClient, err = client.New(cfg, client.Options{Scheme: common.Scheme})
scheme := common.Scheme
err = v1alpha1.AddToScheme(scheme)
Expect(err).ShouldNot(HaveOccurred())
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).Should(BeNil())
Expect(k8sClient).ToNot(BeNil())
By("new kube client success")

View File

@@ -8,6 +8,8 @@ metadata:
definition.oam.dev/alias: test-alias
name: apply-application
namespace: vela-system
labels:
custom.definition.oam.dev/scope: Application
spec:
schematic:
cue:

View File

@@ -52,6 +52,9 @@ func guaranteePolicyNotExist(c []string, policy string) ([]string, bool) {
// extractPolicyListAndProperty can extract policy from string-format properties, and return
// map-format properties in order to further update operation.
func extractPolicyListAndProperty(property string) ([]string, map[string]interface{}, error) {
if len(property) == 0 {
return nil, nil, nil
}
content := map[string]interface{}{}
err := json.Unmarshal([]byte(property), &content)
if err != nil {

View File

@@ -208,6 +208,14 @@ func TestExtractPolicyListAndProperty(t *testing.T) {
noError bool
}{noError: false},
},
{
input: ``,
res: struct {
policies []string
properties map[string]interface{}
noError bool
}{policies: nil, properties: nil, noError: true},
},
}
for _, testCase := range testCases {
policy, properties, err := extractPolicyListAndProperty(testCase.input)

View File

@@ -36,6 +36,7 @@ import (
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/repository"
"github.com/oam-dev/kubevela/pkg/apiserver/event/sync/convert"
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
assembler "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/assembler/v1"
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
@@ -149,26 +150,12 @@ func (w *workflowServiceImpl) CreateOrUpdateWorkflow(ctx context.Context, app *m
if err != nil && errors.Is(err, datastore.ErrRecordNotExist) {
return nil, err
}
var steps []model.WorkflowStep
for _, step := range req.Steps {
properties, err := model.NewJSONStructByString(step.Properties)
if err != nil {
log.Logger.Errorf("parse trait properties failire %w", err)
return nil, bcode.ErrInvalidProperties
}
steps = append(steps, model.WorkflowStep{
Name: step.Name,
Type: step.Type,
Alias: step.Alias,
Inputs: step.Inputs,
Outputs: step.Outputs,
Description: step.Description,
DependsOn: step.DependsOn,
Properties: properties,
})
modelSteps, err := assembler.CreateWorkflowStepModel(req.Steps)
if err != nil {
return nil, err
}
if workflow != nil {
workflow.Steps = steps
workflow.Steps = modelSteps
workflow.Alias = req.Alias
workflow.Description = req.Description
workflow.Default = req.Default
@@ -178,7 +165,7 @@ func (w *workflowServiceImpl) CreateOrUpdateWorkflow(ctx context.Context, app *m
} else {
// It is allowed to set multiple workflows as default, and only one takes effect.
workflow = &model.Workflow{
Steps: steps,
Steps: modelSteps,
Name: req.Name,
Alias: req.Alias,
Description: req.Description,
@@ -490,6 +477,8 @@ func (w *workflowServiceImpl) syncWorkflowStatus(ctx context.Context, appPrimary
status := app.Status.Workflow
summaryStatus := model.RevisionStatusRunning
switch {
case status.Phase == workflowv1alpha1.WorkflowStateFailed:
summaryStatus = model.RevisionStatusFail
case status.Finished:
summaryStatus = model.RevisionStatusComplete
case status.Terminated:
@@ -497,17 +486,26 @@ func (w *workflowServiceImpl) syncWorkflowStatus(ctx context.Context, appPrimary
}
record.Status = summaryStatus
stepStatus := make(map[string]*workflowv1alpha1.WorkflowStepStatus, len(status.Steps))
for i, step := range status.Steps {
stepStatus[step.Name] = &status.Steps[i]
stepStatus := make(map[string]*model.WorkflowStepStatus, len(status.Steps))
stepAlias := make(map[string]string)
for _, step := range record.Steps {
stepAlias[step.Name] = step.Alias
for _, sub := range step.SubStepsStatus {
stepAlias[sub.Name] = sub.Alias
}
}
for _, step := range status.Steps {
stepStatus[step.Name] = &model.WorkflowStepStatus{
StepStatus: convert.FromCRWorkflowStepStatus(step.StepStatus, stepAlias[step.Name]),
SubStepsStatus: make([]model.StepStatus, 0),
}
for _, sub := range step.SubStepsStatus {
stepStatus[step.Name].SubStepsStatus = append(stepStatus[step.Name].SubStepsStatus, convert.FromCRWorkflowStepStatus(sub, stepAlias[sub.Name]))
}
}
for i, step := range record.Steps {
if stepStatus[step.Name] != nil {
record.Steps[i].Phase = stepStatus[step.Name].Phase
record.Steps[i].Message = stepStatus[step.Name].Message
record.Steps[i].Reason = stepStatus[step.Name].Reason
record.Steps[i].FirstExecuteTime = stepStatus[step.Name].FirstExecuteTime.Time
record.Steps[i].LastExecuteTime = stepStatus[step.Name].LastExecuteTime.Time
record.Steps[i] = *stepStatus[step.Name]
}
}
record.Finished = strconv.FormatBool(status.Finished)
@@ -542,9 +540,19 @@ func (w *workflowServiceImpl) CreateWorkflowRecord(ctx context.Context, appModel
steps := make([]model.WorkflowStepStatus, len(workflow.Steps))
for i, step := range workflow.Steps {
steps[i] = model.WorkflowStepStatus{
Name: step.Name,
Alias: step.Alias,
Type: step.Type,
StepStatus: model.StepStatus{
Name: step.Name,
Alias: step.Alias,
Type: step.Type,
},
SubStepsStatus: make([]model.StepStatus, 0),
}
for _, sub := range step.SubSteps {
steps[i].SubStepsStatus = append(steps[i].SubStepsStatus, model.StepStatus{
Name: sub.Name,
Alias: sub.Alias,
Type: sub.Type,
})
}
}
@@ -615,7 +623,7 @@ func resetRevisionsAndRecords(ctx context.Context, ds datastore.DataStore, appNa
record.Finished = "true"
for i, step := range record.Steps {
if step.Phase == workflowv1alpha1.WorkflowStepPhaseRunning {
record.Steps[i].Phase = workflowv1alpha1.WorkflowStepPhaseStopped
record.Steps[i].Phase = model.WorkflowStepPhaseStopped
}
}
if err := ds.Put(ctx, record); err != nil {
@@ -709,7 +717,7 @@ func TerminateWorkflow(ctx context.Context, kubecli client.Client, app *v1beta1.
switch sub.Phase {
case workflowv1alpha1.WorkflowStepPhaseFailed:
if sub.Reason != wfTypes.StatusReasonFailedAfterRetries && sub.Reason != wfTypes.StatusReasonTimeout {
steps[i].SubStepsStatus[j].Phase = wfTypes.StatusReasonTerminate
steps[i].SubStepsStatus[j].Reason = wfTypes.StatusReasonTerminate
}
case workflowv1alpha1.WorkflowStepPhaseRunning:
steps[i].SubStepsStatus[j].Phase = workflowv1alpha1.WorkflowStepPhaseFailed

View File

@@ -58,7 +58,7 @@ var _ = Describe("Test workflow service functions", func() {
Expect(ds).ToNot(BeNil())
Expect(err).Should(BeNil())
rbacService := &rbacServiceImpl{Store: ds}
projectService = &projectServiceImpl{Store: ds, RbacService: rbacService}
projectService = &projectServiceImpl{Store: ds, RbacService: rbacService, K8sClient: k8sClient}
envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService}
envBinding = &envBindingServiceImpl{
Store: ds,
@@ -123,12 +123,28 @@ var _ = Describe("Test workflow service functions", func() {
EnvName: "dev",
Steps: []apisv1.WorkflowStep{
{
Name: "apply-pvc",
Alias: "step-alias-1",
WorkflowStepBase: apisv1.WorkflowStepBase{
Name: "apply-server",
Alias: "step-alias-1",
},
},
{
Name: "apply-server",
Alias: "step-alias-2",
WorkflowStepBase: apisv1.WorkflowStepBase{
Name: "apply-server2",
Alias: "step-alias-2",
},
},
{
WorkflowStepBase: apisv1.WorkflowStepBase{
Name: "group",
Alias: "group-alias",
},
SubSteps: []apisv1.WorkflowStepBase{
{
Name: "suspend",
Alias: "my-suspend",
},
},
},
},
Default: &defaultW,
@@ -255,16 +271,20 @@ var _ = Describe("Test workflow service functions", func() {
By("check the record")
record, err := workflowService.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-233")
Expect(err).Should(BeNil())
Expect(record.Status).Should(Equal(model.RevisionStatusComplete))
Expect(record.Status).Should(Equal(model.RevisionStatusFail))
Expect(record.Steps[0].Alias).Should(Equal("step-alias-1"))
Expect(record.Steps[0].Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
Expect(record.Steps[1].Alias).Should(Equal("step-alias-2"))
Expect(record.Steps[1].Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
Expect(record.Steps[2].Alias).Should(Equal("group-alias"))
Expect(record.Steps[2].Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseFailed))
Expect(record.Steps[2].SubStepsStatus[0].Alias).Should(Equal("my-suspend"))
Expect(record.Steps[2].SubStepsStatus[0].Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseFailed))
By("check the application revision")
err = workflowService.Store.Get(ctx, revision)
Expect(err).Should(BeNil())
Expect(revision.Status).Should(Equal(model.RevisionStatusComplete))
Expect(revision.Status).Should(Equal(model.RevisionStatusFail))
By("create another workflow record to test sync status from controller revision")
app.Status.Workflow.Finished = false
@@ -314,12 +334,12 @@ var _ = Describe("Test workflow service functions", func() {
By("check the record")
anotherRecord, err := workflowService.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-111")
Expect(err).Should(BeNil())
Expect(anotherRecord.Status).Should(Equal(model.RevisionStatusComplete))
Expect(anotherRecord.Status).Should(Equal(model.RevisionStatusFail))
By("check the application revision")
err = workflowService.Store.Get(ctx, anotherRevision)
Expect(err).Should(BeNil())
Expect(anotherRevision.Status).Should(Equal(model.RevisionStatusComplete))
Expect(anotherRevision.Status).Should(Equal(model.RevisionStatusFail))
})
It("Test CreateRecord function", func() {
@@ -541,10 +561,14 @@ var _ = Describe("Test workflow service functions", func() {
Finished: "false",
Steps: []model.WorkflowStepStatus{
{
Phase: workflowv1alpha1.WorkflowStepPhaseSucceeded,
StepStatus: model.StepStatus{
Phase: workflowv1alpha1.WorkflowStepPhaseSucceeded,
},
},
{
Phase: workflowv1alpha1.WorkflowStepPhaseRunning,
StepStatus: model.StepStatus{
Phase: workflowv1alpha1.WorkflowStepPhaseRunning,
},
},
},
})
@@ -562,7 +586,7 @@ var _ = Describe("Test workflow service functions", func() {
Expect(err).Should(BeNil())
Expect(record.Status).Should(Equal(model.RevisionStatusTerminated))
Expect(record.Finished).Should(Equal("true"))
Expect(record.Steps[1].Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseStopped))
Expect(record.Steps[1].Phase).Should(Equal(model.WorkflowStepPhaseStopped))
})
It("Test deleting workflow", func() {
@@ -619,10 +643,10 @@ var yamlStr = `apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
annotations:
app.oam.dev/workflowName: test-workflow-2
app.oam.dev/appName: app-workflow
app.oam.dev/deployVersion: "1234"
app.oam.dev/publishVersion: "test-workflow-name-111"
app.oam.dev/appName: "app-workflow"
app.oam.dev/publishVersion: test-workflow-name-111
app.oam.dev/workflowName: test-workflow-2
name: app-workflow
namespace: default
spec:
@@ -632,31 +656,71 @@ spec:
image: crccheck/hello-world
port: 8000
type: webservice
- name: express-server2
properties:
image: crccheck/hello-world
port: 8000
type: webservice
workflow:
steps:
- name: apply-server
properties:
component: express-server
type: apply-component
- name: apply-server2
properties:
component: express-server
type: apply-component
- name: group
subSteps:
- name: suspend
timeout: 1s
type: suspend
type: step-group
status:
status: workflowFailed
workflow:
appRevision: test-workflow-name-111
contextBackend:
name: workflow-app-workflow-context
namespace: default
uid: ef9bcf49-66a7-4c69-b349-150810aa2bac
endTime: "2022-10-28T06:45:46Z"
finished: true
message: The workflow terminates because of the failed steps
mode: StepByStep-DAG
startTime: "2022-10-28T06:45:37Z"
status: failed
steps:
- firstExecuteTime: "2021-10-26T11:19:33Z"
id: t8bpvi88d1
lastExecuteTime: "2021-10-26T11:19:33Z"
name: apply-pvc
phase: succeeded
type: apply-object
- firstExecuteTime: "2021-10-26T11:19:33Z"
id: 9fou7rbq9r
lastExecuteTime: "2021-10-26T11:19:33Z"
- firstExecuteTime: "2022-10-28T06:45:37Z"
id: fg5uiwroe6
lastExecuteTime: "2022-10-28T06:45:45Z"
name: apply-server
phase: succeeded
type: apply-component
- firstExecuteTime: "2022-10-28T06:45:45Z"
id: prouwp48y7
lastExecuteTime: "2022-10-28T06:45:45Z"
name: apply-server2
phase: succeeded
type: apply-component
- firstExecuteTime: "2022-10-28T06:45:45Z"
id: s6o27xnkzq
lastExecuteTime: "2022-10-28T06:45:46Z"
name: group
phase: failed
reason: Timeout
subSteps:
- firstExecuteTime: "2022-10-28T06:45:45Z"
id: ctu63esz2m
lastExecuteTime: "2022-10-28T06:45:46Z"
name: suspend
phase: failed
reason: Timeout
type: suspend
type: step-group
suspend: false
terminated: false
finished: true
appRevision: "test-workflow-name-111"`
terminated: true`
func (w *workflowServiceImpl) createTestApplicationRevision(ctx context.Context, revision *model.ApplicationRevision) error {
if err := w.Store.Add(ctx, revision); err != nil {

View File

@@ -112,25 +112,48 @@ func FromCRWorkflow(ctx context.Context, cli client.Client, appPrimaryKey string
steps = app.Spec.Workflow.Steps
}
for _, s := range steps {
ws := model.WorkflowStep{
Name: s.Name,
Type: s.Type,
Inputs: s.Inputs,
Outputs: s.Outputs,
DependsOn: s.DependsOn,
base, err := FromCRWorkflowStepBase(s.WorkflowStepBase)
if err != nil {
return dataWf, nil, err
}
if s.Properties != nil {
properties, err := model.NewJSONStruct(s.Properties)
ws := model.WorkflowStep{
WorkflowStepBase: *base,
SubSteps: make([]model.WorkflowStepBase, 0),
}
for _, sub := range s.SubSteps {
subBase, err := FromCRWorkflowStepBase(sub)
if err != nil {
return dataWf, nil, err
}
ws.Properties = properties
ws.SubSteps = append(ws.SubSteps, *subBase)
}
dataWf.Steps = append(dataWf.Steps, ws)
}
return dataWf, steps, nil
}
// FromCRWorkflowStepBase convert cr to model
func FromCRWorkflowStepBase(step workflowv1alpha1.WorkflowStepBase) (*model.WorkflowStepBase, error) {
base := &model.WorkflowStepBase{
Name: step.Name,
Type: step.Type,
Inputs: step.Inputs,
Outputs: step.Outputs,
DependsOn: step.DependsOn,
Meta: step.Meta,
If: step.If,
Timeout: step.Timeout,
}
if step.Properties != nil {
properties, err := model.NewJSONStruct(step.Properties)
if err != nil {
return nil, err
}
base.Properties = properties
}
return base, nil
}
// FromCRTargets converts deployed Cluster/Namespace from Application CR Status into velaux data store
func FromCRTargets(ctx context.Context, cli client.Client, targetApp *v1beta1.Application, existTargets []datastore.Entity, project string) ([]*model.Target, map[string]string) {
existTarget := make(map[string]*model.Target)
@@ -187,9 +210,11 @@ func FromCRWorkflowRecord(app *v1beta1.Application, workflow model.Workflow, rev
steps := make([]model.WorkflowStepStatus, len(workflow.Steps))
for i, step := range workflow.Steps {
steps[i] = model.WorkflowStepStatus{
Name: step.Name,
Alias: step.Alias,
Type: step.Type,
StepStatus: model.StepStatus{
Name: step.Name,
Alias: step.Alias,
Type: step.Type,
},
}
}
return &model.WorkflowRecord{
@@ -205,6 +230,21 @@ func FromCRWorkflowRecord(app *v1beta1.Application, workflow model.Workflow, rev
}
}
// FromCRWorkflowStepStatus convert the workflow step status to workflow step status
func FromCRWorkflowStepStatus(stepStatus workflowv1alpha1.StepStatus, alias string) model.StepStatus {
return model.StepStatus{
Name: stepStatus.Name,
Alias: alias,
ID: stepStatus.ID,
Type: stepStatus.Type,
Message: stepStatus.Message,
Reason: stepStatus.Reason,
Phase: stepStatus.Phase,
FirstExecuteTime: stepStatus.FirstExecuteTime.Time,
LastExecuteTime: stepStatus.LastExecuteTime.Time,
}
}
// FromCRApplicationRevision convert the application revision to the revision in the data store
func FromCRApplicationRevision(ctx context.Context, cli client.Client, app *v1beta1.Application, workflow model.Workflow, envName string) *model.ApplicationRevision {
if app.Status.Workflow == nil || app.Status.Workflow.AppRevision == "" {

View File

@@ -17,19 +17,18 @@ limitations under the License.
package clients
import (
"errors"
"fmt"
pkgmulticluster "github.com/kubevela/pkg/multicluster"
"github.com/kubevela/workflow/api/v1alpha1"
"github.com/kubevela/workflow/pkg/cue/packages"
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"github.com/kubevela/workflow/pkg/cue/packages"
apiConfig "github.com/oam-dev/kubevela/pkg/apiserver/config"
"github.com/oam-dev/kubevela/pkg/auth"
"github.com/oam-dev/kubevela/pkg/multicluster"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/utils/common"
)
@@ -74,20 +73,13 @@ func GetKubeClient() (client.Client, error) {
if kubeConfig == nil {
return nil, fmt.Errorf("please call SetKubeConfig first")
}
var err error
kubeClient, err = multicluster.Initialize(kubeConfig, false)
if err == nil {
return kubeClient, nil
}
if !errors.Is(err, multicluster.ErrDetectClusterGateway) {
return nil, err
}
// create single cluster client
kubeClient, err = client.New(kubeConfig, client.Options{Scheme: common.Scheme})
err := v1alpha1.AddToScheme(common.Scheme)
if err != nil {
return nil, err
}
return kubeClient, nil
return pkgmulticluster.NewClient(kubeConfig, pkgmulticluster.ClientOptions{
Options: client.Options{Scheme: common.Scheme},
})
}
// GetKubeConfig create/get kube runtime config

View File

@@ -212,13 +212,11 @@ func (m *mongodb) List(ctx context.Context, entity datastore.Entity, op *datasto
collection := m.client.Database(m.database).Collection(entity.TableName())
// bson.D{{}} specifies 'all documents'
filter := bson.D{}
if entity.Index() != nil {
for k, v := range entity.Index() {
filter = append(filter, bson.E{
Key: strings.ToLower(k),
Value: v,
})
}
for k, v := range entity.Index() {
filter = append(filter, bson.E{
Key: strings.ToLower(k),
Value: v,
})
}
if op != nil {
filter = _applyFilterOptions(filter, op.FilterOptions)
@@ -272,13 +270,11 @@ func (m *mongodb) Count(ctx context.Context, entity datastore.Entity, filterOpti
}
collection := m.client.Database(m.database).Collection(entity.TableName())
filter := bson.D{}
if entity.Index() != nil {
for k, v := range entity.Index() {
filter = append(filter, bson.E{
Key: strings.ToLower(k),
Value: v,
})
}
for k, v := range entity.Index() {
filter = append(filter, bson.E{
Key: strings.ToLower(k),
Value: v,
})
}
if filterOptions != nil {
filter = _applyFilterOptions(filter, *filterOptions)

View File

@@ -152,19 +152,36 @@ func ConvertFromRecordModel(record *model.WorkflowRecord) *apisv1.WorkflowRecord
// ConvertFromWorkflowStepModel assemble the WorkflowStep model to DTO
func ConvertFromWorkflowStepModel(step model.WorkflowStep) apisv1.WorkflowStep {
apiStep := apisv1.WorkflowStep{
WorkflowStepBase: ConvertFromWorkflowStepBaseModel(step.WorkflowStepBase),
SubSteps: make([]apisv1.WorkflowStepBase, 0),
}
if step.Properties != nil {
apiStep.Properties = step.Properties.JSON()
}
for _, sub := range step.SubSteps {
apiStep.SubSteps = append(apiStep.SubSteps, ConvertFromWorkflowStepBaseModel(sub))
}
return apiStep
}
// ConvertFromWorkflowStepBaseModel assemble the WorkflowStep model to DTO
func ConvertFromWorkflowStepBaseModel(step model.WorkflowStepBase) apisv1.WorkflowStepBase {
apiStepBase := apisv1.WorkflowStepBase{
Name: step.Name,
Type: step.Type,
Alias: step.Alias,
Description: step.Description,
Inputs: step.Inputs,
Outputs: step.Outputs,
Properties: step.Properties.JSON(),
DependsOn: step.DependsOn,
Meta: step.Meta,
If: step.If,
Timeout: step.Timeout,
}
if step.Properties != nil {
apiStep.Properties = step.Properties.JSON()
apiStepBase.Properties = step.Properties.JSON()
}
return apiStep
return apiStepBase
}
// ConvertWorkflowBase assemble the Workflow model to DTO

View File

@@ -47,21 +47,44 @@ func ConvertToEnvBindingModel(app *model.Application, envBind apisv1.EnvBinding)
func CreateWorkflowStepModel(apiSteps []apisv1.WorkflowStep) ([]model.WorkflowStep, error) {
var steps []model.WorkflowStep
for _, step := range apiSteps {
properties, err := model.NewJSONStructByString(step.Properties)
base, err := CreateWorkflowStepBaseModel(step.WorkflowStepBase)
if err != nil {
log.Logger.Errorf("parse trait properties failure %w", err)
return nil, bcode.ErrInvalidProperties
return nil, err
}
steps = append(steps, model.WorkflowStep{
Name: step.Name,
Alias: step.Alias,
Description: step.Description,
DependsOn: step.DependsOn,
Type: step.Type,
Inputs: step.Inputs,
Outputs: step.Outputs,
Properties: properties,
})
stepModel := model.WorkflowStep{
WorkflowStepBase: *base,
SubSteps: make([]model.WorkflowStepBase, 0),
}
for _, sub := range step.SubSteps {
base, err := CreateWorkflowStepBaseModel(sub)
if err != nil {
return nil, err
}
stepModel.SubSteps = append(stepModel.SubSteps, *base)
}
steps = append(steps, stepModel)
}
return steps, nil
}
// CreateWorkflowStepBaseModel convert api to model
func CreateWorkflowStepBaseModel(step apisv1.WorkflowStepBase) (*model.WorkflowStepBase, error) {
properties, err := model.NewJSONStructByString(step.Properties)
if err != nil {
log.Logger.Errorf("parse trait workflow step failure %w", err)
return nil, bcode.ErrInvalidProperties
}
return &model.WorkflowStepBase{
Name: step.Name,
Type: step.Type,
Alias: step.Alias,
Description: step.Description,
Properties: properties,
Inputs: step.Inputs,
Outputs: step.Outputs,
DependsOn: step.DependsOn,
Meta: step.Meta,
If: step.If,
Timeout: step.Timeout,
}, nil
}

View File

@@ -51,6 +51,7 @@ func (d *definitionAPIInterface) GetWebServiceRoute() *restful.WebService {
Param(ws.QueryParameter("queryAll", "query all definitions include hidden in UI").DataType("boolean").DefaultValue("false")).
Param(ws.QueryParameter("appliedWorkload", "if specified, query the trait definition applied to the workload").DataType("string")).
Param(ws.QueryParameter("ownerAddon", "query by which addon created the definition").DataType("string")).
Param(ws.QueryParameter("scope", "query by the specified scope like WorkflowRun or Application").DataType("string")).
Returns(200, "OK", apis.ListDefinitionResponse{}).
Writes(apis.ListDefinitionResponse{}).Do(returns200, returns500))
@@ -97,6 +98,7 @@ func (d *definitionAPIInterface) listDefinitions(req *restful.Request, res *rest
Type: req.QueryParameter("type"),
AppliedWorkloads: req.QueryParameter("appliedWorkload"),
OwnerAddon: req.QueryParameter("ownerAddon"),
Scope: req.QueryParameter("scope"),
QueryAll: queryAll,
})
if err != nil {

View File

@@ -50,12 +50,14 @@ var (
CtxKeyApplicationComponent = "component"
// CtxKeyUser request context key of user
CtxKeyUser = "user"
// CtxKeyProject request context key of project
CtxKeyProject = "project"
// CtxKeyToken request context key of request token
CtxKeyToken = "token"
// CtxKeyPipeline request context key of pipeline
CtxKeyPipeline = "pipeline"
// CtxKeyPipelineContex request context key of pipeline context
CtxKeyPipelineContex = "pipeline-context"
// CtxKeyPipelineContext request context key of pipeline context
CtxKeyPipelineContext = "pipeline-context"
// CtxKeyPipelineRun request context key of pipeline run
CtxKeyPipelineRun = "pipeline-run"
)
@@ -791,6 +793,7 @@ type ProjectBase struct {
CreateTime time.Time `json:"createTime"`
UpdateTime time.Time `json:"updateTime"`
Owner NameAlias `json:"owner,omitempty"`
Namespace string `json:"namespace"`
}
// CreateProjectRequest create project request body
@@ -1003,15 +1006,24 @@ type UpdateWorkflowRequest struct {
// WorkflowStep workflow step config
type WorkflowStep struct {
WorkflowStepBase `json:",inline"`
SubSteps []WorkflowStepBase `json:"subSteps,omitempty"`
}
// WorkflowStepBase is the step base of workflow
type WorkflowStepBase struct {
// Name is the unique name of the workflow step.
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Type string `json:"type" validate:"checkname"`
Description string `json:"description" optional:"true"`
DependsOn []string `json:"dependsOn" optional:"true"`
Properties string `json:"properties,omitempty"`
Inputs workflowv1alpha1.StepInputs `json:"inputs,omitempty" optional:"true"`
Outputs workflowv1alpha1.StepOutputs `json:"outputs,omitempty" optional:"true"`
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Type string `json:"type" validate:"checkname"`
Description string `json:"description" optional:"true"`
DependsOn []string `json:"dependsOn" optional:"true"`
Properties string `json:"properties,omitempty"`
Meta *workflowv1alpha1.WorkflowStepMeta `json:"meta,omitempty" optional:"true"`
If string `json:"if,omitempty" optional:"true"`
Timeout string `json:"timeout,omitempty" optional:"true"`
Inputs workflowv1alpha1.StepInputs `json:"inputs,omitempty" optional:"true"`
Outputs workflowv1alpha1.StepOutputs `json:"outputs,omitempty" optional:"true"`
}
// DetailWorkflowResponse detail workflow response
@@ -1542,16 +1554,17 @@ type ListConfigDistributionResponse struct {
// PipelineMeta is metadata of pipeline
type PipelineMeta struct {
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Project string `json:"project"`
Description string `json:"description" optional:"true"`
Name string `json:"name"`
Alias string `json:"alias"`
Project NameAlias `json:"project"`
Description string `json:"description"`
CreateTime time.Time `json:"createTime"`
}
// PipelineBase is the base info of pipeline
type PipelineBase struct {
PipelineMeta `json:",inline"`
Spec workflowv1alpha1.WorkflowSpec `json:"spec"`
Spec model.WorkflowSpec `json:"spec"`
}
// RunStatInfo is the pipeline run statistics info
@@ -1570,11 +1583,10 @@ type RunStat struct {
// CreatePipelineRequest is the request body of creating pipeline
type CreatePipelineRequest struct {
Name string `json:"name" validate:"checkname"`
Project string `json:"project"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
Spec workflowv1alpha1.WorkflowSpec `json:"spec"`
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
Spec model.WorkflowSpec `json:"spec"`
}
// PipelineMetaResponse is the response body contains PipelineMeta
@@ -1584,8 +1596,9 @@ type PipelineMetaResponse struct {
// ListPipelineRequest is the request body of listing pipeline
type ListPipelineRequest struct {
Projects []string `json:"projects"`
Query string `json:"query"`
Projects []string `json:"projects" optional:"true"`
Query string `json:"query" optional:"true"`
Detailed bool `json:"detailed" optional:"true"`
}
// ListPipelineResponse is the response body of listing pipeline
@@ -1602,14 +1615,9 @@ type PipelineListItem struct {
// UpdatePipelineRequest is the request body of updating pipeline
type UpdatePipelineRequest struct {
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
Spec workflowv1alpha1.WorkflowSpec `json:"spec" optional:"true"`
}
// GetPipelineRequest is the request body of getting pipeline
type GetPipelineRequest struct {
Detailed bool `json:"detailed"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
Spec model.WorkflowSpec `json:"spec" optional:"true"`
}
// GetPipelineResponse is the response body of getting pipeline
@@ -1620,9 +1628,8 @@ type GetPipelineResponse struct {
// PipelineInfo is the info of pipeline
type PipelineInfo struct {
RelatedApps []ApplicationBase `json:"relatedApps"`
LastRunStatus workflowv1alpha1.WorkflowRunStatus `json:"lastRunStatus"`
RunStat RunStat `json:"runStat"`
LastRun *PipelineRun `json:"lastRun"`
RunStat RunStat `json:"runStat"`
}
/***********************/
@@ -1643,9 +1650,9 @@ type PipelineRunBriefing struct {
// PipelineRunMeta is the metadata of pipeline run
type PipelineRunMeta struct {
PipelineName string `json:"pipelineName"`
Project string `json:"project"`
PipelineRunName string `json:"pipelineRunName"`
PipelineName string `json:"pipelineName"`
Project NameAlias `json:"project"`
PipelineRunName string `json:"pipelineRunName"`
}
// PipelineRun is the info of pipeline run
@@ -1658,14 +1665,16 @@ type PipelineRun struct {
type PipelineRunBase struct {
PipelineRunMeta `json:",inline"`
// Record marks the run of the pipeline
Record int64 `json:"record"`
ContextName string `json:"contextName"`
Spec workflowv1alpha1.WorkflowRunSpec `json:"spec"`
Record int64 `json:"record"`
ContextName string `json:"contextName"`
ContextValues []model.Value `json:"contextValues"`
Spec workflowv1alpha1.WorkflowRunSpec `json:"spec"`
}
// RunPipelineRequest is the request body of running pipeline
type RunPipelineRequest struct {
// Mode is the mode of the pipeline run. Available values are: "StepByStep", "DAG" for both `step` and `subStep`
// default: "StepByStep" for `step`, "DAG" for `subStep`
Mode workflowv1alpha1.WorkflowExecuteMode `json:"mode" optional:"true"`
ContextName string `json:"contextName"`
}
@@ -1678,12 +1687,18 @@ type ListPipelineRunResponse struct {
// GetPipelineRunLogResponse is the response body of getting pipeline run log
type GetPipelineRunLogResponse struct {
Log []Log `json:"log"`
StepBase `json:",inline"`
Log string `json:"log"`
}
// GetPipelineRunOutputResponse is the response body of getting pipeline run output
type GetPipelineRunOutputResponse struct {
Output []Output `json:"output"`
StepOutputs []StepOutputBase `json:"outputs"`
}
// GetPipelineRunInputResponse is the response body of getting pipeline run input
type GetPipelineRunInputResponse struct {
StepInputs []StepInputBase `json:"inputs"`
}
// StepBase is the base info of step
@@ -1694,16 +1709,31 @@ type StepBase struct {
Phase string `json:"phase"`
}
// Log is the log of step
type Log struct {
// StepOutputBase is the output of step
type StepOutputBase struct {
StepBase `json:",inline"`
Log string `json:"log"`
Values []OutputVar `json:"values"`
}
// Output is the output of step
type Output struct {
// StepInputBase is the input of step
type StepInputBase struct {
StepBase `json:",inline"`
Vars map[string]string `json:"vars"`
Values []InputVar `json:"values"`
}
// OutputVar is one output var
type OutputVar struct {
Name string `json:"name"`
Value string `json:"value"`
ValueFrom string `json:"valueFrom"`
}
// InputVar is one input var
type InputVar struct {
From string `json:"from"`
FromStep string `json:"fromStep"`
ParameterKey string `json:"parameterKey"`
Value string `json:"value"`
}
/*******************/

View File

@@ -62,6 +62,7 @@ func InitAPIBean() []interface{} {
RegisterAPIInterface(NewApplicationAPIInterface())
RegisterAPIInterface(NewProjectAPIInterface())
RegisterAPIInterface(NewEnvAPIInterface())
RegisterAPIInterface(NewPipelineAPIInterface())
// Extension
RegisterAPIInterface(NewDefinitionAPIInterface())
@@ -82,7 +83,6 @@ func InitAPIBean() []interface{} {
RegisterAPIInterface(NewWebhookAPIInterface())
RegisterAPIInterface(NewRepositoryAPIInterface())
RegisterAPIInterface(NewCloudShellAPIInterface())
RegisterAPIInterface(NewPipelineAPIInterface())
// Authentication
RegisterAPIInterface(NewAuthenticationAPIInterface())

View File

@@ -18,199 +18,242 @@ package api
import (
"context"
"strconv"
restfulspec "github.com/emicklei/go-restful-openapi/v2"
"github.com/emicklei/go-restful/v3"
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/log"
"github.com/kubevela/workflow/api/v1alpha1"
"github.com/pkg/errors"
"github.com/oam-dev/kubevela/pkg/apiserver/domain/service"
apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
"github.com/oam-dev/kubevela/pkg/apiserver/utils/log"
)
type pipelineAPIInterface struct {
PipelineService service.PipelineService `inject:""`
PipelineRunService service.PipelineRunService `inject:""`
ContextService service.ContextService `inject:""`
}
type pipelinePathParamKey string
const (
// Project is the project name key of query param
Project pipelinePathParamKey = "projectName"
Project string = "projectName"
// Pipeline is the pipeline name of query param
Pipeline pipelinePathParamKey = "pipelineName"
Pipeline string = "pipelineName"
// PipelineRun is the pipeline run name of query param
PipelineRun pipelinePathParamKey = "runName"
PipelineRun string = "runName"
// ContextName is the context name of query param
ContextName pipelinePathParamKey = "contextName"
ContextName string = "contextName"
)
// GetWebServiceRoute is the implementation of pipeline Interface
func (p *pipelineAPIInterface) GetWebServiceRoute() *restful.WebService {
ws := new(restful.WebService)
func initPipelineRoutes(ws *restful.WebService, n *projectAPIInterface) {
tags := []string{"pipeline"}
projParam := func(builder *restful.RouteBuilder) {
builder.Param(ws.QueryParameter(string(Project), "project name").Required(true))
builder.Param(ws.PathParameter(Project, "project name").Required(true))
builder.Filter(n.projectCheckFilter)
}
pipelineParam := func(builder *restful.RouteBuilder) {
builder.Param(ws.PathParameter(string(Pipeline), "pipeline name").Required(true))
builder.Filter(p.pipelineCheckFilter)
builder.Param(ws.PathParameter(Pipeline, "pipeline name").Required(true))
builder.Filter(n.pipelineCheckFilter)
}
ctxParam := func(builder *restful.RouteBuilder) {
builder.Param(ws.PathParameter(string(ContextName), "pipeline context name").Required(true))
builder.Filter(p.pipelineContextCheckFilter)
builder.Param(ws.PathParameter(ContextName, "pipeline context name").Required(true))
builder.Filter(n.pipelineContextCheckFilter)
}
runParam := func(builder *restful.RouteBuilder) {
builder.Param(ws.PathParameter(string(PipelineRun), "pipeline run name").Required(true))
builder.Filter(p.pipelineRunCheckFilter)
builder.Param(ws.PathParameter(PipelineRun, "pipeline run name").Required(true))
builder.Filter(n.pipelineRunCheckFilter)
}
meta := func(builder *restful.RouteBuilder) {
builder.Metadata(restfulspec.KeyOpenAPITags, tags)
}
ws.Path(versionPrefix+"/pipelines").
Consumes(restful.MIME_JSON, restful.MIME_XML).
Produces(restful.MIME_JSON, restful.MIME_XML).
Doc("api for pipeline manage")
ws.Route(ws.POST("").To(p.createPipeline).
ws.Route(ws.POST("/{projectName}/pipelines").To(n.createPipeline).
Doc("create pipeline").
Reads(apis.CreatePipelineRequest{}).
Returns(200, "OK", apis.PipelineBase{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.PipelineBase{}).Do(meta))
Filter(n.RBACService.CheckPerm("project/pipeline", "create")).
Writes(apis.PipelineBase{}).Do(meta, projParam))
ws.Route(ws.GET("").To(p.listPipelines).
Doc("list pipelines").
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
Returns(200, "OK", apis.ListPipelineResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.ListPipelineResponse{}).Do(meta, projParam))
ws.Route(ws.GET("/{pipelineName}").To(p.getPipeline).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}").To(n.getPipeline).
Doc("get pipeline").
Reads(apis.GetPipelineRequest{}).
Returns(200, "OK", apis.GetPipelineResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.GetPipelineResponse{}).Do(meta, projParam, pipelineParam))
// use Param instead of pipelineParam to get pipeline information
Param(ws.PathParameter(Pipeline, "pipeline name").Required(true)).
Filter(n.RBACService.CheckPerm("project/pipeline", "detail")).
Writes(apis.GetPipelineResponse{}).Do(meta, projParam))
ws.Route(ws.PUT("/{pipelineName}").To(p.updatePipeline).
ws.Route(ws.PUT("/{projectName}/pipelines/{pipelineName}").To(n.updatePipeline).
Doc("update pipeline").
Reads(apis.UpdatePipelineRequest{}).
Returns(200, "OK", apis.PipelineBase{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline", "update")).
Writes(apis.PipelineBase{}).Do(meta, projParam, pipelineParam))
ws.Route(ws.DELETE("/{pipelineName}").To(p.deletePipeline).
ws.Route(ws.DELETE("/{projectName}/pipelines/{pipelineName}").To(n.deletePipeline).
Doc("delete pipeline").
Returns(200, "OK", apis.PipelineMetaResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline", "delete")).
Writes(apis.PipelineMetaResponse{}).Do(meta, projParam, pipelineParam))
ws.Route(ws.POST("/{pipelineName}/contexts").To(p.createContextValue).
ws.Route(ws.POST("/{projectName}/pipelines/{pipelineName}/contexts").To(n.createContextValue).
Doc("create pipeline context values").
Reads(apis.CreateContextValuesRequest{}).
Returns(200, "OK", apis.Context{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/context", "create")).
Writes(apis.Context{}).Do(meta, projParam, pipelineParam))
ws.Route(ws.GET("/{pipelineName}/contexts").To(p.listContextValues).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/contexts").To(n.listContextValues).
Doc("list pipeline context values").
Returns(200, "OK", apis.ListContextValueResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/context", "list")).
Writes(apis.ListContextValueResponse{}).Do(meta, projParam, pipelineParam))
ws.Route(ws.PUT("/{pipelineName}/contexts/{contextName}").To(p.updateContextValue).
ws.Route(ws.PUT("/{projectName}/pipelines/{pipelineName}/contexts/{contextName}").To(n.updateContextValue).
Doc("update pipeline context value").
Reads(apis.UpdateContextValuesRequest{}).
Returns(200, "OK", apis.Context{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/context", "update")).
Writes(apis.Context{}).Do(meta, projParam, pipelineParam, ctxParam))
ws.Route(ws.DELETE("/{pipelineName}/contexts/{contextName}").To(p.deleteContextValue).
ws.Route(ws.DELETE("/{projectName}/pipelines/{pipelineName}/contexts/{contextName}").To(n.deleteContextValue).
Doc("delete pipeline context value").
Returns(200, "OK", apis.ContextNameResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/context", "delete")).
Writes(apis.ContextNameResponse{}).Do(meta, projParam, pipelineParam, ctxParam))
ws.Route(ws.POST("/{pipelineName}/run").To(p.runPipeline).
ws.Route(ws.POST("/{projectName}/pipelines/{pipelineName}/run").To(n.runPipeline).
Doc("run pipeline").
Reads(apis.RunPipelineRequest{}).
Returns(200, "OK", apis.PipelineRunMeta{}).
Returns(200, "OK", apis.PipelineRun{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline", "run")).
Writes(apis.PipelineRunMeta{}).Do(meta, projParam, pipelineParam))
ws.Route(ws.GET("/{pipelineName}/runs").To(p.listPipelineRuns).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/runs").To(n.listPipelineRuns).
Doc("list pipeline runs").
Param(ws.QueryParameter("status", "query identifier of the status").DataType("string")).
Returns(200, "OK", apis.ListPipelineRunResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "list")).
Writes(apis.ListPipelineRunResponse{}).Do(meta, projParam, pipelineParam))
ws.Route(ws.POST("/{pipelineName}/runs/{runName}/stop").To(p.stopPipeline).
ws.Route(ws.POST("/{projectName}/pipelines/{pipelineName}/runs/{runName}/stop").To(n.stopPipeline).
Doc("stop pipeline run").
Returns(200, "OK", apis.PipelineRunMeta{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "stop")).
Writes(apis.PipelineRunMeta{}).Do(meta, projParam, pipelineParam, runParam))
ws.Route(ws.GET("/{pipelineName}/runs/{runName}").To(p.getPipelineRun).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/runs/{runName}").To(n.getPipelineRun).
Doc("get pipeline run").
Returns(200, "OK", apis.PipelineRunBase{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "get")).
Writes(apis.PipelineRunBase{}).Do(meta, projParam, pipelineParam, runParam))
ws.Route(ws.DELETE("/{pipelineName}/runs/{runName}").To(p.deletePipelineRun).
ws.Route(ws.DELETE("/{projectName}/pipelines/{pipelineName}/runs/{runName}").To(n.deletePipelineRun).
Doc("delete pipeline run").
Returns(200, "OK", apis.PipelineRunMeta{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "delete")).
Writes(apis.PipelineRunMeta{}).Do(meta, projParam, pipelineParam, runParam))
// get pipeline run status
ws.Route(ws.GET("/{pipelineName}/runs/{runName}/status").To(p.getPipelineRunStatus).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/runs/{runName}/status").To(n.getPipelineRunStatus).
Doc("get pipeline run status").
Returns(200, "OK", workflowv1alpha1.WorkflowRunStatus{}).
Returns(200, "OK", v1alpha1.WorkflowRunStatus{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(workflowv1alpha1.WorkflowRunStatus{}).Do(meta, projParam, pipelineParam, runParam))
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "detail")).
Writes(v1alpha1.WorkflowRunStatus{}).Do(meta, projParam, pipelineParam, runParam))
// get pipeline run log
ws.Route(ws.GET("/{pipelineName}/runs/{runName}/log").To(p.getPipelineRunLog).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/runs/{runName}/log").To(n.getPipelineRunLog).
Doc("get pipeline run log").
Param(ws.QueryParameter("step", "query by specific id").DataType("string")).
Param(ws.QueryParameter("step", "query by specific step name").DataType("string")).
Returns(200, "OK", apis.GetPipelineRunLogResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "detail")).
Writes(apis.GetPipelineRunLogResponse{}).Do(meta, projParam, pipelineParam, runParam))
// get pipeline run output
ws.Route(ws.GET("/{pipelineName}/runs/{runName}/output").To(p.getPipelineRunOutput).
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/runs/{runName}/output").To(n.getPipelineRunOutput).
Doc("get pipeline run output").
Param(ws.QueryParameter("step", "query by specific id").DataType("string")).
Param(ws.QueryParameter("step", "query by specific step name").DataType("string").Required(true)).
Returns(200, "OK", apis.GetPipelineRunOutputResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "detail")).
Writes(apis.GetPipelineRunOutputResponse{}).Do(meta, projParam, pipelineParam, runParam))
// get pipeline run input
ws.Route(ws.GET("/{projectName}/pipelines/{pipelineName}/runs/{runName}/input").To(n.getPipelineRunInput).
Doc("get pipeline run input").
Param(ws.QueryParameter("step", "query by specific step name").DataType("string").Required(true)).
Returns(200, "OK", apis.GetPipelineRunInputResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Filter(n.RBACService.CheckPerm("project/pipeline/pipelineRun", "detail")).
Writes(apis.GetPipelineRunInputResponse{}).Do(meta, projParam, pipelineParam, runParam))
ws.Filter(authCheckFilter)
}
// GetWebServiceRoute is the implementation of pipeline Interface
func (n *pipelineAPIInterface) GetWebServiceRoute() *restful.WebService {
tags := []string{"pipeline"}
meta := func(builder *restful.RouteBuilder) {
builder.Metadata(restfulspec.KeyOpenAPITags, tags)
}
ws := new(restful.WebService)
ws.Path(versionPrefix+"/pipelines").
Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML).
Doc("api for project manage")
ws.Route(ws.GET("").To(n.listPipelines).
Doc("list pipelines").
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
Param(ws.QueryParameter("projectName", "query pipelines within a project").DataType("string")).
Param(ws.QueryParameter("detailed", "query pipelines with detail").DataType("bool").DefaultValue("true")).
Returns(200, "OK", apis.ListPipelineResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.ListPipelineResponse{}).Do(meta))
ws.Filter(authCheckFilter)
return ws
}
type pipelineAPIInterface struct {
PipelineService service.PipelineService `inject:""`
}
// NewPipelineAPIInterface new pipeline manage APIInterface
func NewPipelineAPIInterface() Interface {
return &pipelineAPIInterface{}
}
func (p *pipelineAPIInterface) listPipelines(req *restful.Request, res *restful.Response) {
var projetNames []string
if req.QueryParameter("project") != "" {
projetNames = append(projetNames, req.QueryParameter("project"))
func (n *pipelineAPIInterface) listPipelines(req *restful.Request, res *restful.Response) {
var projectNames []string
if req.QueryParameter(Project) != "" {
projectNames = append(projectNames, req.QueryParameter(Project))
}
pipelines, err := p.PipelineService.ListPipelines(req.Request.Context(), apis.ListPipelineRequest{
Projects: projetNames,
_detailed := req.QueryParameter("detailed")
if _detailed == "" {
_detailed = "true"
}
detailed, err := strconv.ParseBool(_detailed)
if err != nil {
bcode.ReturnError(req, res, errors.Wrap(err, "invalid detailed param"))
}
pipelines, err := n.PipelineService.ListPipelines(req.Request.Context(), apis.ListPipelineRequest{
Projects: projectNames,
Query: req.QueryParameter("query"),
Detailed: detailed,
})
if err != nil {
log.Logger.Errorf("list pipeline failure %s", err.Error())
@@ -223,15 +266,18 @@ func (p *pipelineAPIInterface) listPipelines(req *restful.Request, res *restful.
}
}
func (p *pipelineAPIInterface) getPipeline(req *restful.Request, res *restful.Response) {
pipeline := req.Request.Context().Value(apis.CtxKeyPipeline).(apis.PipelineBase)
func (n *projectAPIInterface) getPipeline(req *restful.Request, res *restful.Response) {
pipeline, err := n.PipelineService.GetPipeline(req.Request.Context(), req.PathParameter(Pipeline), true)
if err != nil {
return
}
if err := res.WriteEntity(pipeline); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) createPipeline(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) createPipeline(req *restful.Request, res *restful.Response) {
var createReq apis.CreatePipelineRequest
if err := req.ReadEntity(&createReq); err != nil {
bcode.ReturnError(req, res, err)
@@ -241,19 +287,25 @@ func (p *pipelineAPIInterface) createPipeline(req *restful.Request, res *restful
bcode.ReturnError(req, res, err)
return
}
pipelineBase, err := p.PipelineService.CreatePipeline(req.Request.Context(), createReq)
pipelineBase, err := n.PipelineService.CreatePipeline(req.Request.Context(), createReq)
if err != nil {
log.Logger.Errorf("create pipeline failure %s", err.Error())
bcode.ReturnError(req, res, err)
return
}
_, err = n.ContextService.InitContext(req.Request.Context(), pipelineBase.Project.Name, pipelineBase.Name)
if err != nil {
log.Logger.Errorf("init pipeline context failure: %s", err.Error())
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(pipelineBase); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) updatePipeline(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) updatePipeline(req *restful.Request, res *restful.Response) {
var updateReq apis.UpdatePipelineRequest
if err := req.ReadEntity(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
@@ -263,8 +315,8 @@ func (p *pipelineAPIInterface) updatePipeline(req *restful.Request, res *restful
bcode.ReturnError(req, res, err)
return
}
base := req.Request.Context().Value(apis.CtxKeyPipeline).(apis.PipelineBase)
pipelineBase, err := p.PipelineService.UpdatePipeline(req.Request.Context(), base.Name, base.Project, updateReq)
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
pipelineBase, err := n.PipelineService.UpdatePipeline(req.Request.Context(), pipeline.Name, updateReq)
if err != nil {
log.Logger.Errorf("update pipeline failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -276,43 +328,43 @@ func (p *pipelineAPIInterface) updatePipeline(req *restful.Request, res *restful
}
}
func (p *pipelineAPIInterface) deletePipeline(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) deletePipeline(req *restful.Request, res *restful.Response) {
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
err := p.PipelineService.DeletePipeline(req.Request.Context(), pipeline)
err := n.PipelineService.DeletePipeline(req.Request.Context(), pipeline)
if err != nil {
log.Logger.Errorf("delete pipeline failure %s", err.Error())
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(pipeline.PipelineMeta); err != nil {
if err := res.WriteEntity(apis.EmptyResponse{}); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) runPipeline(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) runPipeline(req *restful.Request, res *restful.Response) {
var runReq apis.RunPipelineRequest
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
if err := req.ReadEntity(runReq); err != nil {
if err := req.ReadEntity(&runReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
err := p.PipelineService.RunPipeline(req.Request.Context(), pipeline, runReq)
run, err := n.PipelineService.RunPipeline(req.Request.Context(), pipeline, runReq)
if err != nil {
log.Logger.Errorf("run pipeline failure %s", err.Error())
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(pipeline.PipelineMeta); err != nil {
if err := res.WriteEntity(run); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) stopPipeline(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(apis.PipelineRun)
err := p.PipelineRunService.StopPipelineRun(req.Request.Context(), pipelineRun.PipelineRunBase)
func (n *projectAPIInterface) stopPipeline(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
err := n.PipelineRunService.StopPipelineRun(req.Request.Context(), pipelineRun.PipelineRunBase)
if err != nil {
log.Logger.Errorf("stop pipeline failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -324,9 +376,9 @@ func (p *pipelineAPIInterface) stopPipeline(req *restful.Request, res *restful.R
}
}
func (p *pipelineAPIInterface) listPipelineRuns(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) listPipelineRuns(req *restful.Request, res *restful.Response) {
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
pipelineRuns, err := p.PipelineRunService.ListPipelineRuns(req.Request.Context(), pipeline)
pipelineRuns, err := n.PipelineRunService.ListPipelineRuns(req.Request.Context(), pipeline)
if err != nil {
log.Logger.Errorf("list pipeline runs failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -338,33 +390,65 @@ func (p *pipelineAPIInterface) listPipelineRuns(req *restful.Request, res *restf
}
}
func (p *pipelineAPIInterface) getPipelineRun(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(apis.PipelineRun)
func (n *projectAPIInterface) getPipelineRun(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
if err := res.WriteEntity(pipelineRun.PipelineRunBase); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) getPipelineRunStatus(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(apis.PipelineRun)
func (n *projectAPIInterface) getPipelineRunStatus(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
if err := res.WriteEntity(pipelineRun.Status); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) getPipelineRunLog(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) getPipelineRunLog(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
logs, err := n.PipelineRunService.GetPipelineRunLog(req.Request.Context(), *pipelineRun, req.QueryParameter("step"))
if err != nil {
log.Logger.Errorf("get pipeline run log failure %s", err.Error())
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(logs); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) getPipelineRunOutput(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) getPipelineRunOutput(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
output, err := n.PipelineRunService.GetPipelineRunOutput(req.Request.Context(), *pipelineRun, req.QueryParameter("step"))
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(output); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (p *pipelineAPIInterface) deletePipelineRun(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(apis.PipelineRun)
err := p.PipelineRunService.DeletePipelineRun(req.Request.Context(), pipelineRun.PipelineRunMeta)
func (n *projectAPIInterface) getPipelineRunInput(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
input, err := n.PipelineRunService.GetPipelineRunInput(req.Request.Context(), *pipelineRun, req.QueryParameter("step"))
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(input); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (n *projectAPIInterface) deletePipelineRun(req *restful.Request, res *restful.Response) {
pipelineRun := req.Request.Context().Value(&apis.CtxKeyPipelineRun).(*apis.PipelineRun)
err := n.PipelineRunService.DeletePipelineRun(req.Request.Context(), pipelineRun.PipelineRunMeta)
if err != nil {
log.Logger.Errorf("delete pipeline run failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -376,11 +460,11 @@ func (p *pipelineAPIInterface) deletePipelineRun(req *restful.Request, res *rest
}
}
func (p *pipelineAPIInterface) listContextValues(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) listContextValues(req *restful.Request, res *restful.Response) {
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
contextValues, err := p.ContextService.ListContexts(req.Request.Context(), pipeline.Project, pipeline.Name)
contextValues, err := n.ContextService.ListContexts(req.Request.Context(), pipeline.Project.Name, pipeline.Name)
if err != nil {
log.Logger.Errorf("list context values failure %s", err.Error())
log.Logger.Errorf("list context values failure: %s", err.Error())
bcode.ReturnError(req, res, err)
return
}
@@ -390,7 +474,7 @@ func (p *pipelineAPIInterface) listContextValues(req *restful.Request, res *rest
}
}
func (p *pipelineAPIInterface) createContextValue(req *restful.Request, res *restful.Response) {
func (n *projectAPIInterface) createContextValue(req *restful.Request, res *restful.Response) {
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
var createReq apis.CreateContextValuesRequest
if err := req.ReadEntity(&createReq); err != nil {
@@ -403,7 +487,7 @@ func (p *pipelineAPIInterface) createContextValue(req *restful.Request, res *res
}
pipelineCtx := apis.Context(createReq)
_, err := p.ContextService.CreateContext(req.Request.Context(), pipeline.Project, pipeline.Name, pipelineCtx)
_, err := n.ContextService.CreateContext(req.Request.Context(), pipeline.Project.Name, pipeline.Name, pipelineCtx)
if err != nil {
log.Logger.Errorf("create context failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -415,8 +499,8 @@ func (p *pipelineAPIInterface) createContextValue(req *restful.Request, res *res
}
}
func (p *pipelineAPIInterface) updateContextValue(req *restful.Request, res *restful.Response) {
plCtx := req.Request.Context().Value(&apis.CtxKeyPipelineContex).(apis.Context)
func (n *projectAPIInterface) updateContextValue(req *restful.Request, res *restful.Response) {
plCtx := req.Request.Context().Value(&apis.CtxKeyPipelineContext).(apis.Context)
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
var updateReq apis.UpdateContextValuesRequest
if err := req.ReadEntity(&updateReq); err != nil {
@@ -428,7 +512,7 @@ func (p *pipelineAPIInterface) updateContextValue(req *restful.Request, res *res
return
}
pipelineCtx := apis.Context{Name: plCtx.Name, Values: updateReq.Values}
_, err := p.ContextService.UpdateContext(req.Request.Context(), pipeline.Project, pipeline.Name, pipelineCtx)
_, err := n.ContextService.UpdateContext(req.Request.Context(), pipeline.Project.Name, pipeline.Name, pipelineCtx)
if err != nil {
log.Logger.Errorf("update context failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -440,10 +524,10 @@ func (p *pipelineAPIInterface) updateContextValue(req *restful.Request, res *res
}
}
func (p *pipelineAPIInterface) deleteContextValue(req *restful.Request, res *restful.Response) {
plCtx := req.Request.Context().Value(&apis.CtxKeyPipelineContex).(apis.Context)
func (n *projectAPIInterface) deleteContextValue(req *restful.Request, res *restful.Response) {
plCtx := req.Request.Context().Value(&apis.CtxKeyPipelineContext).(apis.Context)
pipeline := req.Request.Context().Value(&apis.CtxKeyPipeline).(apis.PipelineBase)
err := p.ContextService.DeleteContext(req.Request.Context(), pipeline.Project, pipeline.Name, plCtx.Name)
err := n.ContextService.DeleteContext(req.Request.Context(), pipeline.Project.Name, pipeline.Name, plCtx.Name)
if err != nil {
log.Logger.Errorf("delete context failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -455,8 +539,18 @@ func (p *pipelineAPIInterface) deleteContextValue(req *restful.Request, res *res
}
}
func (p *pipelineAPIInterface) pipelineCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
pipeline, err := p.PipelineService.GetPipeline(req.Request.Context(), req.PathParameter("pipelineName"), req.QueryParameter("projectName"))
func (n *projectAPIInterface) projectCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
project, err := n.ProjectService.GetProject(req.Request.Context(), req.PathParameter(Project))
if err != nil {
bcode.ReturnError(req, res, err)
return
}
req.Request = req.Request.WithContext(context.WithValue(req.Request.Context(), &apis.CtxKeyProject, project))
chain.ProcessFilter(req, res)
}
func (n *projectAPIInterface) pipelineCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
pipeline, err := n.PipelineService.GetPipeline(req.Request.Context(), req.PathParameter(Pipeline), false)
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -465,8 +559,8 @@ func (p *pipelineAPIInterface) pipelineCheckFilter(req *restful.Request, res *re
chain.ProcessFilter(req, res)
}
func (p *pipelineAPIInterface) pipelineContextCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
contexts, err := p.ContextService.ListContexts(req.Request.Context(), req.PathParameter("pipelineName"), req.QueryParameter("projectName"))
func (n *projectAPIInterface) pipelineContextCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
contexts, err := n.ContextService.ListContexts(req.Request.Context(), req.PathParameter(Project), req.PathParameter(Pipeline))
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -477,20 +571,22 @@ func (p *pipelineAPIInterface) pipelineContextCheckFilter(req *restful.Request,
bcode.ReturnError(req, res, bcode.ErrContextNotFound)
return
}
req.Request = req.Request.WithContext(context.WithValue(req.Request.Context(), &apis.CtxKeyPipelineContex, apis.Context{
req.Request = req.Request.WithContext(context.WithValue(req.Request.Context(), &apis.CtxKeyPipelineContext, apis.Context{
Name: contextName,
Values: contextValue,
}))
chain.ProcessFilter(req, res)
}
func (p *pipelineAPIInterface) pipelineRunCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
func (n *projectAPIInterface) pipelineRunCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
meta := apis.PipelineRunMeta{
PipelineName: req.PathParameter(string(Pipeline)),
Project: req.QueryParameter(string(Project)),
PipelineRunName: req.PathParameter(string(PipelineRun)),
PipelineName: req.PathParameter(Pipeline),
Project: apis.NameAlias{
Name: req.PathParameter(Project),
},
PipelineRunName: req.PathParameter(PipelineRun),
}
run, err := p.PipelineRunService.GetPipelineRun(req.Request.Context(), meta)
run, err := n.PipelineRunService.GetPipelineRun(req.Request.Context(), meta)
if err != nil {
bcode.ReturnError(req, res, err)
return

View File

@@ -29,10 +29,14 @@ import (
)
type projectAPIInterface struct {
RbacService service.RBACService `inject:""`
ProjectService service.ProjectService `inject:""`
TargetService service.TargetService `inject:""`
ConfigService service.ConfigService `inject:""`
RbacService service.RBACService `inject:""`
ProjectService service.ProjectService `inject:""`
TargetService service.TargetService `inject:""`
ConfigService service.ConfigService `inject:""`
PipelineService service.PipelineService `inject:""`
PipelineRunService service.PipelineRunService `inject:""`
ContextService service.ContextService `inject:""`
RBACService service.RBACService `inject:""`
}
// NewProjectAPIInterface new project APIInterface
@@ -305,6 +309,7 @@ func (n *projectAPIInterface) GetWebServiceRoute() *restful.WebService {
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.ListTerraformProviderResponse{}))
initPipelineRoutes(ws, n)
ws.Filter(authCheckFilter)
return ws
}

View File

@@ -38,6 +38,9 @@ const KubeVelaProjectReadGroupPrefix = "kubevela:project-ro:"
// KubeVelaAdminGroupPrefix the prefix kubevela admin
const KubeVelaAdminGroupPrefix = "kubevela:admin:"
// TemplateReaderGroup This group includes the permission that read the ConfigMap in the vela-system namespace.
const TemplateReaderGroup = "template-reader"
// ContextWithUserInfo extract user from context (parse username and project) for impersonation
func ContextWithUserInfo(ctx context.Context) context.Context {
if !features.APIServerFeatureGate.Enabled(features.APIServerEnableImpersonation) {

View File

@@ -33,3 +33,6 @@ var ErrDeleteEnvButAppExist = NewBcode(400, 11005, "env can't be deleted as app
// ErrEnvTargetConflict in one project, one target can only belong to one env
var ErrEnvTargetConflict = NewBcode(400, 11006, "in one project, one target can only belong to one env.")
// ErrEnvTargetNotAllowDelete means can not remove existing targets from this environment, because there are applications deployed.
var ErrEnvTargetNotAllowDelete = NewBcode(400, 11007, "target can not be deleted, because there are applications deployed.")

View File

@@ -21,4 +21,22 @@ var (
ErrContextNotFound = NewBcode(400, 17001, "pipeline context is not found")
// ErrContextAlreadyExist means the certain context already exists
ErrContextAlreadyExist = NewBcode(400, 17002, "pipeline context of pipeline already exist")
// ErrGetPipelineInfo means failed to get pipeline info
ErrGetPipelineInfo = NewBcode(400, 17003, "get pipeline info failed")
// ErrPipelineNotExist means specific pipeline not found
ErrPipelineNotExist = NewBcode(404, 17004, "failed to find log pods")
// ErrGetPodsLogs means failed to get pods logs
ErrGetPodsLogs = NewBcode(500, 17006, "failed to get pods logs")
// ErrReadSourceLog means failed to read source log
ErrReadSourceLog = NewBcode(500, 17007, "failed to read log from URL source")
// ErrGetContextBackendData means failed to get context backend data
ErrGetContextBackendData = NewBcode(500, 17008, "failed to get context backend data")
// ErrNoSteps means pipeline doesn't have a step
ErrNoSteps = NewBcode(400, 17009, "pipeline step number is zero")
// ErrPipelineExist means the pipeline is exist
ErrPipelineExist = NewBcode(400, 17010, "the pipeline is exist")
// ErrPipelineRunFinished means pipeline run is finished
ErrPipelineRunFinished = NewBcode(400, 17011, "pipeline run is finished")
// ErrWrongMode means the pipeline run mode is wrong
ErrWrongMode = NewBcode(400, 17012, "wrong pipeline run mode, only \"DAG\" and \"StepByStep\" are supported")
)

View File

@@ -329,7 +329,7 @@ func (af *Appfile) generateAndFilterCommonLabels(compName string) map[string]str
oam.LabelAppComponent: compName,
}
// merge application's all labels
finalLabels := util.MergeMapOverrideWithDst(Labels, af.AppLabels)
finalLabels := util.MergeMapOverrideWithDst(af.AppLabels, Labels)
filterLabels, ok := af.AppAnnotations[oam.AnnotationFilterLabelKeys]
if ok {
filter(finalLabels, strings.Split(filterLabels, ","))

View File

@@ -452,15 +452,24 @@ func (p *Parser) loadWorkflowToAppfile(ctx context.Context, af *Appfile) error {
Steps: workflowv1alpha1.WorkflowModeDAG,
SubSteps: workflowv1alpha1.WorkflowModeDAG,
}
if wfSpec := af.app.Spec.Workflow; wfSpec != nil && len(wfSpec.Steps) > 0 {
if wfSpec := af.app.Spec.Workflow; wfSpec != nil {
app := af.app
mode := wfSpec.Mode
if wfSpec.Ref != "" && mode == nil {
wf := &workflowv1alpha1.Workflow{}
if err := af.WorkflowClient(p.client).Get(ctx, ktypes.NamespacedName{Namespace: af.app.Namespace, Name: app.Spec.Workflow.Ref}, wf); err != nil {
return err
}
mode = wf.Mode
}
af.WorkflowSteps = wfSpec.Steps
af.WorkflowMode.Steps = workflowv1alpha1.WorkflowModeStep
if wfSpec.Mode != nil {
if wfSpec.Mode.Steps != "" {
af.WorkflowMode.Steps = wfSpec.Mode.Steps
if mode != nil {
if mode.Steps != "" {
af.WorkflowMode.Steps = mode.Steps
}
if wfSpec.Mode.SubSteps != "" {
af.WorkflowMode.SubSteps = wfSpec.Mode.SubSteps
if mode.SubSteps != "" {
af.WorkflowMode.SubSteps = mode.SubSteps
}
}
}

View File

@@ -338,7 +338,7 @@ func (a *ApplicationPrivilege) GetRoles() []client.Object {
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{"core.oam.dev"},
Resources: []string{"applications", "policies", "workflows"},
Resources: []string{"applications", "policies", "workflows", "workflowruns"},
Verbs: verbs,
},
},

Some files were not shown because too many files have changed in this diff Show More