Compare commits

..

47 Commits

Author SHA1 Message Date
Tianxin Dong
4209080adc Fix: add volume bottom check in resource topology rule (#5835)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-04-13 10:56:46 +08:00
github-actions[bot]
61348b9d45 Fix: use step id to filter the log data and fix the regex (#5813)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 308093159f)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-04-07 10:40:41 +08:00
github-actions[bot]
aa5e825683 Fix: fix step id to name in workflow logs (#5807)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 6b1f57e877)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-04-06 14:59:44 +08:00
github-actions[bot]
95d04c370d Fix: vela top cannot switch the theme (#5756)
Signed-off-by: howieyuen <howieyuen@outlook.com>
(cherry picked from commit cb1c33bed1)

Co-authored-by: howieyuen <howieyuen@outlook.com>
2023-03-28 15:38:55 +08:00
github-actions[bot]
a583f66b0d [Backport release-1.7] Fix: gateway message is wrong (#5751)
Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-03-28 09:30:29 +08:00
github-actions[bot]
7ae1aff648 [Backport release-1.7] Fix: fix vela-minimal helm chart unrecognised options (#5729)
* fix(vela-minimal): fix unrecognised options

Signed-off-by: florent.madiot.e <florent.madiot.e@thalesdigital.io>
(cherry picked from commit c9394a18a6)

* Fix(vela-minimal): make reviewable

Signed-off-by: florent.madiot.e <florent.madiot.e@thalesdigital.io>
(cherry picked from commit f4f7f96cc8)

---------

Co-authored-by: florent.madiot.e <florent.madiot.e@thalesdigital.io>
2023-03-24 11:29:34 +08:00
github-actions[bot]
0ff40d75e5 Fix: use logs to show errs intead of return in adopt all (#5712)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit f0e3c33be2)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-21 13:40:54 +08:00
github-actions[bot]
3d410fed5f Fix: system crd validation hook should not always use the default vela system (#5711)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit b4b0f99f41)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-03-21 10:18:28 +08:00
Tianxin Dong
f8285df49d Feat: add adopt all command (#5690) (#5696) (#5697)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-20 13:40:04 +08:00
Tianxin Dong
e4cd1ffd1d Feat: add adopt all command (#5690) (#5696)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-17 15:51:39 +08:00
Tianxin Dong
592f8b8e8f Fix: stores workflow status in revison if it is restarted (#5604) (#5673)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-14 22:14:41 +08:00
github-actions[bot]
94c215c361 [Backport release-1.7] Fix: add addon registry (#5660)
* Fix: add addon registry

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit 74d3ad2c88)

* Fix: modify edit errors

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit 6ae828cb04)

---------

Co-authored-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
2023-03-13 14:15:13 +08:00
github-actions[bot]
1723a1795d Fix: make read-only object not found error more clear (#5619)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 7bc97f812b)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-03-06 13:20:20 +08:00
github-actions[bot]
0861498ab8 Fix: replication example componentdefinition miss workload field for webhook validation (#5618)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit c8709a2c13)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-03-06 13:18:49 +08:00
github-actions[bot]
52c9a8f0a3 [Backport release-1.7] Fix: length of name should be less than 32 (#5599)
* Fix: length of name should be less than 32

Signed-off-by: caiqi <caiqi_yewu@cmss.chinamobile.com>
(cherry picked from commit c06347c923)

* Fix: length of name should be less than 32

Signed-off-by: caiqi <caiqi_yewu@cmss.chinamobile.com>
(cherry picked from commit b18bca6f92)

---------

Co-authored-by: caiqi <caiqi_yewu@cmss.chinamobile.com>
2023-03-03 16:56:38 +08:00
github-actions[bot]
c7f337fd35 [Backport release-1.7] Feat: update version of terraform-controller to v0.7.10. (#5591)
Co-authored-by: raradhakrishnan <raradhakrishnan@guidewire.com>
2023-03-01 11:05:22 +08:00
github-actions[bot]
9dca76e0de [Backport release-1.7] Fix: the array type cannot be converted to interface type (#5588)
* Fix: the array type cannot be converted to interface type

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

* Fix: the array type cannot be converted to interface type

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

* Fix: the array type cannot be converted to interface type

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

* Fix: the array type cannot be converted to interface type

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

---------

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2023-03-01 09:49:19 +08:00
github-actions[bot]
348f540a82 Fix: The resource topology fails to display the pods under the job (#5566) (#5573)
Signed-off-by: hanzhaoyang <hanzhaoyang@jd.com>
(cherry picked from commit c0327918fb)

Co-authored-by: hanzhaoyang <hanzhaoyang@jd.com>
2023-02-27 16:29:38 +08:00
github-actions[bot]
1c2df10299 Fix: swagger DateType (#5570)
Signed-off-by: yueyongyue <yueyongyue@sina.cn>
(cherry picked from commit a4a4d64729)

Co-authored-by: yueyongyue <yueyongyue@sina.cn>
2023-02-27 09:53:52 +08:00
github-actions[bot]
918ed9727b [Backport release-1.7] Fix: delete the secret of the cluster (#5517)
* Fix: delete the secret of the cluster

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit ec466ab67e)

* Fix: add test

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit 63c44fdc39)

* Fix: modify error

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit e580597367)

* Fix: solve check-diff

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit c2316e10e8)

* Fix: modify test

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit afca7e6027)

---------

Co-authored-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
2023-02-16 14:04:41 +08:00
github-actions[bot]
fa78cb7632 [Backport release-1.7] Fix: removes default parameter name for terraform provider (#5516)
* removes default name for terraform provider

Signed-off-by: afzalbin64 <afzal442@gmail.com>
(cherry picked from commit 92e7bf8263)

* fixes minor typos

Signed-off-by: afzalbin64 <afzal442@gmail.com>

undo the changes to typo

fixes minor typos in go_test files

updates config_test to support name as required param

(cherry picked from commit 51c2650a95)

---------

Co-authored-by: afzalbin64 <afzal442@gmail.com>
2023-02-16 14:02:10 +08:00
github-actions[bot]
f3cdbcf203 [Backport release-1.7] Feat: The vela-apiserver supports displaying chart values stored in the OCI registry (#5509)
* support helm chart values

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

rebase

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

no lint

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

fix lint error

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

add test and deprecated API

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

fix url bug

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

fix tests panic

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

fix tests

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

* fix golint

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

* return values.yaml

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

* fix test

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

* fix return values

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

* add multiple valeus yaml in

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

* add old interface back

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

* fix golint

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

fix test

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

---------

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2023-02-15 14:00:16 +08:00
github-actions[bot]
7bd2cf4dbc [Backport release-1.7] Fix: read-only definition in cue spec (#5508)
* Fix: ref-object and take-over definition in cue spec

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

* rollback ref-objects

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

---------

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-15 13:59:48 +08:00
github-actions[bot]
969babdd9e Fix: apply-terraform-provider and container-image definition (#5486)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 978feccf91)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-13 11:21:52 +08:00
github-actions[bot]
94c46a179b Fix: use correct helm value when setting apprev compression (#5478)
Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com>
(cherry picked from commit 17c36206bc)

Co-authored-by: Charlie Chiang <charlie_c_0129@outlook.com>
2023-02-10 19:18:14 +08:00
Tianxin Dong
bec288c6b4 Chore: update cue version to v0.5.0-beta.5 to fix certain bugs in the old version (#5475)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-02-10 19:17:51 +08:00
github-actions[bot]
9a44be9788 Fix: pod view invalid cue for special pod output (#5474)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit ece0396425)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-10 13:07:21 +08:00
github-actions[bot]
9c7f4b7e03 Feat: enhance expose trait and adopt (#5473)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit a05e4c8643)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-10 11:30:20 +08:00
github-actions[bot]
539f1ed02b Fix: expose trait load balance cue check bug (#5461)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 9dccfcea1e)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-08 23:25:11 +08:00
github-actions[bot]
9e95122387 Chore: fix krew release with new binary format for .exe (#5462)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit a4ea6ccb04)

Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2023-02-08 23:24:37 +08:00
github-actions[bot]
f49f11dd72 Fix: suppress klog logs output for vela top (#5452)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 55662b645a)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-08 16:26:44 +08:00
github-actions[bot]
191d9038f1 [Backport release-1.7] Fix: use get before create or update (#5450)
* Fix: use get before create or update

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 93c1881663)

* Fix: ignore resource not found error when manage privileges for target

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit dd4864c6d1)

---------

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-08 14:50:38 +08:00
github-actions[bot]
e10e43b6c8 [Backport release-1.7] Fix: simplify notification parameters (#5446)
* Fix: simplify notification parameters

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

* remove close

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

* format

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

---------

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-08 14:05:13 +08:00
github-actions[bot]
b9cc523267 [Backport release-1.7] Fix: Add confirmation prompt for vela adopt --apply with existing app name (#5419)
* Add confirmation prompt for vela adopt --apply with existing app name

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 5278e1b350)

* Added changes according to the review

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 0a437e336f)

* Fixed Userinput and used loadremoteApplication

Signed-off-by: Karanjot Singh <drquark@duck.com>

minor fixes

Signed-off-by: Karanjot Singh <drquark@duck.com>

used loadRemoteApplication

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 4e92eaf73e)

* Used f.Client().Get method

Signed-off-by: Karanjot Singh <drquark@duck.com>

minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 96a2ae8fb7)

* Changed bool to False

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 17a1131b90)

---------

Co-authored-by: Karanjot Singh <drquark@duck.com>
2023-02-03 18:03:42 +08:00
github-actions[bot]
7f1743ef58 [Backport release-1.7] Fix: sync project from app crd to velaux (#5410)
* Fix: sync project from app crd to velaux

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

* Fix: sync project from app crd to velaux

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

* Fix: sync project from app crd to velaux

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

* Fix: sync project from app crd to velaux

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

* Fix: sync project from app crd to velaux

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

* Fix: sync project from app crd to velaux

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

---------

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2023-02-02 15:31:25 +08:00
github-actions[bot]
dd39c38cf1 fix bugs of specified addonName (#5407)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 3a9df79b3a)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2023-02-01 16:44:30 +08:00
github-actions[bot]
0851454c6f Fix: ignore validation webhook for ref-objects typed component (#5406)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 0fb1ab497b)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-01 16:10:16 +08:00
github-actions[bot]
cd3577db53 Fix: skip last-applied-configuration error for threewaymergepatch (#5405)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 6bf79461d4)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-01 16:00:44 +08:00
github-actions[bot]
d578adfe6e Fix: longer releaser timeout (#5400)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 4ca1acdc22)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-01 14:01:07 +08:00
github-actions[bot]
4b88cd201e [Backport release-1.7] Fix: replace homemade release script with goreleaser (#5398)
* Replace homemade release script with goreleaser

refactor release.yml

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

* wrap files in a directory

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

---------

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-01-31 20:55:06 +08:00
github-actions[bot]
492e7d7f0d [Backport release-1.7] Fix: use the namespace specified in the resource if -n is not s… (#5396)
* fix #5368, use the namespace specified in the resource if -n is not specified

Signed-off-by: Basuotian <basuoluomiu@gmail.com>
(cherry picked from commit 47c9b4457b)

* add default namespace for the case missing namespace in resourceRef

Signed-off-by: Basuotian <basuoluomiu@gmail.com>
(cherry picked from commit 3ae0657796)

* add test case

Signed-off-by: Basuotian <basuoluomiu@gmail.com>
(cherry picked from commit 4ba5eb88eb)

---------

Co-authored-by: Basuotian <basuoluomiu@gmail.com>
2023-01-31 20:16:18 +08:00
Jianbo Sun
0742ca9ee5 Fix: aligin config create to be managed by apps with Dispatch function (#5384) (#5394)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2023-01-31 18:04:36 +08:00
github-actions[bot]
1cf4ae3fc3 [Backport release-1.7] Feat: add the updating the application trigger API (#5395)
* Feat: add the updating the application trigger API

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

* Fix: change the test case

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

* Fix: imported more than once

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

---------

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-01-31 17:14:03 +08:00
qiaozp
444d315143 Fix: rework on apisrever e2e test covergae (#5390)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-01-31 15:04:24 +08:00
github-actions[bot]
2e3a89f6b1 Chore: update workflow version to fix panic (#5386)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 4ae1fe044e)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-01-31 10:57:40 +08:00
github-actions[bot]
d94293ac59 Fix: failed to create the record when rollbacking the application (#5381)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 57d85ecb7c)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-01-30 20:51:04 +08:00
github-actions[bot]
cc604cfadb Feat: upgrade cluster gateway to 1.7.0 (#5356)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 3245ea148c)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-01-19 11:21:38 +08:00
94 changed files with 2195 additions and 646 deletions

View File

@@ -186,7 +186,7 @@ jobs:
uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: /tmp/e2e_apiserver_test.out
files: /tmp/e2e-profile.out, /tmp/e2e_apiserver_test.out
flags: apiserver-e2etests
name: codecov-umbrella

View File

@@ -7,7 +7,6 @@ on:
workflow_dispatch: { }
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUCKET: ${{ secrets.CLI_OSS_BUCKET }}
ENDPOINT: ${{ secrets.CLI_OSS_ENDPOINT }}
ACCESS_KEY: ${{ secrets.CLI_OSS_ACCESS_KEY }}
@@ -28,105 +27,36 @@ jobs:
repository-projects: read
statuses: read
runs-on: ubuntu-latest
name: build
strategy:
matrix:
TARGETS: [ linux/amd64, darwin/amd64, windows/amd64, linux/arm64, darwin/arm64 ]
env:
VELA_VERSION_KEY: github.com/oam-dev/kubevela/version.VelaVersion
VELA_GITVERSION_KEY: github.com/oam-dev/kubevela/version.GitRevision
GO_BUILD_ENV: GO111MODULE=on CGO_ENABLED=0
DIST_DIRS: find * -type d -exec
name: goreleaser
steps:
- name: Checkout
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
with:
fetch-depth: 0
- run: git fetch --force --tags
- name: Set up Go
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
with:
go-version: 1.19
- name: Get release
id: get_release
uses: bruceadams/get-release@74c3d60f5a28f358ccf241a00c9021ea16f0569f # v1.3.2
cache: true
- uses: goreleaser/goreleaser-action@9754a253a8673b0ea869c2e863b4e975497efd0c # v4.1.1
with:
distribution: goreleaser
version: 1.14.1
args: release --rm-dist --timeout 60m
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Since goreleaser haven't supported aliyun OSS, we need to upload the release manually
- name: Get version
run: echo "VELA_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
- name: Get matrix
id: get_matrix
run: |
TARGETS=${{matrix.TARGETS}}
echo "OS=${TARGETS%/*}" >> $GITHUB_OUTPUT
echo "ARCH=${TARGETS#*/}" >> $GITHUB_OUTPUT
- name: Get ldflags
id: get_ldflags
run: |
LDFLAGS="-s -w -X ${{ env.VELA_VERSION_KEY }}=${{ env.VELA_VERSION }} -X ${{ env.VELA_GITVERSION_KEY }}=git-$(git rev-parse --short HEAD)"
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_ENV
- name: Build
run: |
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
go build -ldflags "${{ env.LDFLAGS }}" \
-o _bin/vela/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/vela -v \
./references/cmd/cli/main.go
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
go build -ldflags "${{ env.LDFLAGS }}" \
-o _bin/kubectl-vela/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/kubectl-vela -v \
./cmd/plugin/main.go
- name: Compress
run: |
echo "\n## Release Info\nVERSION: ${{ env.VELA_VERSION }}" >> README.md && \
echo "GIT_COMMIT: ${GITHUB_SHA}\n" >> README.md && \
cd _bin/vela && \
${{ env.DIST_DIRS }} cp ../../LICENSE {} \; && \
${{ env.DIST_DIRS }} cp ../../README.md {} \; && \
${{ env.DIST_DIRS }} tar -zcf vela-{}.tar.gz {} \; && \
${{ env.DIST_DIRS }} zip -r vela-{}.zip {} \; && \
cd ../kubectl-vela && \
${{ env.DIST_DIRS }} cp ../../LICENSE {} \; && \
${{ env.DIST_DIRS }} cp ../../README.md {} \; && \
${{ env.DIST_DIRS }} tar -zcf kubectl-vela-{}.tar.gz {} \; && \
${{ env.DIST_DIRS }} zip -r kubectl-vela-{}.zip {} \; && \
cd .. && \
sha256sum vela/vela-* kubectl-vela/kubectl-vela-* >> sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt \
- name: Upload Vela tar.gz
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
with:
release_id: ${{ steps.get_release.outputs.id }}
asset_path: ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
asset_name: vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
- name: Upload Vela zip
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
with:
release_id: ${{ steps.get_release.outputs.id }}
asset_path: ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
asset_name: vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
- name: Upload Kubectl-Vela tar.gz
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
with:
release_id: ${{ steps.get_release.outputs.id }}
asset_path: ./_bin/kubectl-vela/kubectl-vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
asset_name: kubectl-vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
- name: Upload Kubectl-Vela zip
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
with:
release_id: ${{ steps.get_release.outputs.id }}
asset_path: ./_bin/kubectl-vela/kubectl-vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
asset_name: kubectl-vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
- name: Post sha256
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1
with:
name: sha256sums
path: ./_bin/sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt
retention-days: 1
- name: clear the asset
run: |
rm -rf ./_bin/vela/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}
mv ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz ./_bin/vela/vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
mv ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip ./_bin/vela/vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
- name: Install ossutil
run: wget http://gosspublic.alicdn.com/ossutil/1.7.0/ossutil64 && chmod +x ossutil64 && mv ossutil64 ossutil
- name: Configure Alibaba Cloud OSSUTIL
run: ./ossutil --config-file .ossutilconfig config -i ${ACCESS_KEY} -k ${ACCESS_KEY_SECRET} -e ${ENDPOINT} -c .ossutilconfig
run: ./ossutil --config-file .ossutilconfig config -i ${ACCESS_KEY} -k ${ACCESS_KEY_SECRET} -e ${ENDPOINT}
- name: split files to be upload
run: mkdir -p ./dist/files_upload && mv ./dist/*.tar.gz ./dist/files_upload && mv ./dist/*.zip ./dist/files_upload
- name: sync local to cloud
run: ./ossutil --config-file .ossutilconfig sync ./_bin/vela oss://$BUCKET/binary/vela/${{ env.VELA_VERSION }}
run: ./ossutil --config-file .ossutilconfig sync ./dist/files_upload oss://$BUCKET/binary/vela/${{ env.VELA_VERSION }}
- name: sync the latest version file
if: ${{ !contains(env.VELA_VERSION,'alpha') && !contains(env.VELA_VERSION,'beta') }}
run: |
@@ -137,7 +67,6 @@ jobs:
verlte ${{ env.VELA_VERSION }} $LATEST_VERSION && echo "${{ env.VELA_VERSION }} <= $LATEST_VERSION, skip update" && exit 0
echo ${{ env.VELA_VERSION }} > ./latest_version
./ossutil --config-file .ossutilconfig cp -u ./latest_version oss://$BUCKET/binary/vela/latest_version
upload-plugin-homebrew:
permissions:
contents: write
@@ -154,34 +83,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
- name: Get release
id: get_release
uses: bruceadams/get-release@74c3d60f5a28f358ccf241a00c9021ea16f0569f # v1.3.2
- name: Download sha256sums
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1
with:
name: sha256sums
path: cli-artifacts
- name: Display structure of downloaded files
run: ls -R
working-directory: cli-artifacts
- name: Get version
run: echo "VELA_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
- shell: bash
working-directory: cli-artifacts
run: |
for file in *
do
sed -i "s/\/vela/-${{ env.VELA_VERSION }}/g" ${file}
sed -i "s/\/kubectl-vela/-${{ env.VELA_VERSION }}/g" ${file}
cat ${file} >> sha256sums.txt
done
- name: Upload Checksums
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
with:
release_id: ${{ steps.get_release.outputs.id }}
asset_path: cli-artifacts/sha256sums.txt
asset_name: sha256sums.txt
- name: Update kubectl plugin version in krew-index
uses: rajatjindal/krew-release-bot@3320c0b546b5d2320613c46762bd3f73e2801bdc # v0.0.38
- name: Update Homebrew formula

2
.gitignore vendored
View File

@@ -53,3 +53,5 @@ git-page/
# e2e rollout runtime image build
runtime/rollout/e2e/tmp
vela.json
dist/

76
.goreleaser.yaml Normal file
View File

@@ -0,0 +1,76 @@
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
builds:
- id: vela-cli
binary: vela
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
main: ./references/cmd/cli/main.go
ldflags:
- -s -w -X github.com/oam-dev/kubevela/version.VelaVersion={{ .Version }} -X github.com/oam-dev/kubevela/version.GitRevision=git-{{.ShortCommit}}
env:
- CGO_ENABLED=0
- id: kubectl-vela
binary: kubectl-vela
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
main: ./cmd/plugin/main.go
ldflags:
- -s -w -X github.com/oam-dev/kubevela/version.VelaVersion={{ .Version }} -X github.com/oam-dev/kubevela/version.GitRevision=git-{{.ShortCommit}}
archives:
- format: tar.gz
id: vela-cli-tgz
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
builds:
- vela-cli
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
files: [ LICENSE, README.md ]
- format: zip
id: vela-cli-zip
builds:
- vela-cli
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
files: [ LICENSE, README.md ]
- format: tar.gz
id: plugin-tgz
builds:
- kubectl-vela
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
files: [ LICENSE, README.md ]
- format: zip
id: plugin-zip
builds:
- kubectl-vela
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
files: [ LICENSE, README.md ]
checksum:
name_template: 'sha256sums.txt'
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

View File

@@ -33,8 +33,8 @@ spec:
arch: amd64
{{addURIAndSha "https://github.com/oam-dev/kubevela/releases/download/{{ .TagName }}/kubectl-vela-{{ .TagName }}-windows-amd64.zip" .TagName }}
files:
- from: "*/kubectl-vela"
to: "kubectl-vela.exe"
- from: "*/kubectl-vela.exe"
to: "."
- from: "*/LICENSE"
to: "."
bin: "kubectl-vela.exe"

View File

@@ -111,7 +111,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.7.0-alpha.3` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.7.0` |
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |

View File

@@ -116,7 +116,7 @@ spec:
#ECProvider: {
type: "ec"
apiKey: *"" | string
name: "ec-provider" | string
name: *"ec-provider" | string
}
#GCPProvider: {
credentials: string

View File

@@ -72,7 +72,7 @@ spec:
}]
}
}
parameter: *#PatchParams | close({
parameter: #PatchParams | close({
// +usage=Specify the container image for multiple containers
containers: [...#PatchParams]
})

View File

@@ -53,7 +53,10 @@ spec:
}
if service.spec.type == "LoadBalancer" {
status: service.status
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
isHealth: *false | bool
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
isHealth: true
}
if !isHealth {
message: "ExternalIP: Pending"
}
@@ -62,10 +65,15 @@ spec:
}
}
healthPolicy: |-
isHealth: *true | bool
service: context.outputs.service
if service.spec.type == "LoadBalancer" {
status: service.status
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
isHealth: *false | bool
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
isHealth: true
}
}
if service.spec.type != "LoadBalancer" {
isHealth: true
}

View File

@@ -113,19 +113,20 @@ spec:
}
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
let igs = context.outputs.ingress.status.loadBalancer.ingress
let host = context.outputs.ingress.spec.rules[0].host
if igs[0].ip != _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
}
if igs[0].host == _|_ {
if host == _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
}
}
if igs[0].ip == _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
}
if igs[0].host != _|_ {
if host != _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
}
}

View File

@@ -56,44 +56,41 @@ spec:
// +usage=Specify the message that you want to sent, refer to [dingtalk messaging](https://developers.dingtalk.com/document/robots/custom-robot-access/title-72m-8ag-pqw)
message: {
// +usage=Specify the message content of dingtalk notification
text?: *null | close({
text?: close({
content: string
})
// +usage=msgType can be text, link, mardown, actionCard, feedCard
msgtype: *"text" | "link" | "markdown" | "actionCard" | "feedCard"
link?: *null | close({
#link: {
text?: string
title?: string
messageUrl?: string
picUrl?: string
})
markdown?: *null | close({
}
link?: #link
markdown?: close({
text: string
title: string
})
at?: *null | close({
atMobiles?: *null | [...string]
isAtAll?: bool
at?: close({
atMobiles?: [...string]
isAtAll?: bool
})
actionCard?: *null | close({
actionCard?: close({
text: string
title: string
hideAvatar: string
btnOrientation: string
singleTitle: string
singleURL: string
btns: *null | close([...*null | close({
btns?: [...close({
title: string
actionURL: string
})])
})]
})
feedCard?: *null | close({
links: *null | close([...*null | close({
text?: string
title?: string
messageUrl?: string
picUrl?: string
})])
feedCard?: close({
links: [...#link]
})
}
}
@@ -114,11 +111,11 @@ spec:
// +usage=Specify the message that you want to sent, refer to [slack messaging](https://api.slack.com/reference/messaging/payload)
message: {
// +usage=Specify the message text for slack notification
text: string
blocks?: *null | close([...block])
attachments?: *null | close({
blocks?: *null | close([...block])
color?: string
text: string
blocks?: [...block]
attachments?: close({
blocks?: [...block]
color?: string
})
thread_ts?: string
// +usage=Specify the message text format in markdown for slack notification

View File

@@ -13,7 +13,7 @@ spec:
template: |
#PolicyRule: {
// +usage=Specify how to select the targets of the rule
selector: [...#RuleSelector]
selector: #RuleSelector
}
#RuleSelector: {
// +usage=Select resources by component names

View File

@@ -323,7 +323,7 @@ spec:
envName: string
secretKey: string
}]
mountPath?: string
mountPath: string
subPath?: string
defaultMode: *420 | int
readOnly: *false | bool

View File

@@ -272,8 +272,8 @@ spec:
- "--feature-gates=ZstdResourceTracker={{- .Values.featureGates.zstdResourceTracker | toString -}}"
- "--feature-gates=ApplyOnce={{- .Values.featureGates.applyOnce | toString -}}"
- "--feature-gates=MultiStageComponentApply= {{- .Values.featureGates.multiStageComponentApply | toString -}}"
- "--feature-gates=GzipApplicationRevision={{- .Values.featureGates.gzipResourceTracker | toString -}}"
- "--feature-gates=ZstdApplicationRevision={{- .Values.featureGates.zstdResourceTracker | toString -}}"
- "--feature-gates=GzipApplicationRevision={{- .Values.featureGates.gzipApplicationRevision | toString -}}"
- "--feature-gates=ZstdApplicationRevision={{- .Values.featureGates.zstdApplicationRevision | toString -}}"
- "--feature-gates=PreDispatchDryRun={{- .Values.featureGates.preDispatchDryRun | toString -}}"
{{ if .Values.authentication.enabled }}
{{ if .Values.authentication.withUser }}

View File

@@ -2,7 +2,7 @@ apiVersion: v1
data:
template: |
import (
"vela/ql"
"vela/ql"
)
parameter: {
@@ -55,9 +55,15 @@ data:
phase: pod.object.status.phase
// refer to https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
if phase != "Pending" && phase != "Unknown" {
podIP: pod.object.status.podIP
hostIP: pod.object.status.hostIP
nodeName: pod.object.spec.nodeName
if pod.object.podIP != _|_ {
podIP: pod.object.status.podIP
}
if pod.object.hostIP != _|_ {
hostIP: pod.object.status.hostIP
}
if pod.object.nodeName != _|_ {
nodeName: pod.object.spec.nodeName
}
}
}
}]

View File

@@ -148,7 +148,7 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.7.0-alpha.3
tag: v1.7.0
pullPolicy: IfNotPresent
resources:
limits:

View File

@@ -65,7 +65,6 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
| `controllerArgs.reSyncPeriod` | The period for resync the applications | `5m` |
| `OAMSpecVer` | OAMSpecVer is the oam spec version controller want to setup | `minimal` |
| `disableCaps` | Disable capability | `envbinding,rollout` |
| `applyOnceOnly` | Valid applyOnceOnly values: true/false/on/off/force | `off` |
| `dependCheckWait` | dependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready | `30s` |
@@ -97,20 +96,29 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
| `healthCheck.port` | KubeVela health check port | `9440` |
### KubeVela controller optimization parameters
| Name | Description | Value |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `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` |
### MultiCluster parameters
| Name | Description | Value |
| ----------------------------------------------------- | -------------------------------- | -------------------------------- |
| `multicluster.enabled` | Whether to enable multi-cluster | `true` |
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.4.0` |
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
| `multicluster.clusterGateway.secureTLS.enabled` | Whether to enable secure TLS | `true` |
| `multicluster.clusterGateway.secureTLS.certPath` | Path to the certificate file | `/etc/k8s-cluster-gateway-certs` |
| Name | Description | Value |
| ------------------------------------------------------- | -------------------------------- | -------------------------------- |
| `multicluster.enabled` | Whether to enable multi-cluster | `true` |
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.8.0-alpha.3` |
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
| `multicluster.clusterGateway.resources.requests.cpu` | ClusterGateway cpu request | `50m` |
| `multicluster.clusterGateway.resources.requests.memory` | ClusterGateway memory request | `20Mi` |
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `500m` |
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
| `multicluster.clusterGateway.secureTLS.enabled` | Whether to enable secure TLS | `true` |
| `multicluster.clusterGateway.secureTLS.certPath` | Path to the certificate file | `/etc/k8s-cluster-gateway-certs` |
### Test parameters

View File

@@ -116,7 +116,7 @@ spec:
#ECProvider: {
type: "ec"
apiKey: *"" | string
name: "ec-provider" | string
name: *"ec-provider" | string
}
#GCPProvider: {
credentials: string

View File

@@ -72,7 +72,7 @@ spec:
}]
}
}
parameter: *#PatchParams | close({
parameter: #PatchParams | close({
// +usage=Specify the container image for multiple containers
containers: [...#PatchParams]
})

View File

@@ -53,7 +53,10 @@ spec:
}
if service.spec.type == "LoadBalancer" {
status: service.status
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
isHealth: *false | bool
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
isHealth: true
}
if !isHealth {
message: "ExternalIP: Pending"
}
@@ -62,10 +65,15 @@ spec:
}
}
healthPolicy: |-
isHealth: *true | bool
service: context.outputs.service
if service.spec.type == "LoadBalancer" {
status: service.status
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
isHealth: *false | bool
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
isHealth: true
}
}
if service.spec.type != "LoadBalancer" {
isHealth: true
}

View File

@@ -113,19 +113,20 @@ spec:
}
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
let igs = context.outputs.ingress.status.loadBalancer.ingress
let host = context.outputs.ingress.spec.rules[0].host
if igs[0].ip != _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
}
if igs[0].host == _|_ {
if host == _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
}
}
if igs[0].ip == _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
}
if igs[0].host != _|_ {
if host != _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
}
}

View File

@@ -56,44 +56,41 @@ spec:
// +usage=Specify the message that you want to sent, refer to [dingtalk messaging](https://developers.dingtalk.com/document/robots/custom-robot-access/title-72m-8ag-pqw)
message: {
// +usage=Specify the message content of dingtalk notification
text?: *null | close({
text?: close({
content: string
})
// +usage=msgType can be text, link, mardown, actionCard, feedCard
msgtype: *"text" | "link" | "markdown" | "actionCard" | "feedCard"
link?: *null | close({
#link: {
text?: string
title?: string
messageUrl?: string
picUrl?: string
})
markdown?: *null | close({
}
link?: #link
markdown?: close({
text: string
title: string
})
at?: *null | close({
atMobiles?: *null | [...string]
isAtAll?: bool
at?: close({
atMobiles?: [...string]
isAtAll?: bool
})
actionCard?: *null | close({
actionCard?: close({
text: string
title: string
hideAvatar: string
btnOrientation: string
singleTitle: string
singleURL: string
btns: *null | close([...*null | close({
btns?: [...close({
title: string
actionURL: string
})])
})]
})
feedCard?: *null | close({
links: *null | close([...*null | close({
text?: string
title?: string
messageUrl?: string
picUrl?: string
})])
feedCard?: close({
links: [...#link]
})
}
}
@@ -114,11 +111,11 @@ spec:
// +usage=Specify the message that you want to sent, refer to [slack messaging](https://api.slack.com/reference/messaging/payload)
message: {
// +usage=Specify the message text for slack notification
text: string
blocks?: *null | close([...block])
attachments?: *null | close({
blocks?: *null | close([...block])
color?: string
text: string
blocks?: [...block]
attachments?: close({
blocks?: [...block]
color?: string
})
thread_ts?: string
// +usage=Specify the message text format in markdown for slack notification

View File

@@ -13,7 +13,7 @@ spec:
template: |
#PolicyRule: {
// +usage=Specify how to select the targets of the rule
selector: [...#RuleSelector]
selector: #RuleSelector
}
#RuleSelector: {
// +usage=Select resources by component names

View File

@@ -323,7 +323,7 @@ spec:
envName: string
secretKey: string
}]
mountPath?: string
mountPath: string
subPath?: string
defaultMode: *420 | int
readOnly: *false | bool

View File

@@ -166,10 +166,8 @@ spec:
- "--use-webhook=true"
- "--webhook-port={{ .Values.webhookService.port }}"
- "--webhook-cert-dir={{ .Values.admissionWebhooks.certificate.mountPath }}"
- "--autogen-workload-definition={{ .Values.admissionWebhooks.autoGenWorkloadDefinition }}"
{{ end }}
- "--health-addr=:{{ .Values.healthCheck.port }}"
- "--apply-once-only={{ .Values.applyOnceOnly }}"
{{ if ne .Values.disableCaps "" }}
- "--disable-caps={{ .Values.disableCaps }}"
{{ end }}
@@ -188,6 +186,7 @@ spec:
- "--max-workflow-step-error-retry-times={{ .Values.workflow.step.errorRetryTimes }}"
- "--feature-gates=EnableSuspendOnFailure={{- .Values.workflow.enableSuspendOnFailure | toString -}}"
- "--feature-gates=AuthenticateApplication={{- .Values.authentication.enabled | toString -}}"
- "--feature-gates=ApplyOnce={{- .Values.featureGates.applyOnce | toString -}}"
{{ if .Values.authentication.enabled }}
{{ if .Values.authentication.withUser }}
- "--authentication-with-user"

View File

@@ -26,9 +26,6 @@ OAMSpecVer: "minimal"
## @param disableCaps Disable capability
disableCaps: "envbinding,rollout"
## @param applyOnceOnly Valid applyOnceOnly values: true/false/on/off/force
applyOnceOnly: "off"
## @param dependCheckWait dependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready
dependCheckWait: 30s
@@ -86,6 +83,11 @@ webhookService:
healthCheck:
port: 9440
## @section KubeVela controller optimization parameters
##@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
featureGates:
applyOnce: false
## @section MultiCluster parameters
@@ -95,6 +97,8 @@ healthCheck:
## @param multicluster.clusterGateway.image.repository ClusterGateway image repository
## @param multicluster.clusterGateway.image.tag ClusterGateway image tag
## @param multicluster.clusterGateway.image.pullPolicy ClusterGateway image pull policy
## @param multicluster.clusterGateway.resources.requests.cpu ClusterGateway cpu request
## @param multicluster.clusterGateway.resources.requests.memory ClusterGateway memory request
## @param multicluster.clusterGateway.resources.limits.cpu ClusterGateway cpu limit
## @param multicluster.clusterGateway.resources.limits.memory ClusterGateway memory limit
## @param multicluster.clusterGateway.secureTLS.enabled Whether to enable secure TLS
@@ -106,11 +110,14 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.4.0
tag: v1.8.0-alpha.3
pullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 20Mi
limits:
cpu: 100m
cpu: 500m
memory: 200Mi
secureTLS:
enabled: true

View File

@@ -22,6 +22,7 @@ import (
"time"
"github.com/kubevela/pkg/util/compression"
"github.com/kubevela/pkg/util/k8s"
"github.com/kubevela/pkg/util/singleton"
"k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2"
@@ -55,7 +56,7 @@ func (in *SystemCRDValidationHook) Run(ctx context.Context) error {
feature.DefaultMutableFeatureGate.Enabled(features.GzipApplicationRevision) {
appRev := &v1beta1.ApplicationRevision{}
appRev.Name = fmt.Sprintf("core.pre-check.%d", time.Now().UnixNano())
appRev.Namespace = types.DefaultKubeVelaNS
appRev.Namespace = k8s.GetRuntimeNamespace()
key := client.ObjectKeyFromObject(appRev)
appRev.SetLabels(map[string]string{oam.LabelPreCheck: types.VelaCoreName})
appRev.Spec.Application.Name = appRev.Name

View File

@@ -21,6 +21,7 @@ import (
"strconv"
"time"
pkgclient "github.com/kubevela/pkg/controller/client"
ctrlrec "github.com/kubevela/pkg/controller/reconciler"
pkgmulticluster "github.com/kubevela/pkg/multicluster"
wfTypes "github.com/kubevela/workflow/pkg/types"
@@ -171,6 +172,7 @@ func (s *CoreOptions) Flags() cliflag.NamedFlagSets {
local := flag.NewFlagSet("klog", flag.ExitOnError)
klog.InitFlags(local)
kfs.AddGoFlagSet(local)
pkgclient.AddTimeoutControllerClientFlags(fss.FlagSet("controllerclient"))
if s.LogDebug {
_ = kfs.Set("v", strconv.Itoa(int(commonconfig.LogDebug)))

View File

@@ -2086,7 +2086,7 @@
"tags": [
"application"
],
"summary": "list application triggers",
"summary": "List the application triggers",
"operationId": "listApplicationTriggers",
"parameters": [
{
@@ -2124,7 +2124,7 @@
"tags": [
"application"
],
"summary": "create one application trigger",
"summary": "Create an application trigger",
"operationId": "createApplicationTrigger",
"parameters": [
{
@@ -2160,6 +2160,51 @@
}
},
"/api/v1/applications/{appName}/triggers/{token}": {
"put": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "Update an application trigger",
"operationId": "updateApplicationTrigger",
"parameters": [
{
"type": "string",
"description": "identifier of the application ",
"name": "appName",
"in": "path",
"required": true
},
{
"type": "string",
"description": "identifier of the trigger",
"name": "token",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/v1.ApplicationTriggerBase"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
},
"delete": {
"consumes": [
"application/xml",
@@ -2172,7 +2217,7 @@
"tags": [
"application"
],
"summary": "delete one application trigger",
"summary": "Delete an application trigger",
"operationId": "deleteApplicationTrigger",
"parameters": [
{
@@ -8964,8 +9009,8 @@
},
"model.ApplicationRevision": {
"required": [
"createTime",
"updateTime",
"createTime",
"appPrimaryKey",
"version",
"revisionCRName",
@@ -9347,11 +9392,11 @@
},
"model.WorkflowStep": {
"required": [
"alias",
"name",
"dependsOn",
"description",
"orderIndex",
"dependsOn",
"name",
"alias",
"type"
],
"properties": {
@@ -9469,9 +9514,9 @@
},
"model.WorkflowStepStatus": {
"required": [
"id",
"name",
"alias"
"alias",
"id"
],
"properties": {
"alias": {
@@ -10055,11 +10100,11 @@
"v1.ApplicationDeployResponse": {
"required": [
"version",
"status",
"triggerType",
"createTime",
"status",
"note",
"envName",
"triggerType",
"record"
],
"properties": {
@@ -10338,6 +10383,7 @@
"type",
"payloadType",
"token",
"registry",
"createTime",
"updateTime"
],
@@ -10361,6 +10407,9 @@
"payloadType": {
"type": "string"
},
"registry": {
"type": "string"
},
"token": {
"type": "string"
},
@@ -10833,13 +10882,13 @@
},
"v1.ConfigTemplateDetail": {
"required": [
"sensitive",
"createTime",
"alias",
"name",
"namespace",
"description",
"scope",
"sensitive",
"createTime",
"alias",
"schema",
"uiSchema"
],
@@ -11669,11 +11718,11 @@
},
"v1.DetailAddonResponse": {
"required": [
"invisible",
"name",
"version",
"description",
"icon",
"invisible",
"description",
"schema",
"uiSchema",
"definitions",
@@ -11753,12 +11802,12 @@
},
"v1.DetailApplicationResponse": {
"required": [
"project",
"createTime",
"updateTime",
"name",
"alias",
"project",
"description",
"createTime",
"updateTime",
"icon",
"policies",
"envBindings",
@@ -11816,20 +11865,20 @@
},
"v1.DetailClusterResponse": {
"required": [
"status",
"provider",
"dashboardURL",
"description",
"icon",
"labels",
"reason",
"apiServerURL",
"kubeConfigSecret",
"alias",
"status",
"dashboardURL",
"icon",
"description",
"reason",
"createTime",
"updateTime",
"name",
"kubeConfig",
"labels",
"provider",
"apiServerURL",
"createTime",
"resourceInfo"
],
"properties": {
@@ -11887,13 +11936,13 @@
},
"v1.DetailComponentResponse": {
"required": [
"name",
"main",
"alias",
"createTime",
"updateTime",
"appPrimaryKey",
"creator",
"name",
"main",
"createTime",
"updateTime",
"alias",
"type",
"definition"
],
@@ -11982,12 +12031,12 @@
},
"v1.DetailDefinitionResponse": {
"required": [
"alias",
"labels",
"ownerAddon",
"name",
"alias",
"icon",
"labels",
"description",
"icon",
"status",
"schema",
"uiSchema"
@@ -12045,15 +12094,15 @@
},
"v1.DetailPolicyResponse": {
"required": [
"description",
"creator",
"envName",
"name",
"alias",
"type",
"description",
"createTime",
"updateTime",
"type",
"properties"
"alias",
"creator",
"properties",
"envName"
],
"properties": {
"alias": {
@@ -12095,18 +12144,18 @@
},
"v1.DetailRevisionResponse": {
"required": [
"appPrimaryKey",
"revisionCRName",
"triggerType",
"workflowName",
"version",
"status",
"deployUser",
"note",
"createTime",
"appPrimaryKey",
"deployUser",
"triggerType",
"updateTime",
"revisionCRName",
"reason",
"envName"
"envName",
"version",
"workflowName",
"createTime"
],
"properties": {
"appPrimaryKey": {
@@ -12163,10 +12212,10 @@
},
"v1.DetailTargetResponse": {
"required": [
"updateTime",
"name",
"project",
"createTime",
"updateTime"
"project"
],
"properties": {
"alias": {
@@ -12206,11 +12255,11 @@
},
"v1.DetailUserResponse": {
"required": [
"email",
"disabled",
"createTime",
"lastLoginTime",
"name",
"email",
"projects",
"roles"
],
@@ -12252,12 +12301,12 @@
"v1.DetailWorkflowRecordResponse": {
"required": [
"status",
"mode",
"workflowAlias",
"applicationRevision",
"namespace",
"message",
"mode",
"name",
"namespace",
"workflowName",
"deployTime",
"deployUser",
@@ -12321,15 +12370,15 @@
"v1.DetailWorkflowResponse": {
"required": [
"name",
"enable",
"envName",
"alias",
"description",
"default",
"createTime",
"updateTime",
"subMode",
"alias",
"enable",
"default",
"envName",
"mode"
"mode",
"subMode"
],
"properties": {
"alias": {
@@ -12537,8 +12586,8 @@
},
"v1.EnvBindingTarget": {
"required": [
"name",
"alias"
"alias",
"name"
],
"properties": {
"alias": {
@@ -12565,11 +12614,11 @@
"v1.GetPipelineResponse": {
"required": [
"spec",
"description",
"createTime",
"name",
"alias",
"project",
"description",
"info"
],
"properties": {
@@ -12612,10 +12661,10 @@
},
"v1.GetPipelineRunLogResponse": {
"required": [
"phase",
"id",
"name",
"type",
"phase",
"source",
"log"
],
@@ -13269,11 +13318,11 @@
},
"v1.LoginUserInfoResponse": {
"required": [
"createTime",
"lastLoginTime",
"name",
"email",
"disabled",
"createTime",
"lastLoginTime",
"projects",
"platformPermissions",
"projectPermissions"
@@ -13475,11 +13524,11 @@
},
"v1.PipelineBase": {
"required": [
"description",
"createTime",
"name",
"alias",
"project",
"description",
"spec"
],
"properties": {
@@ -13578,11 +13627,11 @@
},
"v1.PipelineMetaResponse": {
"required": [
"name",
"alias",
"project",
"description",
"createTime",
"name",
"alias"
"createTime"
],
"properties": {
"alias": {
@@ -13605,13 +13654,13 @@
},
"v1.PipelineRun": {
"required": [
"contextName",
"contextValues",
"spec",
"pipelineName",
"project",
"pipelineRunName",
"record",
"contextName",
"contextValues",
"spec",
"status"
],
"properties": {
@@ -14208,9 +14257,9 @@
},
"v1.SystemInfoResponse": {
"required": [
"loginType",
"platformID",
"enableCollection",
"loginType",
"systemVersion"
],
"properties": {
@@ -14734,14 +14783,14 @@
},
"v1.WorkflowRecord": {
"required": [
"namespace",
"message",
"status",
"mode",
"name",
"namespace",
"workflowName",
"workflowAlias",
"applicationRevision"
"applicationRevision",
"mode",
"message"
],
"properties": {
"applicationRevision": {
@@ -14832,8 +14881,8 @@
},
"v1.WorkflowStep": {
"required": [
"type",
"name"
"name",
"type"
],
"properties": {
"alias": {

View File

@@ -74,6 +74,12 @@ var _ = Describe("Addon Test", func() {
Expect(output).To(ContainSubstring("enabled successfully."))
})
It("Enable addon with specified registry ", func() {
output, err := e2e.LongTimeExec("vela addon enable KubeVela/test-addon", 300*time.Second)
Expect(err).NotTo(HaveOccurred())
Expect(output).To(ContainSubstring("enabled successfully."))
})
It("Disable addon test-addon", func() {
output, err := e2e.LongTimeExec("vela addon disable test-addon", 600*time.Second)
Expect(err).NotTo(HaveOccurred())

32
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/oam-dev/kubevela
go 1.19
require (
cuelang.org/go v0.5.0-alpha.1
cuelang.org/go v0.5.0-beta.5
github.com/AlecAivazis/survey/v2 v2.1.1
github.com/FogDong/uitable v0.0.5
github.com/Masterminds/semver/v3 v3.1.1
@@ -54,17 +54,16 @@ require (
github.com/hashicorp/hcl/v2 v2.12.0
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/imdario/mergo v0.3.13
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/kubevela/pkg v0.0.0-20230105054759-263dc191bf51
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac
github.com/kubevela/prism v1.7.0-alpha.1
github.com/kubevela/workflow v0.4.0
github.com/kubevela/workflow v0.4.3
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/oam-dev/cluster-gateway v1.7.0-alpha.1
github.com/oam-dev/cluster-register v1.0.4-0.20220928064144-5f76a9d7ca8c
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
github.com/oam-dev/terraform-controller v0.7.8
github.com/oam-dev/terraform-controller v0.7.10
github.com/olekukonko/tablewriter v0.0.5
github.com/onsi/ginkgo v1.16.5
github.com/onsi/ginkgo/v2 v2.1.6
@@ -88,9 +87,9 @@ require (
go.mongodb.org/mongo-driver v1.5.1
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.4.0
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
golang.org/x/term v0.3.0
golang.org/x/text v0.5.0
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c
golang.org/x/term v0.5.0
golang.org/x/text v0.7.0
gomodules.xyz/jsonpatch/v2 v2.2.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools v2.2.0+incompatible
@@ -100,14 +99,14 @@ require (
k8s.io/apiextensions-apiserver v0.25.2
k8s.io/apimachinery v0.25.3
k8s.io/apiserver v0.25.3
k8s.io/cli-runtime v0.25.2
k8s.io/cli-runtime v0.25.3
k8s.io/client-go v0.25.3
k8s.io/component-base v0.25.3
k8s.io/helm v2.17.0+incompatible
k8s.io/klog/v2 v2.70.1
k8s.io/kube-aggregator v0.25.3
k8s.io/kubectl v0.25.2
k8s.io/metrics v0.25.2
k8s.io/kubectl v0.25.3
k8s.io/metrics v0.25.3
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
open-cluster-management.io/api v0.7.0
sigs.k8s.io/controller-runtime v0.12.3
@@ -117,6 +116,8 @@ require (
sigs.k8s.io/yaml v1.3.0
)
require github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -301,14 +302,14 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.3.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
@@ -348,7 +349,6 @@ require (
replace (
cloud.google.com/go => cloud.google.com/go v0.100.2
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

55
go.sum
View File

@@ -34,6 +34,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
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.5.0-beta.5 h1:TAV4ZjXw2M6xf6jI8XyAAXCqWJ82Y0oxhlf9w3l544A=
cuelang.org/go v0.5.0-beta.5/go.mod h1:okjJBHFQFer+a41sAe2SaGm1glWS8oEb6CmJvn5Zdws=
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=
@@ -1283,14 +1285,12 @@ 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-20230105054759-263dc191bf51 h1:xrcNNaAjqC6tr1leSYcjLFgrXKpZ8u87jpB5TolhUIc=
github.com/kubevela/pkg v0.0.0-20230105054759-263dc191bf51/go.mod h1:ZRnxY/gOcg/8FilZA+eYr+rtVXb1ijT5HFTe8zrv9zo=
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac h1:TLQchMx+BRTnHyebDpOWF2RpF2eTczFBtJro3/H9vwI=
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac/go.mod h1:GilLxt+9L4sU2tLeZAGHga8wiYmjjfPX/Q6JkyuuXSM=
github.com/kubevela/prism v1.7.0-alpha.1 h1:oeZFn1Oy6gxSSFzMTfsWjLOCKaaooMVm1JGNK4j4Mlo=
github.com/kubevela/prism v1.7.0-alpha.1/go.mod h1:AJSDfdA+RkRSnWx3xEcogbmOTpX+l7RSIwqVHxwUtaI=
github.com/kubevela/workflow v0.4.0 h1:Zzb9wPOvLUGEArdnC6EsfNM5j3VNJj0/v2iDKq1JT3k=
github.com/kubevela/workflow v0.4.0/go.mod h1:AX/WL3G/YBkpmNpA/SKKm9M3Y0T9y95gZA8mFWylkyM=
github.com/kubevela/workflow v0.4.3 h1:1WAMb4xrRXQW5hK5bXwV2WFHlxn2+ezkblai8oC5DmY=
github.com/kubevela/workflow v0.4.3/go.mod h1:U94Hz5rlHPAatN+Birhumly26zjAguMumdhrYk+e5mo=
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=
@@ -1435,8 +1435,8 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
github.com/mitchellh/hashstructure/v2 v2.0.1 h1:L60q1+q7cXE4JeEJJKMnh2brFIe3rZxCihYAB61ypAY=
github.com/mitchellh/hashstructure/v2 v2.0.1/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@@ -1523,8 +1523,8 @@ github.com/oam-dev/stern v1.13.2 h1:jlGgtJbKmIVhzkH44ft5plkgs8XEfvxbFrQdX60CQR4=
github.com/oam-dev/stern v1.13.2/go.mod h1:0pLjZt0amXE/ErF16Rdrgd98H2owN8Hmn3/7CX5+AeA=
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28 h1:tD8HiFKnt0jnwdTWjeqUnfnUYLD/+Nsmj8ZGIxqDWiU=
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28/go.mod h1:Mu8i0/DdplvnjwRbAYPsc8+LRR27n/mp8VWdkN10GzE=
github.com/oam-dev/terraform-controller v0.7.8 h1:4Kss5EnMljKecw8o2aPCpZdOTP1L1ODgf8BjmgN/cMI=
github.com/oam-dev/terraform-controller v0.7.8/go.mod h1:83eY+m0ehYAnQytilG9TVjuCgDQWl3+pnE6oIJ9EujE=
github.com/oam-dev/terraform-controller v0.7.10 h1:e2STz6Od53S4Ra4+QQs65lujF50vIb6eQtTMuvvofjk=
github.com/oam-dev/terraform-controller v0.7.10/go.mod h1:xvgChKG0pij0WEKRrX7w30SdVBPVOlRl/+Mv7+2C1cI=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
@@ -2300,8 +2300,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -2319,8 +2319,8 @@ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 h1:+jnHzr9VPj32ykQVai5DNahi9+NSp7yYuCsl5eAQtL0=
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY=
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -2484,8 +2484,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/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=
@@ -2494,8 +2494,8 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -2507,8 +2507,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2813,8 +2813,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
@@ -2969,8 +2970,8 @@ k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
k8s.io/apiserver v0.22.6/go.mod h1:OlL1rGa2kKWGj2JEXnwBcul/BwC9Twe95gm4ohtiIIs=
k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI=
k8s.io/apiserver v0.25.3/go.mod h1:9bT47iM2fzRuhICJpM/RcQR9sqDDfZ7Yw60h0p3JW08=
k8s.io/cli-runtime v0.25.2 h1:XOx+SKRjBpYMLY/J292BHTkmyDffl/qOx3YSuFZkTuc=
k8s.io/cli-runtime v0.25.2/go.mod h1:OQx3+/0st6x5YpkkJQlEWLC73V0wHsOFMC1/roxV8Oc=
k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8=
k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
k8s.io/client-go v0.0.0-20191122220542-ed16ecbdf3a0/go.mod h1:tyxNgOmR/Xi39HrlQ/9LQgiHJgBvmY7gp95o5GpBA4o=
@@ -3063,11 +3064,11 @@ k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2R
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA=
k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg=
k8s.io/kubectl v0.25.3 h1:HnWJziEtmsm4JaJiKT33kG0kadx68MXxUE8UEbXnN4U=
k8s.io/kubectl v0.25.3/go.mod h1:glU7PiVj/R6Ud4A9FJdTcJjyzOtCJyc0eO7Mrbh3jlI=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/metrics v0.25.2 h1:105TuPaIFfr4EHzN56WwZJO7r1UesuDytNTzeMqGySo=
k8s.io/metrics v0.25.2/go.mod h1:4NDAauOuEJ+NWO2+hWkhFE4rWBx/plLWJOYU3vGl0sA=
k8s.io/metrics v0.25.3 h1:fp5RuALkbwI3UbKITdNYu6sa3LF4JPANR/ofq3oe+Fg=
k8s.io/metrics v0.25.3/go.mod h1:5j5FKJb8RHsb3Q2PLsD/p1mLiA1fTrl+a62Les+KDhc=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=

View File

@@ -99,6 +99,7 @@ type ApplicationService interface {
CreateApplicationTrigger(ctx context.Context, app *model.Application, req apisv1.CreateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error)
ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error)
DeleteApplicationTrigger(ctx context.Context, app *model.Application, triggerName string) error
UpdateApplicationTrigger(ctx context.Context, app *model.Application, token string, req apisv1.UpdateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error)
}
type applicationServiceImpl struct {
@@ -410,6 +411,18 @@ func (c *applicationServiceImpl) CreateApplication(ctx context.Context, req apis
// CreateApplicationTrigger create application trigger
func (c *applicationServiceImpl) CreateApplicationTrigger(ctx context.Context, app *model.Application, req apisv1.CreateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error) {
// checking the workflow
_, err := c.WorkflowService.GetWorkflow(ctx, app, req.WorkflowName)
if err != nil {
return nil, err
}
if req.ComponentName != "" {
_, err := c.GetApplicationComponent(ctx, app, req.ComponentName)
if err != nil {
return nil, err
}
}
trigger := &model.ApplicationTrigger{
AppPrimaryKey: app.Name,
WorkflowName: req.WorkflowName,
@@ -427,18 +440,7 @@ func (c *applicationServiceImpl) CreateApplicationTrigger(ctx context.Context, a
return nil, err
}
return &apisv1.ApplicationTriggerBase{
WorkflowName: req.WorkflowName,
Name: req.Name,
Alias: req.Alias,
Description: req.Description,
Type: req.Type,
PayloadType: req.PayloadType,
Token: trigger.Token,
ComponentName: trigger.ComponentName,
CreateTime: trigger.CreateTime,
UpdateTime: trigger.UpdateTime,
}, nil
return assembler.ConvertTrigger2DTO(*trigger), nil
}
// DeleteApplicationTrigger delete application trigger
@@ -457,6 +459,42 @@ func (c *applicationServiceImpl) DeleteApplicationTrigger(ctx context.Context, a
return nil
}
// UpdateApplicationTrigger update application trigger
func (c *applicationServiceImpl) UpdateApplicationTrigger(ctx context.Context, app *model.Application, token string, req apisv1.UpdateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error) {
trigger := model.ApplicationTrigger{
AppPrimaryKey: app.PrimaryKey(),
Token: token,
}
if err := c.Store.Get(ctx, &trigger); err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return nil, bcode.ErrApplicationTriggerNotExist
}
klog.Warningf("get app trigger failure %s", err.Error())
return nil, err
}
// checking the workflow
_, err := c.WorkflowService.GetWorkflow(ctx, app, req.WorkflowName)
if err != nil {
return nil, err
}
if req.ComponentName != "" {
_, err := c.GetApplicationComponent(ctx, app, req.ComponentName)
if err != nil {
return nil, err
}
}
trigger.Alias = req.Alias
trigger.ComponentName = req.ComponentName
trigger.Description = req.Description
trigger.WorkflowName = req.WorkflowName
trigger.Registry = req.Registry
trigger.PayloadType = req.PayloadType
if err := c.Store.Put(ctx, &trigger); err != nil {
return nil, err
}
return assembler.ConvertTrigger2DTO(trigger), nil
}
// ListApplicationTrigger list application triggers
func (c *applicationServiceImpl) ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error) {
trigger := &model.ApplicationTrigger{
@@ -1715,6 +1753,10 @@ func (c *applicationServiceImpl) RollbackWithRevision(ctx context.Context, appli
if err != nil {
return nil, err
}
// The deploy version is the primary key of the revision
if rollbackApplication.Annotations[oam.AnnotationDeployVersion] == "" {
rollbackApplication.Annotations[oam.AnnotationDeployVersion] = publishVersion
}
record, err := c.WorkflowService.CreateWorkflowRecord(ctx, application, rollbackApplication, &work)
if err != nil {
return nil, fmt.Errorf("create workflow record failure %w", err)

View File

@@ -208,15 +208,17 @@ var _ = Describe("Test application service function", func() {
appModel, err := appService.GetApplication(context.TODO(), testApp)
Expect(err).Should(BeNil())
_, err = appService.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{
Name: "trigger-name",
Name: "trigger-name",
WorkflowName: repository.ConvertWorkflowName("app-dev"),
})
Expect(err).Should(BeNil())
base, err := appService.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{
Name: "trigger-name-2",
ComponentName: "trigger-component",
ComponentName: "component-name",
WorkflowName: repository.ConvertWorkflowName("app-dev"),
})
Expect(err).Should(BeNil())
Expect(base.ComponentName).Should(Equal("trigger-component"))
Expect(base.ComponentName).Should(Equal("component-name"))
})
It("Test ListTriggers function", func() {
@@ -299,6 +301,33 @@ var _ = Describe("Test application service function", func() {
Expect(cmp.Diff(len(detailResponse.Traits), 2)).Should(BeEmpty())
})
It("Test UpdateTrigger function", func() {
appModel, err := appService.GetApplication(context.TODO(), testApp)
Expect(err).Should(BeNil())
triggers, err := appService.ListApplicationTriggers(context.TODO(), appModel)
Expect(err).Should(BeNil())
Expect(len(triggers)).Should(Equal(2))
_, err = appService.UpdateApplicationTrigger(context.TODO(), appModel, triggers[1].Token, v1.UpdateApplicationTriggerRequest{
ComponentName: "notfound",
WorkflowName: repository.ConvertWorkflowName("app-dev"),
})
Expect(err).Should(Equal(bcode.ErrApplicationComponentNotExist))
_, err = appService.UpdateApplicationTrigger(context.TODO(), appModel, triggers[1].Token, v1.UpdateApplicationTriggerRequest{
WorkflowName: "notfound",
})
Expect(err).Should(Equal(bcode.ErrWorkflowNotExist))
base, err := appService.UpdateApplicationTrigger(context.TODO(), appModel, triggers[1].Token, v1.UpdateApplicationTriggerRequest{
Alias: triggers[1].Alias,
Description: triggers[1].Description,
ComponentName: "test2",
WorkflowName: repository.ConvertWorkflowName("app-dev"),
PayloadType: triggers[1].PayloadType,
Registry: triggers[1].Registry,
})
Expect(err).Should(BeNil())
Expect(cmp.Diff(base.ComponentName, "test2")).Should(BeEmpty())
})
It("Test DetailComponent function", func() {
appModel, err := appService.GetApplication(context.TODO(), testApp)
Expect(err).Should(BeNil())

View File

@@ -387,7 +387,10 @@ func (c *clusterServiceImpl) DeleteKubeCluster(ctx context.Context, clusterName
cluster, err := c.getClusterFromDataStore(ctx, clusterName)
if err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return nil, bcode.ErrClusterNotFoundInDataStore
if err = multicluster.DetachCluster(ctx, c.K8sClient, clusterName); err != nil {
return nil, bcode.ErrClusterNotFoundInDataStore
}
return &apis.ClusterBase{Name: clusterName}, nil
}
return nil, errors.Wrapf(err, "failed to found cluster %s in data store", clusterName)
}

View File

@@ -98,6 +98,27 @@ var _ = Describe("Test cluster service function", func() {
Expect(err).Should(Equal(bcode.ErrClusterNotFoundInDataStore))
})
It("Test delete kube cluster", func() {
service := clusterServiceImpl{
Store: ds,
caches: cache,
K8sClient: k8sClient,
}
Expect(createClusterSecret("prism-cluster", "prism-alias")).Should(Succeed())
Expect(ds.Add(ctx, &model.Cluster{Name: "prism-cluster", Alias: "prism-alias", Icon: "prism-icon"})).Should(Succeed())
resp, err := service.DeleteKubeCluster(ctx, "prism-cluster")
Expect(err).Should(Succeed())
Expect(resp.Name).Should(Equal("prism-cluster"))
Expect(resp.Alias).Should(Equal("prism-alias"))
Expect(resp.Icon).Should(Equal("prism-icon"))
_, err = service.DeleteKubeCluster(ctx, "non-exist-cluster")
Expect(err).Should(Equal(bcode.ErrClusterNotFoundInDataStore))
Expect(createClusterSecret("secret-exist-cm-non-exist-cluster", "secret-exist-cm-non-exist-cluster")).Should(Succeed())
resp, err = service.DeleteKubeCluster(ctx, "secret-exist-cm-non-exist-cluster")
Expect(err).Should(Succeed())
Expect(resp.Name).Should(Equal("secret-exist-cm-non-exist-cluster"))
})
It("Test list kube clusters", func() {
service := clusterServiceImpl{
Store: ds,

View File

@@ -91,7 +91,7 @@ template: {
parameter: {
//+usage=The name of Terraform Provider for Alibaba Cloud
name: *"default" | string
name: string
//+usage=Get ALICLOUD_ACCESS_KEY per this guide https://help.aliyun.com/knowledge_detail/38738.html
ALICLOUD_ACCESS_KEY: string
//+usage=Get ALICLOUD_SECRET_KEY per this guide https://help.aliyun.com/knowledge_detail/38738.html
@@ -144,7 +144,7 @@ var _ = Describe("Test config service", func() {
Expect(err).ToNot(BeNil())
var paramErr = &script.ParameterError{}
Expect(errors.As(err, &paramErr)).To(Equal(true))
Expect(paramErr.Name).To(Equal("ALICLOUD_ACCESS_KEY"))
Expect(paramErr.Name).To(Equal("name"))
Expect(paramErr.Message).To(Equal("This parameter is required"))
config, err := configService.CreateConfig(context.TODO(), "", v1.CreateConfigRequest{

View File

@@ -45,8 +45,9 @@ func NewHelmService() HelmService {
type HelmService interface {
ListChartNames(ctx context.Context, url string, secretName string, skipCache bool) ([]string, error)
ListChartVersions(ctx context.Context, url string, chartName string, secretName string, skipCache bool) (repo.ChartVersions, error)
GetChartValues(ctx context.Context, url string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error)
ListChartValuesFiles(ctx context.Context, url string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]string, error)
ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error)
GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]interface{}, error)
}
type defaultHelmImpl struct {
@@ -99,7 +100,7 @@ func (d defaultHelmImpl) ListChartVersions(ctx context.Context, repoURL string,
return chartVersions, nil
}
func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error) {
func (d defaultHelmImpl) ListChartValuesFiles(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]string, error) {
if !utils.IsValidURL(repoURL) {
return nil, bcode.ErrRepoInvalidURL
}
@@ -111,13 +112,33 @@ func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, cha
return nil, bcode.ErrRepoBasicAuth
}
}
v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, opts)
v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, repoType, opts)
if err != nil {
klog.Errorf("cannot fetch chart values repo: %s, chart: %s, version: %s, error: %s", utils.Sanitize(repoURL), utils.Sanitize(chartName), utils.Sanitize(version), err.Error())
return nil, bcode.ErrGetChartValues
}
res := make(map[string]interface{}, len(v))
flattenKey("", v, res)
return v.Data, nil
}
func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]interface{}, error) {
if !utils.IsValidURL(repoURL) {
return nil, bcode.ErrRepoInvalidURL
}
var opts *common.HTTPOption
var err error
if len(secretName) != 0 {
opts, err = helm.SetHTTPOption(ctx, d.K8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName})
if err != nil {
return nil, bcode.ErrRepoBasicAuth
}
}
v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, repoType, opts)
if err != nil {
klog.Errorf("cannot fetch chart values repo: %s, chart: %s, version: %s, error: %s", utils.Sanitize(repoURL), utils.Sanitize(chartName), utils.Sanitize(version), err.Error())
return nil, bcode.ErrGetChartValues
}
res := make(map[string]interface{}, len(v.Values))
flattenKey("", v.Values, res)
return res, nil
}

View File

@@ -213,7 +213,7 @@ var _ = Describe("test helm usecasae", func() {
Expect(len(versions)).Should(BeEquivalentTo(1))
Expect(versions[0].Version).Should(BeEquivalentTo("8.8.23"))
values, err := u.GetChartValues(ctx, mockServer.URL, "mysql", "8.8.23", "repo-secret", false)
values, err := u.ListChartValuesFiles(ctx, mockServer.URL, "mysql", "8.8.23", "repo-secret", "helm", false)
Expect(err).Should(BeNil())
Expect(values).ShouldNot(BeNil())
Expect(len(values)).ShouldNot(BeEquivalentTo(0))
@@ -228,7 +228,7 @@ var _ = Describe("test helm usecasae", func() {
_, err = u.ListChartVersions(ctx, "http://127.0.0.1:8080", "mysql", "repo-secret-notExist", false)
Expect(err).ShouldNot(BeNil())
_, err = u.GetChartValues(ctx, "http://127.0.0.1:8080", "mysql", "8.8.23", "repo-secret-notExist", false)
_, err = u.ListChartValuesFiles(ctx, "http://127.0.0.1:8080", "mysql", "8.8.23", "repo-secret-notExist", "helm", false)
Expect(err).ShouldNot(BeNil())
})
})

View File

@@ -259,7 +259,9 @@ func managePrivilegesForTarget(ctx context.Context, cli client.Client, target *m
f, msg = auth.RevokePrivileges, "RevokePrivileges"
}
if err := f(ctx, cli, []auth.PrivilegeDescription{p}, identity, writer); err != nil {
return err
klog.Warningf("error encountered for %s: %s", msg, err.Error())
// for some cluster, authn/authz is not supported, ignore errors
return client.IgnoreNotFound(err)
}
klog.Infof("%s: %s", msg, writer.String())
return nil

View File

@@ -18,6 +18,7 @@ package service
import (
"fmt"
"reflect"
)
// guaranteePolicyExist check the slice whether contain the target policy, if not put it in.
@@ -57,16 +58,36 @@ func extractPolicyListAndProperty(property map[string]interface{}) ([]string, ma
if policies == nil {
return nil, property, nil
}
list, ok := policies.([]interface{})
if !ok {
list, err := InterfaceSlice(policies)
if err != nil {
return nil, nil, fmt.Errorf("the policies incorrect")
}
if len(list) == 0 {
return nil, property, nil
}
res := []string{}
var res []string
for _, i := range list {
res = append(res, i.(string))
}
return res, property, nil
}
// InterfaceSlice interface to []interface{}
func InterfaceSlice(slice interface{}) ([]interface{}, error) {
if arr, ok := slice.([]interface{}); ok {
return arr, nil
}
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
return nil, fmt.Errorf("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil, nil
}
ret := make([]interface{}, s.Len())
for i := 0; i < s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret, nil
}

View File

@@ -174,61 +174,87 @@ func TestExtractPolicyListAndProperty(t *testing.T) {
testCases := []struct {
input string
res struct {
policies []string
properties map[string]interface{}
noError bool
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}
}{
{
input: `{"policies": null, "components": null}`,
res: struct {
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: nil, properties: map[string]interface{}{
"policies": nil,
"components": nil,
}, noUnmarshallError: true, noExtractError: true},
},
{
input: `{"policies": "policy1", "components": "comp1"}`,
res: struct {
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: nil, properties: nil, noUnmarshallError: true, noExtractError: false},
},
{
input: `{"policies":["policy1","policy2"], "components": ["comp1"]}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: []string{"policy1", "policy2"}, properties: map[string]interface{}{
"policies": []interface{}{"policy1", "policy2"},
"components": []interface{}{"comp1"},
}, noError: true},
}, noUnmarshallError: true, noExtractError: true},
},
{
input: `{"policies":["policy1"], "components": ["comp1"]}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: []string{"policy1"}, properties: map[string]interface{}{
"policies": []interface{}{"policy1"},
"components": []interface{}{"comp1"},
}, noError: true},
}, noUnmarshallError: true, noExtractError: true},
},
{
input: `{"policies":["policy1", "components": ["comp1"]}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
}{noError: false},
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{noUnmarshallError: false, noExtractError: false},
},
{
input: `{}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
}{policies: nil, properties: nil, noError: true},
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: nil, properties: nil, noUnmarshallError: true, noExtractError: true},
},
}
for _, testCase := range testCases {
var in = map[string]interface{}{}
err := json.Unmarshal([]byte(testCase.input), &in)
if testCase.res.noError {
if testCase.res.noUnmarshallError {
assert.NilError(t, err)
} else {
assert.Equal(t, err != nil, true)
continue
}
policy, properties, err := extractPolicyListAndProperty(in)
if testCase.res.noError {
if testCase.res.noExtractError {
assert.NilError(t, err)
} else {
assert.Equal(t, err != nil, true)

View File

@@ -29,6 +29,7 @@ import (
"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"
"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"
@@ -168,6 +169,7 @@ var _ = Describe("Test application service function", func() {
Name: "test-acr",
PayloadType: "acr",
Type: "webhook",
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
ComponentName: "component-name-webhook",
})
Expect(err).Should(BeNil())
@@ -202,6 +204,7 @@ var _ = Describe("Test application service function", func() {
PayloadType: "acr",
Type: "webhook",
ComponentName: "component-name-webhook",
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
Registry: "test-enterprise-registry.test-region.cr.aliyuncs.com",
})
Expect(err).Should(BeNil())
@@ -236,6 +239,7 @@ var _ = Describe("Test application service function", func() {
PayloadType: "harbor",
Type: "webhook",
ComponentName: "component-name-webhook",
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
})
Expect(err).Should(BeNil())
@@ -274,6 +278,7 @@ var _ = Describe("Test application service function", func() {
PayloadType: "dockerhub",
Type: "webhook",
ComponentName: "component-name-webhook",
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
})
Expect(err).Should(BeNil())
@@ -306,6 +311,7 @@ var _ = Describe("Test application service function", func() {
PayloadType: "jfrog",
Type: "webhook",
ComponentName: "component-name-webhook",
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
})
Expect(err).Should(BeNil())
jfrogBody := apisv1.HandleApplicationTriggerJFrogRequest{

View File

@@ -48,6 +48,7 @@ var _ = Describe("Test workflow service functions", func() {
projectService *projectServiceImpl
envService *envServiceImpl
envBinding *envBindingServiceImpl
targetService *targetServiceImpl
testProject = "workflow-project"
ds datastore.DataStore
)
@@ -60,6 +61,7 @@ var _ = Describe("Test workflow service functions", func() {
rbacService := &rbacServiceImpl{Store: ds}
projectService = &projectServiceImpl{Store: ds, RbacService: rbacService, K8sClient: k8sClient}
envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService}
targetService = &targetServiceImpl{Store: ds, K8sClient: k8sClient}
envBinding = &envBindingServiceImpl{
Store: ds,
WorkflowService: workflowService,
@@ -77,11 +79,20 @@ var _ = Describe("Test workflow service functions", func() {
ProjectService: projectService,
EnvService: envService,
EnvBindingService: envBinding,
WorkflowService: workflowService,
}
})
It("Test CreateWorkflow function", func() {
_, err := projectService.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject})
Expect(err).Should(BeNil())
_, err = targetService.CreateTarget(context.TODO(), apisv1.CreateTargetRequest{
Name: "dev-1", Project: testProject, Cluster: &apisv1.ClusterTarget{ClusterName: "local", Namespace: "dev-1"}})
Expect(err).Should(BeNil())
_, err = envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "dev", Namespace: "dev-1", Targets: []string{"dev-1"}, Project: testProject})
Expect(err).Should(BeNil())
reqApp := apisv1.CreateApplicationRequest{
Name: appName,
Project: testProject,

View File

@@ -190,7 +190,7 @@ func (c *CR2UX) generateEnv(ctx context.Context, defaultProject string, envNames
env.Targets = append(env.Targets, name)
}
}
return env, "", nil
return env, env.Project, nil
}
// generate new environment

View File

@@ -217,6 +217,47 @@ var _ = Describe("Test CR convert to ux", func() {
Expect(count).Should(Equal(int64(2)))
})
It("Test to sync the project which existed env belongs", func() {
dbNamespace := "update-app-db-ns1-test"
ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: dbNamespace})
Expect(err).Should(BeNil())
cr2ux := newCR2UX(ds)
projectName := "project-test"
_, err = cr2ux.projectService.CreateProject(context.TODO(), v1.CreateProjectRequest{
Name: projectName,
Owner: "admin",
})
Expect(err).Should(BeNil())
_, err = cr2ux.targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{
Name: "target-test1",
Project: projectName,
Cluster: &v1.ClusterTarget{
ClusterName: "local",
Namespace: "target-test1",
},
})
Expect(err).Should(BeNil())
_, err = cr2ux.envService.CreateEnv(context.TODO(), v1.CreateEnvRequest{
Name: "env-test1",
Project: projectName,
Namespace: "env-test1",
Targets: []string{"target-test1"},
})
Expect(err).Should(BeNil())
app5 := &v1beta1.Application{}
Expect(common2.ReadYamlToObject("testdata/test-app5.yaml", app5)).Should(BeNil())
app5.Namespace = "env-test1"
Expect(cr2ux.AddOrUpdate(context.Background(), app5)).Should(BeNil())
app, err := cr2ux.applicationService.GetApplication(context.TODO(), app5.Name)
Expect(err).Should(BeNil())
Expect(app.Project).Should(Equal("project-test"))
})
})
func newCR2UX(ds datastore.DataStore) *CR2UX {

View File

@@ -0,0 +1,16 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: example-sync-project
spec:
components:
- name: example-exist-env
type: webservice
properties:
image: wordpress
traits:
- type: gateway
properties:
domain: testsvc.example.com
http:
"/": 8000

View File

@@ -118,7 +118,7 @@ func (c *application) GetWebServiceRoute() *restful.WebService {
Writes(apis.ApplicationStatisticsResponse{}))
ws.Route(ws.POST("/{appName}/triggers").To(c.createApplicationTrigger).
Doc("create one application trigger").
Doc("Create an application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "create")).
Filter(c.appCheckFilter).
@@ -129,7 +129,7 @@ func (c *application) GetWebServiceRoute() *restful.WebService {
Writes(apis.ApplicationTriggerBase{}))
ws.Route(ws.DELETE("/{appName}/triggers/{token}").To(c.deleteApplicationTrigger).
Doc("delete one application trigger").
Doc("Delete an application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "delete")).
Filter(c.appCheckFilter).
@@ -139,8 +139,19 @@ func (c *application) GetWebServiceRoute() *restful.WebService {
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]*apis.EmptyResponse{}))
ws.Route(ws.PUT("/{appName}/triggers/{token}").To(c.updateApplicationTrigger).
Doc("Update an application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "update")).
Filter(c.appCheckFilter).
Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")).
Param(ws.PathParameter("token", "identifier of the trigger").DataType("string")).
Returns(200, "OK", apis.ApplicationTriggerBase{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]*apis.ApplicationTriggerBase{}))
ws.Route(ws.GET("/{appName}/triggers").To(c.listApplicationTriggers).
Doc("list application triggers").
Doc("List the application triggers").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "list")).
Filter(c.appCheckFilter).
@@ -747,6 +758,24 @@ func (c *application) deleteApplicationTrigger(req *restful.Request, res *restfu
}
}
func (c *application) updateApplicationTrigger(req *restful.Request, res *restful.Response) {
var updateReq apis.UpdateApplicationTriggerRequest
if err := req.ReadEntity(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application)
trigger, err := c.ApplicationService.UpdateApplicationTrigger(req.Request.Context(), app, req.PathParameter("token"), updateReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(trigger); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (c *application) publishApplicationTemplate(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application)
base, err := c.ApplicationService.PublishApplicationTemplate(req.Request.Context(), app)

View File

@@ -274,6 +274,23 @@ func ConvertPermission2DTO(permission *model.Permission) *apisv1.PermissionBase
}
}
// ConvertTrigger2DTO convert trigger model to the DTO
func ConvertTrigger2DTO(trigger model.ApplicationTrigger) *apisv1.ApplicationTriggerBase {
return &apisv1.ApplicationTriggerBase{
WorkflowName: trigger.WorkflowName,
Name: trigger.Name,
Alias: trigger.Alias,
Description: trigger.Description,
Type: trigger.Type,
PayloadType: trigger.PayloadType,
Token: trigger.Token,
Registry: trigger.Registry,
ComponentName: trigger.ComponentName,
CreateTime: trigger.CreateTime,
UpdateTime: trigger.UpdateTime,
}
}
func convertBool(b *bool) bool {
if b == nil {
return false

View File

@@ -512,6 +512,16 @@ type CreateApplicationTriggerRequest struct {
Registry string `json:"registry,omitempty" optional:"true"`
}
// UpdateApplicationTriggerRequest update application trigger
type UpdateApplicationTriggerRequest struct {
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
WorkflowName string `json:"workflowName"`
PayloadType string `json:"payloadType" validate:"checkpayloadtype"`
ComponentName string `json:"componentName,omitempty" optional:"true"`
Registry string `json:"registry,omitempty" optional:"true"`
}
// ApplicationTriggerBase application trigger base model
type ApplicationTriggerBase struct {
Name string `json:"name"`
@@ -522,6 +532,7 @@ type ApplicationTriggerBase struct {
PayloadType string `json:"payloadType"`
Token string `json:"token"`
ComponentName string `json:"componentName,omitempty"`
Registry string `json:"registry"`
CreateTime time.Time `json:"createTime"`
UpdateTime time.Time `json:"updateTime"`
}

View File

@@ -234,7 +234,7 @@ func (n *pipeline) GetWebServiceRoute() *restful.WebService {
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")).
Param(ws.QueryParameter("detailed", "query pipelines with detail").DataType("boolean").DefaultValue("true")).
Returns(200, "OK", apis.ListPipelineResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.ListPipelineResponse{}).Do(meta))

View File

@@ -69,9 +69,19 @@ func (h repository) GetWebServiceRoute() *restful.WebService {
Writes([]string{}))
// List available chart versions
ws.Route(ws.GET("/charts/{chart}/versions").To(h.listVersions).
ws.Route(ws.GET("/chart/versions").To(h.listVersionsFromQuery).
Doc("list versions").
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("chart", "helm chart").DataType("string").Required(true)).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string").Required(true)).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", v1.ChartVersionListResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]string{}))
ws.Route(ws.GET("/charts/{chart}/versions").To(h.listChartVersions).
Doc("list versions").Deprecate().
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string")).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", v1.ChartVersionListResponse{}).
@@ -79,14 +89,26 @@ func (h repository) GetWebServiceRoute() *restful.WebService {
Writes([]string{}))
// List available chart versions
ws.Route(ws.GET("/charts/{chart}/versions/{version}/values").To(h.chartValues).
ws.Route(ws.GET("/chart/values").To(h.chartValues).
Doc("get chart value").
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("chart", "helm chart").DataType("string").Required(true)).
Param(ws.QueryParameter("version", "helm chart version").DataType("string").Required(true)).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string").Required(true)).
Param(ws.QueryParameter("repoType", "helm repository type").DataType("string").Required(true)).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", "").
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(map[string]string{}))
ws.Route(ws.GET("/charts/{chart}/versions/{version}/values").To(h.getChartValues).
Doc("get chart value").Deprecate().
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string")).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", map[string]interface{}{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]string{}))
Writes(map[string]interface{}{}))
ws.Route(ws.GET("/image/repos").To(h.getImageRepos).
Doc("get the oci repos").
@@ -132,9 +154,9 @@ func (h repository) listCharts(req *restful.Request, res *restful.Response) {
}
}
func (h repository) listVersions(req *restful.Request, res *restful.Response) {
func (h repository) listVersionsFromQuery(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
chartName := req.PathParameter("chart")
chartName := req.QueryParameter("chart")
secName := req.QueryParameter("secretName")
skipCache, err := isSkipCache(req)
if err != nil {
@@ -154,7 +176,7 @@ func (h repository) listVersions(req *restful.Request, res *restful.Response) {
}
}
func (h repository) chartValues(req *restful.Request, res *restful.Response) {
func (h repository) getChartValues(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
secName := req.QueryParameter("secretName")
chartName := req.PathParameter("chart")
@@ -165,12 +187,57 @@ func (h repository) chartValues(req *restful.Request, res *restful.Response) {
return
}
versions, err := h.HelmService.GetChartValues(req.Request.Context(), url, chartName, version, secName, skipCache)
values, err := h.HelmService.GetChartValues(req.Request.Context(), url, chartName, version, secName, "helm", skipCache)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
err = res.WriteEntity(versions)
err = res.WriteEntity(values)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (h repository) listChartVersions(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
chartName := req.PathParameter("chart")
secName := req.QueryParameter("secretName")
skipCache, err := isSkipCache(req)
if err != nil {
bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter)
return
}
versions, err := h.HelmService.ListChartVersions(req.Request.Context(), url, chartName, secName, skipCache)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
err = res.WriteEntity(v1.ChartVersionListResponse{Versions: versions})
if err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (h repository) chartValues(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
secName := req.QueryParameter("secretName")
chartName := req.QueryParameter("chart")
version := req.QueryParameter("version")
repoType := req.QueryParameter("repoType")
skipCache, err := isSkipCache(req)
if err != nil {
bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter)
return
}
values, err := h.HelmService.ListChartValuesFiles(req.Request.Context(), url, chartName, version, secName, repoType, skipCache)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
err = res.WriteEntity(values)
if err != nil {
bcode.ReturnError(req, res, err)
return

View File

@@ -69,7 +69,7 @@ func ValidatePayloadType(fl validator.FieldLevel) bool {
// ValidateName custom check name field
func ValidateName(fl validator.FieldLevel) bool {
value := fl.Field().String()
if len(value) > 32 || len(value) < 2 {
if len(value) > 31 || len(value) < 2 {
return false
}
return nameRegexp.MatchString(value)

View File

@@ -23,21 +23,21 @@ var (
// ErrNoConfigOrTarget means there is no target or config when creating the distribution.
ErrNoConfigOrTarget = NewBcode(400, 16002, "you must specify the config name and destination to distribute")
// ErrConfigExist means the config is exist
ErrConfigExist = NewBcode(400, 16003, "the config name is exist")
// ErrConfigExist means the config does exist
ErrConfigExist = NewBcode(400, 16003, "the config name does exist")
// ErrChangeTemplate the template of the config can not be change
ErrChangeTemplate = NewBcode(400, 16004, "the template of the config can not be change")
// ErrChangeTemplate the template of the config can not be changed
ErrChangeTemplate = NewBcode(400, 16004, "the template of the config can not be changed")
// ErrTemplateNotFound means the template is not exist
ErrTemplateNotFound = NewBcode(404, 16005, "the template is not exist")
// ErrTemplateNotFound means the template does not exist
ErrTemplateNotFound = NewBcode(404, 16005, "the template does not exist")
// ErrConfigNotFound means the config is not exist
ErrConfigNotFound = NewBcode(404, 16006, "the config is not exist")
// ErrConfigNotFound means the config does not exist
ErrConfigNotFound = NewBcode(404, 16006, "the config does not exist")
// ErrNotFoundDistribution means the distribution is not exist
ErrNotFoundDistribution = NewBcode(404, 16007, "the distribution is not exist")
// ErrNotFoundDistribution means the distribution does not exist
ErrNotFoundDistribution = NewBcode(404, 16007, "the distribution does not exist")
// ErrChangeSecretType the secret type of the config can not be change
ErrChangeSecretType = NewBcode(400, 16008, "the secret type of the config can not be change")
// ErrChangeSecretType the secret type of the config can not be changed
ErrChangeSecretType = NewBcode(400, 16008, "the secret type of the config can not be changed")
)

View File

@@ -23,6 +23,7 @@ import (
"github.com/kubevela/workflow/pkg/cue/process"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/apis/types"
velaprocess "github.com/oam-dev/kubevela/pkg/cue/process"
)
@@ -32,7 +33,7 @@ func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error {
for _, wl := range a.Workloads {
// because helm & kube schematic has no CUE template
// it only validates CUE schematic workload
if wl.CapabilityCategory != types.CUECategory {
if wl.CapabilityCategory != types.CUECategory || wl.Type == v1alpha1.RefObjectsComponentType {
continue
}
ctxData := GenerateContextDataFromAppFile(a, wl.Name)

View File

@@ -76,23 +76,23 @@ var ErrSensitiveConfig = errors.New("the config is sensitive")
// ErrNoConfigOrTarget means the config or the target is empty.
var ErrNoConfigOrTarget = errors.New("you must specify the config name and destination to distribute")
// ErrNotFoundDistribution means the app of the distribution is not exist.
var ErrNotFoundDistribution = errors.New("the distribution is not found")
// ErrNotFoundDistribution means the app of the distribution does not exist.
var ErrNotFoundDistribution = errors.New("the distribution does not found")
// ErrConfigExist means the config is exist.
var ErrConfigExist = errors.New("the config is exist")
// ErrConfigExist means the config does exist.
var ErrConfigExist = errors.New("the config does exist")
// ErrConfigNotFound means the config is not exist
var ErrConfigNotFound = errors.New("the config is not exist")
// ErrConfigNotFound means the config does not exist
var ErrConfigNotFound = errors.New("the config does not exist")
// ErrTemplateNotFound means the template is not exist
var ErrTemplateNotFound = errors.New("the template is not exist")
// ErrTemplateNotFound means the template does not exist
var ErrTemplateNotFound = errors.New("the template does not exist")
// ErrChangeTemplate means the template of the config can not be change
var ErrChangeTemplate = errors.New("the template of the config can not be change")
// ErrChangeTemplate means the template of the config can not be changed
var ErrChangeTemplate = errors.New("the template of the config can not be changed")
// ErrChangeSecretType means the secret type of the config can not be change
var ErrChangeSecretType = errors.New("the secret type of the config can not be change")
// ErrChangeSecretType means the secret type of the config can not be changed
var ErrChangeSecretType = errors.New("the secret type of the config can not be changed")
// NamespacedName the namespace and name model
type NamespacedName struct {
@@ -206,14 +206,37 @@ type Factory interface {
MergeDistributionStatus(ctx context.Context, config *Config, namespace string) error
}
// Dispatcher is a client for apply resources.
type Dispatcher func(context.Context, []*unstructured.Unstructured, []apply.ApplyOption) error
// NewConfigFactory create a config factory instance
func NewConfigFactory(cli client.Client) Factory {
return &kubeConfigFactory{cli: cli, apiApply: apply.NewAPIApplicator(cli)}
return &kubeConfigFactory{cli: cli, apiApply: defaultDispatcher(cli)}
}
// NewConfigFactoryWithDispatcher create a config factory instance with a specified dispatcher
func NewConfigFactoryWithDispatcher(cli client.Client, ds Dispatcher) Factory {
if ds == nil {
ds = defaultDispatcher(cli)
}
return &kubeConfigFactory{cli: cli, apiApply: ds}
}
func defaultDispatcher(cli client.Client) Dispatcher {
api := apply.NewAPIApplicator(cli)
return func(ctx context.Context, manifests []*unstructured.Unstructured, ao []apply.ApplyOption) error {
for _, m := range manifests {
if err := api.Apply(ctx, m, ao...); err != nil {
return err
}
}
return nil
}
}
type kubeConfigFactory struct {
cli client.Client
apiApply *apply.APIApplicator
apiApply Dispatcher
}
// ParseTemplate parse a config template instance form the cue script
@@ -307,7 +330,14 @@ func (k *kubeConfigFactory) CreateOrUpdateConfigTemplate(ctx context.Context, ns
if ns != "" {
it.ConfigMap.Namespace = ns
}
return k.apiApply.Apply(ctx, it.ConfigMap, apply.DisableUpdateAnnotation(), apply.Quiet())
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(it.ConfigMap)
if err != nil {
return fmt.Errorf("fail to convert configmap to unstructured: %w", err)
}
us := &unstructured.Unstructured{Object: obj}
us.SetAPIVersion("v1")
us.SetKind("ConfigMap")
return k.apiApply(ctx, []*unstructured.Unstructured{us}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()})
}
func convertConfigMap2Template(cm v1.ConfigMap) (*Template, error) {
@@ -562,11 +592,20 @@ func (k *kubeConfigFactory) CreateOrUpdateConfig(ctx context.Context, i *Config,
return ErrChangeSecretType
}
}
if err := k.apiApply.Apply(ctx, i.Secret, apply.Quiet()); err != nil {
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(i.Secret)
if err != nil {
return fmt.Errorf("fail to convert secret to unstructured: %w", err)
}
us := &unstructured.Unstructured{Object: obj}
us.SetAPIVersion("v1")
us.SetKind("Secret")
if err := k.apiApply(ctx, []*unstructured.Unstructured{us}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()}); err != nil {
return fmt.Errorf("fail to apply the secret: %w", err)
}
for key, obj := range i.OutputObjects {
if err := k.apiApply.Apply(ctx, obj, apply.Quiet()); err != nil {
if err := k.apiApply(ctx, []*unstructured.Unstructured{obj}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()}); err != nil {
return fmt.Errorf("fail to apply the object %s: %w", key, err)
}
}
@@ -768,7 +807,15 @@ func (k *kubeConfigFactory) CreateOrUpdateDistribution(ctx context.Context, ns,
Policies: policies,
},
}
return k.apiApply.Apply(ctx, distribution, apply.Quiet())
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(distribution)
if err != nil {
return fmt.Errorf("fail to convert application to unstructured: %w", err)
}
us := &unstructured.Unstructured{Object: obj}
us.SetAPIVersion(v1beta1.SchemeGroupVersion.String())
us.SetKind(v1beta1.ApplicationKind)
return k.apiApply(ctx, []*unstructured.Unstructured{us}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()})
}
func (k *kubeConfigFactory) ListDistributions(ctx context.Context, ns string) ([]*Distribution, error) {

View File

@@ -0,0 +1,147 @@
/*
Copyright 2023 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package provider
import (
"errors"
"strings"
"sigs.k8s.io/controller-runtime/pkg/client"
monitorContext "github.com/kubevela/pkg/monitor/context"
wfContext "github.com/kubevela/workflow/pkg/context"
"github.com/kubevela/workflow/pkg/cue/model/value"
"github.com/kubevela/workflow/pkg/types"
"github.com/oam-dev/kubevela/pkg/config"
)
const (
// ProviderName is provider name
ProviderName = "config"
)
// ErrRequestInvalid means the request is invalid
var ErrRequestInvalid = errors.New("the request is in valid")
type provider struct {
factory config.Factory
}
// CreateConfigProperties the request body for creating a config
type CreateConfigProperties struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Template string `json:"template,omitempty"`
Config map[string]interface{} `json:"config"`
}
// Response the response body
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
}
func (p *provider) Create(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
var ccp CreateConfigProperties
if err := v.UnmarshalTo(&ccp); err != nil {
return ErrRequestInvalid
}
name := ccp.Template
namespace := "vela-system"
if strings.Contains(ccp.Template, "/") {
namespacedName := strings.SplitN(ccp.Template, "/", 2)
namespace = namespacedName[0]
name = namespacedName[1]
}
configItem, err := p.factory.ParseConfig(ctx.GetContext(), config.NamespacedName{
Name: name,
Namespace: namespace,
}, config.Metadata{
NamespacedName: config.NamespacedName{
Name: ccp.Name,
Namespace: ccp.Namespace,
},
Properties: ccp.Config,
})
if err != nil {
return err
}
return p.factory.CreateOrUpdateConfig(ctx.GetContext(), configItem, ccp.Namespace)
}
func (p *provider) Read(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
var nn config.NamespacedName
if err := v.UnmarshalTo(&nn); err != nil {
return ErrRequestInvalid
}
content, err := p.factory.ReadConfig(ctx.GetContext(), nn.Namespace, nn.Name)
if err != nil {
return err
}
return v.FillObject(content, "config")
}
func (p *provider) List(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
template, err := v.GetString("template")
if err != nil {
return ErrRequestInvalid
}
namespace, err := v.GetString("namespace")
if err != nil {
return ErrRequestInvalid
}
if strings.Contains(template, "/") {
namespacedName := strings.SplitN(template, "/", 2)
template = namespacedName[1]
}
configs, err := p.factory.ListConfigs(ctx.GetContext(), namespace, template, "", false)
if err != nil {
return err
}
var contents = []map[string]interface{}{}
for _, config := range configs {
contents = append(contents, map[string]interface{}{
"name": config.Name,
"alias": config.Alias,
"description": config.Description,
"config": config.Properties,
})
}
return v.FillObject(contents, "configs")
}
func (p *provider) Delete(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
var nn config.NamespacedName
if err := v.UnmarshalTo(&nn); err != nil {
return errors.New("the request is in valid")
}
return p.factory.DeleteConfig(ctx.GetContext(), nn.Namespace, nn.Name)
}
// Install register handlers to provider discover.
func Install(p types.Providers, cli client.Client, apply config.Dispatcher) {
prd := &provider{
factory: config.NewConfigFactoryWithDispatcher(cli, apply),
}
p.Register(ProviderName, map[string]types.Handler{
"create": prd.Create,
"read": prd.Read,
"list": prd.List,
"delete": prd.Delete,
})
}

View File

@@ -0,0 +1,237 @@
/*
Copyright 2023 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package provider
import (
"context"
"strings"
"testing"
"time"
monitorContext "github.com/kubevela/pkg/monitor/context"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
wfContext "github.com/kubevela/workflow/pkg/context"
"github.com/kubevela/workflow/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/config"
)
var cfg *rest.Config
var k8sClient client.Client
var testEnv *envtest.Environment
var scheme = runtime.NewScheme()
var p *provider
func TestProvider(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Test Config Suite")
}
var _ = BeforeSuite(func(done Done) {
By("Bootstrapping test environment")
testEnv = &envtest.Environment{
ControlPlaneStartTimeout: time.Minute,
ControlPlaneStopTimeout: time.Minute,
UseExistingCluster: pointer.BoolPtr(false),
}
var err error
cfg, err = testEnv.Start()
Expect(err).ToNot(HaveOccurred())
Expect(cfg).ToNot(BeNil())
Expect(clientgoscheme.AddToScheme(scheme)).Should(BeNil())
// +kubebuilder:scaffold:scheme
By("Create the k8s client")
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).ToNot(HaveOccurred())
Expect(k8sClient).ToNot(BeNil())
p = &provider{
factory: config.NewConfigFactory(k8sClient),
}
close(done)
}, 120)
var _ = AfterSuite(func() {
By("Tearing down the test environment")
err := testEnv.Stop()
Expect(err).ToNot(HaveOccurred())
})
var _ = Describe("Test the config provider", func() {
It("test creating a config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "hub-kubevela"
namespace: "default"
template: "default/test-image-registry"
config: {
registry: "hub.kubevela.net"
}
`, nil, "")
Expect(err).ToNot(HaveOccurred())
err = p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)
Expect(strings.Contains(err.Error(), "the template does not exist")).Should(BeTrue())
template, err := p.factory.ParseTemplate("test-image-registry", []byte(templateContent))
Expect(err).ToNot(HaveOccurred())
Expect(p.factory.CreateOrUpdateConfigTemplate(context.TODO(), "default", template)).ToNot(HaveOccurred())
Expect(p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
})
It("test creating a config without the template", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "www-kubevela"
namespace: "default"
config: {
url: "kubevela.net"
}
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
})
It("test listing the config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
namespace: "default"
template: "test-image-registry"
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.List(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
configs, err := v.LookupValue("configs")
Expect(err).ToNot(HaveOccurred())
var contents []map[string]interface{}
Expect(configs.UnmarshalTo(&contents)).ToNot(HaveOccurred())
Expect(len(contents)).To(Equal(1))
Expect(contents[0]["config"].(map[string]interface{})["registry"]).To(Equal("hub.kubevela.net"))
})
It("test reading the config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "hub-kubevela"
namespace: "default"
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.Read(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
registry, err := v.GetString("config", "registry")
Expect(err).ToNot(HaveOccurred())
Expect(registry).To(Equal("hub.kubevela.net"))
})
It("test deleting the config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "hub-kubevela"
namespace: "default"
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.Delete(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
configs, err := p.factory.ListConfigs(context.Background(), "default", "", "", false)
Expect(err).ToNot(HaveOccurred())
Expect(len(configs)).To(Equal(1))
Expect(configs[0].Properties["url"]).To(Equal("kubevela.net"))
})
})
var templateContent = `
import (
"encoding/base64"
"encoding/json"
"strconv"
)
metadata: {
name: "image-registry"
alias: "Image Registry"
scope: "project"
description: "Config information to authenticate image registry"
sensitive: false
}
template: {
output: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: context.name
namespace: context.namespace
labels: {
"config.oam.dev/catalog": "velacore-config"
"config.oam.dev/type": "image-registry"
}
}
if parameter.auth != _|_ {
type: "kubernetes.io/dockerconfigjson"
}
if parameter.auth == _|_ {
type: "Opaque"
}
stringData: {
if parameter.auth != _|_ && parameter.auth.username != _|_ {
".dockerconfigjson": json.Marshal({
"auths": (parameter.registry): {
"username": parameter.auth.username
"password": parameter.auth.password
if parameter.auth.email != _|_ {
"email": parameter.auth.email
}
"auth": base64.Encode(null, (parameter.auth.username + ":" + parameter.auth.password))
}
})
}
if parameter.insecure != _|_ {
"insecure-skip-verify": strconv.FormatBool(parameter.insecure)
}
if parameter.useHTTP != _|_ {
"protocol-use-http": strconv.FormatBool(parameter.useHTTP)
}
}
}
parameter: {
// +usage=Image registry FQDN, such as: index.docker.io
registry: *"index.docker.io" | string
// +usage=Authenticate the image registry
auth?: {
// +usage=Private Image registry username
username: string
// +usage=Private Image registry password
password: string
// +usage=Private Image registry email
email?: string
}
// +usage=For the registry server that uses the self-signed certificate
insecure?: bool
// +usage=For the registry server that uses the HTTP protocol
useHTTP?: bool
}
}
`

View File

@@ -193,7 +193,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
app.Status.SetConditions(condition.ReadyCondition(common.PolicyCondition.String()))
r.Recorder.Event(app, event.Normal(velatypes.ReasonPolicyGenerated, velatypes.MessagePolicyGenerated))
workflowInstance, runners, err := handler.GenerateApplicationSteps(logCtx, app, appParser, appFile, handler.currentAppRev)
handler.CheckWorkflowRestart(logCtx, app)
workflowInstance, runners, err := handler.GenerateApplicationSteps(logCtx, app, appParser, appFile)
if err != nil {
logCtx.Error(err, "[handle workflow]")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedWorkflow, err))
@@ -449,15 +451,12 @@ func (r *Reconciler) doWorkflowFinish(logCtx monitorContext.Context, app *v1beta
wfContext.CleanupMemoryStore(app.Name, app.Namespace)
t := time.Since(app.Status.Workflow.StartTime.Time).Seconds()
metrics.WorkflowFinishedTimeHistogram.WithLabelValues(string(state)).Observe(t)
switch state {
case workflowv1alpha1.WorkflowStateSucceeded:
if state == workflowv1alpha1.WorkflowStateSucceeded {
app.Status.SetConditions(condition.ReadyCondition(common.WorkflowCondition.String()))
r.Recorder.Event(app, event.Normal(velatypes.ReasonApplied, velatypes.MessageWorkflowFinished))
handler.UpdateApplicationRevisionStatus(logCtx, handler.currentAppRev, true, app.Status.Workflow)
logCtx.Info("Application manifests has applied by workflow successfully")
default:
handler.UpdateApplicationRevisionStatus(logCtx, handler.latestAppRev, false, app.Status.Workflow)
}
handler.UpdateApplicationRevisionStatus(logCtx, handler.currentAppRev, app.Status.Workflow)
logCtx.Info("Application manifests has applied by workflow successfully")
}
func hasHealthCheckPolicy(policies []*appfile.Workload) bool {

View File

@@ -719,6 +719,76 @@ var _ = Describe("Test Application Controller", func() {
}, appRevision)).Should(BeNil())
})
It("revision should be updated if the workflow is restarted", func() {
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "vela-test-app-restart-revision",
},
}
Expect(k8sClient.Create(ctx, ns)).Should(BeNil())
app := &v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "vela-test-app-restart-revision",
Namespace: "vela-test-app-restart-revision",
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{},
Workflow: &v1beta1.Workflow{
Steps: []workflowv1alpha1.WorkflowStep{
{
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
Name: "suspend",
Type: "suspend",
},
},
},
},
},
}
Expect(k8sClient.Create(ctx, app.DeepCopy())).Should(BeNil())
appKey := client.ObjectKey{
Name: app.Name,
Namespace: app.Namespace,
}
testutil.ReconcileOnceAfterFinalizer(reconciler, reconcile.Request{NamespacedName: appKey})
By("Check Application Created with the correct revision")
curApp := &v1beta1.Application{}
Expect(k8sClient.Get(ctx, appKey, curApp)).Should(BeNil())
Expect(curApp.Status.Phase).Should(Equal(common.ApplicationWorkflowSuspending))
Expect(curApp.Status.LatestRevision).ShouldNot(BeNil())
Expect(curApp.Status.LatestRevision.Revision).Should(BeEquivalentTo(1))
appRevision := &v1beta1.ApplicationRevision{}
Expect(k8sClient.Get(ctx, client.ObjectKey{
Namespace: app.Namespace,
Name: curApp.Status.LatestRevision.Name,
}, appRevision)).Should(BeNil())
Expect(appRevision.Status.Workflow).Should(BeNil())
// update the app
curApp.Spec.Workflow.Steps[0].DependsOn = []string{"invalid"}
Expect(k8sClient.Update(ctx, curApp)).Should(BeNil())
Expect(k8sClient.Get(ctx, appKey, curApp)).Should(BeNil())
testutil.ReconcileOnce(reconciler, reconcile.Request{NamespacedName: appKey})
Expect(k8sClient.Get(ctx, client.ObjectKey{
Namespace: app.Namespace,
Name: curApp.Status.LatestRevision.Name,
}, appRevision)).Should(BeNil())
Expect(appRevision.Status.Workflow).ShouldNot(BeNil())
Expect(appRevision.Status.Workflow.Finished).Should(BeTrue())
Expect(appRevision.Status.Workflow.Terminated).Should(BeTrue())
Expect(appRevision.Status.Workflow.EndTime.IsZero()).ShouldNot(BeTrue())
Expect(appRevision.Status.Workflow.Phase).Should(Equal(workflowv1alpha1.WorkflowStateSuspending))
By("Delete Application, clean the resource")
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
})
It("revision should exist in created workload render by context.appRevision", func() {
ns := &corev1.Namespace{

View File

@@ -25,7 +25,9 @@ import (
pkgmulticluster "github.com/kubevela/pkg/multicluster"
utilfeature "k8s.io/apiserver/pkg/util/feature"
configprovider "github.com/oam-dev/kubevela/pkg/config/provider"
"github.com/oam-dev/kubevela/pkg/features"
"github.com/oam-dev/kubevela/pkg/utils/apply"
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/pkg/errors"
@@ -83,18 +85,24 @@ var (
func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
app *v1beta1.Application,
appParser *appfile.Parser,
af *appfile.Appfile,
appRev *v1beta1.ApplicationRevision) (*wfTypes.WorkflowInstance, []wfTypes.TaskRunner, error) {
af *appfile.Appfile) (*wfTypes.WorkflowInstance, []wfTypes.TaskRunner, error) {
appRev := h.currentAppRev
appLabels := map[string]string{
oam.LabelAppName: app.Name,
oam.LabelAppNamespace: app.Namespace,
}
handlerProviders := providers.NewProviders()
kube.Install(handlerProviders, h.r.Client,
map[string]string{
oam.LabelAppName: app.Name,
oam.LabelAppNamespace: app.Namespace,
}, &kube.Handlers{
Apply: h.Dispatch,
Delete: h.Delete,
})
kube.Install(handlerProviders, h.r.Client, appLabels, &kube.Handlers{
Apply: h.Dispatch,
Delete: h.Delete,
})
configprovider.Install(handlerProviders, h.r.Client, func(ctx context.Context, resources []*unstructured.Unstructured, applyOptions []apply.ApplyOption) error {
for _, res := range resources {
res.SetLabels(util.MergeMapOverrideWithDst(res.GetLabels(), appLabels))
}
return h.resourceKeeper.Dispatch(ctx, resources, applyOptions)
})
oamProvider.Install(handlerProviders, app, af, h.r.Client, h.applyComponentFunc(
appParser, appRev, af), h.renderComponentFunc(appParser, appRev, af))
pCtx := velaprocess.NewContext(generateContextDataFromApp(app, appRev.Name))
@@ -110,7 +118,7 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
})
query.Install(handlerProviders, h.r.Client, nil)
instance := generateWorkflowInstance(af, app, appRev.Name)
instance := generateWorkflowInstance(af, app)
executor.InitializeWorkflowInstance(instance)
runners, err := generator.GenerateRunners(ctx, instance, wfTypes.StepGeneratorOptions{
Providers: handlerProviders,
@@ -135,7 +143,7 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
return instance, runners, nil
}
// needRestart check if application workflow need restart and return the desired
// CheckWorkflowRestart check if application workflow need restart and return the desired
// rev to be set in status
// 1. If workflow status is empty, it means no previous running record, the
// workflow will restart (cold start)
@@ -144,8 +152,8 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
// 3. If workflow status is not empty, the desired rev will be the
// ApplicationRevision name. For backward compatibility, the legacy style
// <rev>:<hash> will be recognized and reduced into <rev>
func needRestart(app *v1beta1.Application, revName string) (string, bool) {
desiredRev, currentRev := revName, ""
func (h *AppHandler) CheckWorkflowRestart(ctx monitorContext.Context, app *v1beta1.Application) {
desiredRev, currentRev := h.currentAppRev.Name, ""
if app.Status.Workflow != nil {
currentRev = app.Status.Workflow.AppRevision
}
@@ -158,10 +166,40 @@ func needRestart(app *v1beta1.Application, revName string) (string, bool) {
currentRev = currentRev[:idx]
}
}
return desiredRev, currentRev == "" || desiredRev != currentRev
if currentRev != "" && desiredRev == currentRev {
return
}
// record in revision
if h.latestAppRev != nil && h.latestAppRev.Status.Workflow == nil && app.Status.Workflow != nil {
app.Status.Workflow.Terminated = true
app.Status.Workflow.Finished = true
if app.Status.Workflow.EndTime.IsZero() {
app.Status.Workflow.EndTime = metav1.Now()
}
h.UpdateApplicationRevisionStatus(ctx, h.latestAppRev, app.Status.Workflow)
}
// clean recorded resources info.
app.Status.Services = nil
app.Status.AppliedResources = nil
// clean conditions after render
var reservedConditions []condition.Condition
for i, cond := range app.Status.Conditions {
condTpy, err := common.ParseApplicationConditionType(string(cond.Type))
if err == nil {
if condTpy <= common.RenderCondition {
reservedConditions = append(reservedConditions, app.Status.Conditions[i])
}
}
}
app.Status.Conditions = reservedConditions
app.Status.Workflow = &common.WorkflowStatus{
AppRevision: desiredRev,
}
}
func generateWorkflowInstance(af *appfile.Appfile, app *v1beta1.Application, appRev string) *wfTypes.WorkflowInstance {
func generateWorkflowInstance(af *appfile.Appfile, app *v1beta1.Application) *wfTypes.WorkflowInstance {
instance := &wfTypes.WorkflowInstance{
WorkflowMeta: wfTypes.WorkflowMeta{
Name: af.Name,
@@ -183,27 +221,6 @@ func generateWorkflowInstance(af *appfile.Appfile, app *v1beta1.Application, app
Steps: af.WorkflowSteps,
Mode: af.WorkflowMode,
}
if desiredRev, nr := needRestart(app, appRev); nr {
// clean recorded resources info.
app.Status.Services = nil
app.Status.AppliedResources = nil
// clean conditions after render
var reservedConditions []condition.Condition
for i, cond := range app.Status.Conditions {
condTpy, err := common.ParseApplicationConditionType(string(cond.Type))
if err == nil {
if condTpy <= common.RenderCondition {
reservedConditions = append(reservedConditions, app.Status.Conditions[i])
}
}
}
app.Status.Conditions = reservedConditions
app.Status.Workflow = &common.WorkflowStatus{
AppRevision: desiredRev,
}
return instance
}
status := app.Status.Workflow
instance.Status = workflowv1alpha1.WorkflowRunStatus{
Mode: *af.WorkflowMode,

View File

@@ -112,13 +112,15 @@ var _ = Describe("Test Application workflow generator", func() {
Expect(err).Should(BeNil())
_, err = af.GeneratePolicyManifests(context.Background())
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).To(BeNil())
Expect(len(taskRunner)).Should(BeEquivalentTo(2))
Expect(taskRunner[0].Name()).Should(BeEquivalentTo("myweb1"))
@@ -154,13 +156,14 @@ var _ = Describe("Test Application workflow generator", func() {
Expect(err).Should(BeNil())
_, err = af.GeneratePolicyManifests(context.Background())
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).To(BeNil())
Expect(len(taskRunner)).Should(BeEquivalentTo(2))
Expect(taskRunner[0].Name()).Should(BeEquivalentTo("myweb1"))
@@ -276,13 +279,14 @@ var _ = Describe("Test Application workflow generator", func() {
}
af, err := appParser.GenerateAppFile(ctx, app)
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).To(BeNil())
Expect(len(taskRunner)).Should(BeEquivalentTo(2))
Expect(taskRunner[0].Name()).Should(BeEquivalentTo("myweb1"))
@@ -317,13 +321,14 @@ var _ = Describe("Test Application workflow generator", func() {
}
af, err := appParser.GenerateAppFile(ctx, app)
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).NotTo(BeNil())
})
@@ -355,13 +360,14 @@ var _ = Describe("Test Application workflow generator", func() {
}
af, err := appParser.GenerateAppFile(ctx, app)
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).NotTo(BeNil())
})
})

View File

@@ -1019,11 +1019,11 @@ func (h historiesByComponentRevision) Less(i, j int) bool {
}
// UpdateApplicationRevisionStatus update application revision status
func (h *AppHandler) UpdateApplicationRevisionStatus(ctx context.Context, appRev *v1beta1.ApplicationRevision, succeed bool, wfStatus *common.WorkflowStatus) {
func (h *AppHandler) UpdateApplicationRevisionStatus(ctx context.Context, appRev *v1beta1.ApplicationRevision, wfStatus *common.WorkflowStatus) {
if appRev == nil || DisableAllApplicationRevision {
return
}
appRev.Status.Succeeded = succeed
appRev.Status.Succeeded = wfStatus.Phase == workflowv1alpha1.WorkflowStateSucceeded
appRev.Status.Workflow = wfStatus
// Versioned the context backend values.

View File

@@ -121,8 +121,8 @@ func loggingApply(msg string, desired client.Object, quiet bool) {
klog.InfoS(msg, "name", d.GetName(), "resource", desired.GetObjectKind().GroupVersionKind().String())
}
// filterRecordForSpecial will filter special object that can reduce the record for "app.oam.dev/last-applied-configuration" annotation.
func filterRecordForSpecial(desired client.Object) bool {
// trimLastAppliedConfigurationForSpecialResources will filter special object that can reduce the record for "app.oam.dev/last-applied-configuration" annotation.
func trimLastAppliedConfigurationForSpecialResources(desired client.Object) bool {
if desired == nil {
return false
}
@@ -159,7 +159,7 @@ func (a *APIApplicator) Apply(ctx context.Context, desired client.Object, ao ...
if err != nil {
return err
}
applyAct := &applyAction{updateAnnotation: filterRecordForSpecial(desired)}
applyAct := &applyAction{updateAnnotation: trimLastAppliedConfigurationForSpecialResources(desired)}
existing, err := a.createOrGetExisting(ctx, applyAct, a.c, desired, ao...)
if err != nil {
return err
@@ -231,7 +231,7 @@ func createOrGetExisting(ctx context.Context, act *applyAction, c client.Client,
return nil, err
}
if act.readOnly {
return nil, fmt.Errorf("cannot create %s (%s) in read-only mode", desired.GetObjectKind().GroupVersionKind().Kind, desired.GetName())
return nil, fmt.Errorf("%s (%s) is marked as read-only but does not exist. You should check the existence of the resource or remove the read-only policy", desired.GetObjectKind().GroupVersionKind().Kind, desired.GetName())
}
if act.updateAnnotation {
if err := addLastAppliedConfigAnnotation(desired); err != nil {

View File

@@ -574,15 +574,15 @@ func TestFilterSpecialAnn(t *testing.T) {
var sc = &corev1.Secret{}
var dp = &appsv1.Deployment{}
var crd = &v1.CustomResourceDefinition{}
assert.Equal(t, false, filterRecordForSpecial(cm))
assert.Equal(t, false, filterRecordForSpecial(sc))
assert.Equal(t, false, filterRecordForSpecial(crd))
assert.Equal(t, true, filterRecordForSpecial(dp))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(cm))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(sc))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(crd))
assert.Equal(t, true, trimLastAppliedConfigurationForSpecialResources(dp))
dp.Annotations = map[string]string{oam.AnnotationLastAppliedConfig: "-"}
assert.Equal(t, false, filterRecordForSpecial(dp))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(dp))
dp.Annotations = map[string]string{oam.AnnotationLastAppliedConfig: "skip"}
assert.Equal(t, false, filterRecordForSpecial(dp))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(dp))
dp.Annotations = map[string]string{oam.AnnotationLastAppliedConfig: "xxx"}
assert.Equal(t, true, filterRecordForSpecial(dp))
assert.Equal(t, true, trimLastAppliedConfigurationForSpecialResources(dp))
}

View File

@@ -164,7 +164,7 @@ func getOriginalConfiguration(obj runtime.Object) ([]byte, error) {
return nil, nil
}
original, ok := annots[oam.AnnotationLastAppliedConfig]
if !ok {
if !ok || original == "-" || original == "skip" {
return nil, nil
}
return []byte(original), nil

View File

@@ -24,6 +24,7 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"strings"
"time"
@@ -32,6 +33,9 @@ import (
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/downloader"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/kube"
"helm.sh/helm/v3/pkg/release"
relutil "helm.sh/helm/v3/pkg/releaseutil"
@@ -56,6 +60,12 @@ const (
valuesPatten = "repoUrl: %s, chart: %s, version: %s"
)
// ChartValues contain all values files in chart and default chart values
type ChartValues struct {
Data map[string]string
Values map[string]interface{}
}
// Helper provides helper functions for common Helm operations
type Helper struct {
cache *utils2.MemoryCacheStore
@@ -309,12 +319,22 @@ func (h *Helper) ListChartsFromRepo(repoURL string, skipCache bool, opts *common
}
// GetValuesFromChart will extract the parameter from a helm chart
func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version string, skipCache bool, opts *common.HTTPOption) (map[string]interface{}, error) {
func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version string, skipCache bool, repoType string, opts *common.HTTPOption) (*ChartValues, error) {
if h.cache != nil && !skipCache {
if v := h.cache.Get(fmt.Sprintf(valuesPatten, repoURL, chartName, version)); v != nil {
return v.(map[string]interface{}), nil
return v.(*ChartValues), nil
}
}
if repoType == "oci" {
v, err := fetchChartValuesFromOciRepo(repoURL, chartName, version, opts)
if err != nil {
return nil, err
}
if h.cache != nil {
h.cache.Put(fmt.Sprintf(valuesPatten, repoURL, chartName, version), v, 20*time.Minute)
}
return v, nil
}
i, err := h.GetIndexInfo(repoURL, skipCache, opts)
if err != nil {
return nil, err
@@ -334,10 +354,17 @@ func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version st
if err != nil {
continue
}
if h.cache != nil {
h.cache.Put(fmt.Sprintf(valuesPatten, repoURL, chartName, version), c.Values, calculateCacheTimeFromIndex(len(i.Entries)))
v := &ChartValues{
Data: loadValuesYamlFile(c),
Values: c.Values,
}
return c.Values, nil
if err != nil {
return nil, err
}
if h.cache != nil {
h.cache.Put(fmt.Sprintf(valuesPatten, repoURL, chartName, version), v, calculateCacheTimeFromIndex(len(i.Entries)))
}
return v, nil
}
return nil, fmt.Errorf("cannot load chart from chart repo")
}
@@ -351,3 +378,49 @@ func calculateCacheTimeFromIndex(length int) time.Duration {
}
return cacheTime
}
// nolint
func fetchChartValuesFromOciRepo(repoURL string, chartName string, version string, opts *common.HTTPOption) (*ChartValues, error) {
d := downloader.ChartDownloader{
Verify: downloader.VerifyNever,
Getters: getter.All(cli.New()),
}
if opts != nil {
d.Options = append(d.Options, getter.WithInsecureSkipVerifyTLS(opts.InsecureSkipTLS),
getter.WithTLSClientConfig(opts.CertFile, opts.KeyFile, opts.CaFile),
getter.WithBasicAuth(opts.Username, opts.Password))
}
var err error
dest, err := os.MkdirTemp("", "helm-")
if err != nil {
return nil, errors.Wrap(err, "failed to fetch values file")
}
defer os.RemoveAll(dest)
chartRef := fmt.Sprintf("%s/%s", repoURL, chartName)
saved, _, err := d.DownloadTo(chartRef, version, dest)
if err != nil {
return nil, err
}
c, err := loader.Load(saved)
if err != nil {
return nil, errors.Wrap(err, "failed to fetch values file")
}
return &ChartValues{
Data: loadValuesYamlFile(c),
Values: c.Values,
}, nil
}
func loadValuesYamlFile(chart *chart.Chart) map[string]string {
result := map[string]string{}
re := regexp.MustCompile(`.*yaml$`)
for _, f := range chart.Raw {
if re.MatchString(f.Name) && !strings.Contains(f.Name, "/") && f.Name != "Chart.yaml" {
result[f.Name] = string(f.Data)
}
}
return result
}

View File

@@ -114,9 +114,9 @@ var _ = Describe("Test helm helper", func() {
It("Test getValues from chart", func() {
helper := NewHelper()
values, err := helper.GetValuesFromChart("./testdata", "autoscalertrait", "0.2.0", true, nil)
values, err := helper.GetValuesFromChart("./testdata", "autoscalertrait", "0.2.0", true, "helm", nil)
Expect(err).Should(BeNil())
Expect(values).ShouldNot(BeEmpty())
Expect(values).ShouldNot(BeNil())
})
})

View File

@@ -92,12 +92,26 @@ func MergeNoConflictLabels(labels map[string]string) MutateOption {
// CreateOrUpdateNamespace will create a namespace if not exist, it will also update a namespace if exists
// It will report an error if the labels conflict while it will override the annotations
func CreateOrUpdateNamespace(ctx context.Context, kubeClient client.Client, name string, options ...MutateOption) error {
err := CreateNamespace(ctx, kubeClient, name, options...)
// only if namespace don't have the env label that we need to update it
if apierrors.IsAlreadyExists(err) {
return UpdateNamespace(ctx, kubeClient, name, options...)
ns, err := GetNamespace(ctx, kubeClient, name)
switch {
case err == nil:
return PatchNamespace(ctx, kubeClient, ns, options...)
case apierrors.IsNotFound(err):
return CreateNamespace(ctx, kubeClient, name, options...)
default:
return err
}
return err
}
// PatchNamespace will patch a namespace
func PatchNamespace(ctx context.Context, kubeClient client.Client, ns *corev1.Namespace, options ...MutateOption) error {
original := ns.DeepCopy()
for _, op := range options {
if err := op(ns); err != nil {
return err
}
}
return kubeClient.Patch(ctx, ns, client.MergeFrom(original))
}
// CreateNamespace will create a namespace with mutate option

View File

@@ -108,6 +108,15 @@ func init() {
}),
GroupResourceType: GroupResourceType{Group: "apps", Kind: "DaemonSet"},
},
ChildrenResourcesRule{
GroupResourceType: GroupResourceType{Group: "batch", Kind: "Job"},
SubResources: buildSubResources([]*SubResourceSelector{
{
ResourceType: ResourceType{APIVersion: "v1", Kind: "Pod"},
listOptions: defaultWorkloadLabelListOption,
},
}),
},
ChildrenResourcesRule{
GroupResourceType: GroupResourceType{Group: "", Kind: "Service"},
SubResources: buildSubResources([]*SubResourceSelector{

View File

@@ -72,8 +72,8 @@ func NewAddAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *cob
Short: "Add an addon registry.",
Long: "Add an addon registry.",
Example: `add a helm repo registry: vela addon registry add --type=helm my-repo --endpoint=<URL>
add a github registry: vela addon registry add my-repo --type git --endpoint=<URL> --path=<ptah> --token=<git token>"
add a gitlab registry: vela addon registry add my-repo --type gitlab --endpoint=<URL> --gitlabRepoName=<repoName> --path=<path> --token=<git token>`,
add a github registry: vela addon registry add my-repo --type git --endpoint=<URL> --path=<ptah> --gitToken=<git token>"
add a gitlab registry: vela addon registry add my-repo --type gitlab --endpoint=<URL> --gitlabRepoName=<repoName> --path=<path> --gitToken=<git token>`,
RunE: func(cmd *cobra.Command, args []string) error {
registry, err := getRegistryFromArgs(cmd, args)
if err != nil {

View File

@@ -167,7 +167,7 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
addonArgs[pkgaddon.InstallerRuntimeOption] = map[string]interface{}{
"upgrade": false,
}
var addonName string
if file, err := os.Stat(addonOrDir); err == nil {
if !file.IsDir() {
return fmt.Errorf("%s is not addon dir", addonOrDir)
@@ -178,13 +178,13 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if err != nil {
return errors.Wrapf(err, "directory %s is invalid", addonOrDir)
}
name = filepath.Base(abs)
addonName = filepath.Base(abs)
if !yes2all {
if err := checkUninstallFromClusters(ctx, k8sClient, name, addonArgs); err != nil {
if err := checkUninstallFromClusters(ctx, k8sClient, addonName, addonArgs); err != nil {
return err
}
}
additionalInfo, err = enableAddonByLocal(ctx, name, addonOrDir, k8sClient, dc, config, addonArgs)
additionalInfo, err = enableAddonByLocal(ctx, addonName, addonOrDir, k8sClient, dc, config, addonArgs)
if err != nil {
return err
}
@@ -192,8 +192,12 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if filepath.IsAbs(addonOrDir) || strings.HasPrefix(addonOrDir, ".") || strings.HasSuffix(addonOrDir, "/") {
return fmt.Errorf("addon directory %s not found in local file system", addonOrDir)
}
_, addonName, err = splitSpecifyRegistry(name)
if err != nil {
return fmt.Errorf("failed to split addonName and addonRegistry: %w", err)
}
if !yes2all {
if err := checkUninstallFromClusters(ctx, k8sClient, name, addonArgs); err != nil {
if err := checkUninstallFromClusters(ctx, k8sClient, addonName, addonArgs); err != nil {
return err
}
}
@@ -205,8 +209,8 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if dryRun {
return nil
}
fmt.Printf("Addon %s enabled successfully.\n", name)
AdditionalEndpointPrinter(ctx, c, k8sClient, name, additionalInfo, false)
fmt.Printf("Addon %s enabled successfully.\n", addonName)
AdditionalEndpointPrinter(ctx, c, k8sClient, addonName, additionalInfo, false)
return nil
},
}

View File

@@ -17,6 +17,7 @@ limitations under the License.
package cli
import (
"context"
_ "embed"
"encoding/json"
"fmt"
@@ -31,7 +32,9 @@ import (
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil"
"helm.sh/helm/v3/pkg/storage"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
apitypes "k8s.io/apimachinery/pkg/types"
@@ -43,6 +46,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/kubevela/pkg/util/k8s"
"github.com/kubevela/pkg/util/resourcetopology"
velaslices "github.com/kubevela/pkg/util/slices"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
@@ -51,7 +56,9 @@ import (
"github.com/oam-dev/kubevela/apis/types"
velacmd "github.com/oam-dev/kubevela/pkg/cmd"
cmdutil "github.com/oam-dev/kubevela/pkg/cmd/util"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/utils/apply"
"github.com/oam-dev/kubevela/pkg/utils/env"
"github.com/oam-dev/kubevela/pkg/utils/util"
)
@@ -69,6 +76,9 @@ const (
//go:embed adopt-templates/default.cue
var defaultAdoptTemplate string
//go:embed resource-topology/builtin-rule.cue
var defaultResourceTopologyRule string
var (
adoptTypes = []string{adoptTypeNative, adoptTypeHelm}
adoptModes = []string{adoptModeReadOnly, adoptModeTakeOver}
@@ -90,35 +100,49 @@ type AdoptOptions struct {
HelmReleaseName string
HelmReleaseNamespace string
HelmDriver string
HelmConfig *action.Configuration
HelmStore *storage.Storage
HelmRelease *release.Release
HelmReleases []*release.Release
HelmReleaseRevisions []*release.Release
NativeResourceRefs []*resourceRef
Apply bool
Recycle bool
Yes bool
All bool
AdoptTemplateFile string
AdoptTemplate string
AdoptTemplateCUEValue cue.Value
ResourceTopologyRuleFile string
ResourceTopologyRule string
AllGVKs []schema.GroupVersionKind
Resources []*unstructured.Unstructured `json:"resources"`
util.IOStreams
}
func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command, arg string) (*resourceRef, error) {
parts := strings.Split(arg, "/")
_, gr := schema.ParseResourceArg(parts[0])
func (opt *AdoptOptions) parseResourceGVK(f velacmd.Factory, arg string) (schema.GroupVersionKind, error) {
_, gr := schema.ParseResourceArg(arg)
gvks, err := f.Client().RESTMapper().KindsFor(gr.WithVersion(""))
if err != nil {
return nil, fmt.Errorf("failed to find types for resource %s: %w", arg, err)
return schema.GroupVersionKind{}, fmt.Errorf("failed to find types for resource %s: %w", arg, err)
}
if len(gvks) == 0 {
return nil, fmt.Errorf("no schema found for resource %s: %w", arg, err)
return schema.GroupVersionKind{}, fmt.Errorf("no schema found for resource %s: %w", arg, err)
}
return gvks[0], nil
}
func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command, arg string) (*resourceRef, error) {
parts := strings.Split(arg, "/")
gvk, err := opt.parseResourceGVK(f, parts[0])
if err != nil {
return nil, err
}
gvk := gvks[0]
mappings, err := f.Client().RESTMapper().RESTMappings(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, fmt.Errorf("failed to find mappings for resource %s: %w", arg, err)
@@ -133,6 +157,9 @@ func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command,
or.Name = parts[1]
if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
or.Namespace = velacmd.GetNamespace(f, cmd)
if or.Namespace == "" {
or.Namespace = env.DefaultEnvNamespace
}
}
case 3:
or.Namespace = parts[1]
@@ -143,6 +170,186 @@ func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command,
return or, nil
}
// Init .
func (opt *AdoptOptions) Init(f velacmd.Factory, cmd *cobra.Command, args []string) error {
if opt.All {
if len(args) > 0 {
for _, arg := range args {
gvk, err := opt.parseResourceGVK(f, arg)
if err != nil {
return err
}
opt.AllGVKs = append(opt.AllGVKs, gvk)
apiVersion, kind := gvk.ToAPIVersionAndKind()
fmt.Fprintf(opt.Out, "Adopt all %s/%s resources\n", apiVersion, kind)
}
}
if len(opt.AllGVKs) == 0 {
opt.AllGVKs = []schema.GroupVersionKind{
appsv1.SchemeGroupVersion.WithKind("Deployment"),
appsv1.SchemeGroupVersion.WithKind("StatefulSet"),
appsv1.SchemeGroupVersion.WithKind("DaemonSet"),
}
_, _ = opt.Out.Write([]byte("No arguments specified, adopt all Deployment/StatefulSet/DaemonSet resources by default\n"))
}
}
if opt.AdoptTemplateFile != "" {
bs, err := os.ReadFile(opt.AdoptTemplateFile)
if err != nil {
return fmt.Errorf("failed to load file %s", opt.AdoptTemplateFile)
}
opt.AdoptTemplate = string(bs)
} else {
opt.AdoptTemplate = defaultAdoptTemplate
}
if opt.ResourceTopologyRuleFile != "" {
bs, err := os.ReadFile(opt.ResourceTopologyRuleFile)
if err != nil {
return fmt.Errorf("failed to load file %s", opt.ResourceTopologyRuleFile)
}
opt.ResourceTopologyRule = string(bs)
} else {
opt.ResourceTopologyRule = defaultResourceTopologyRule
}
opt.AppNamespace = velacmd.GetNamespace(f, cmd)
opt.AdoptTemplateCUEValue = cuecontext.New().CompileString(fmt.Sprintf("%s\n\n%s: %s", opt.AdoptTemplate, adoptCUETempVal, adoptCUETempFunc))
switch opt.Type {
case adoptTypeNative:
if opt.Recycle {
return fmt.Errorf("native resource adoption does not support --recycle flag")
}
case adoptTypeHelm:
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = os.Getenv(helmDriverEnvKey)
}
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = defaultHelmDriver
}
actionConfig := new(action.Configuration)
opt.HelmReleaseNamespace = opt.AppNamespace
if err := actionConfig.Init(
util.NewRestConfigGetterByConfig(f.Config(), opt.HelmReleaseNamespace),
opt.HelmReleaseNamespace,
opt.HelmDriver,
klog.Infof); err != nil {
return err
}
opt.HelmConfig = actionConfig
default:
return fmt.Errorf("invalid adopt type: %s, available types: [%s]", opt.Type, strings.Join(adoptTypes, ", "))
}
if slices.Index(adoptModes, opt.Mode) < 0 {
return fmt.Errorf("invalid adopt mode: %s, available modes: [%s]", opt.Mode, strings.Join(adoptModes, ", "))
}
if opt.Recycle && !opt.Apply {
return fmt.Errorf("old data can only be recycled when the adoption application is applied")
}
return nil
}
// MultipleRun .
func (opt *AdoptOptions) MultipleRun(f velacmd.Factory, cmd *cobra.Command) error {
resources := make([][]*unstructured.Unstructured, 0)
releases := make([]*release.Release, 0)
var err error
ctx := context.Background()
matchLabels := metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: oam.LabelAppName,
Operator: metav1.LabelSelectorOpDoesNotExist,
},
},
}
selector, err := metav1.LabelSelectorAsSelector(&matchLabels)
if err != nil {
return err
}
switch opt.Type {
case adoptTypeNative:
for _, gvk := range opt.AllGVKs {
list := &unstructured.UnstructuredList{}
list.SetGroupVersionKind(gvk)
if err := f.Client().List(ctx, list, &client.ListOptions{Namespace: opt.AppNamespace, LabelSelector: selector}); err != nil {
apiVersion, kind := gvk.ToAPIVersionAndKind()
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to list resources from %s/%s: %s", apiVersion, kind, err.Error())
continue
}
dedup := make([]k8s.ResourceIdentifier, 0)
for _, item := range list.Items {
engine := resourcetopology.New(opt.ResourceTopologyRule)
itemIdentifier := k8s.ResourceIdentifier{
Name: item.GetName(),
Namespace: item.GetNamespace(),
Kind: item.GetKind(),
APIVersion: item.GetAPIVersion(),
}
if velaslices.Contains(dedup, itemIdentifier) {
continue
}
firstElement := item
r := []*unstructured.Unstructured{&firstElement}
peers, err := engine.GetPeerResources(ctx, itemIdentifier)
if err != nil {
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to get peer resources for %s/%s: %s", itemIdentifier.APIVersion, itemIdentifier.Kind, err.Error())
resources = append(resources, r)
continue
}
dedup = append(dedup, peers...)
for _, peer := range peers {
gvk, err := k8s.GetGVKFromResource(peer)
if err != nil {
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to get gvk from resource %s/%s: %s", peer.APIVersion, peer.Kind, err.Error())
continue
}
peerResource := &unstructured.Unstructured{}
peerResource.SetGroupVersionKind(gvk)
if err := f.Client().Get(ctx, apitypes.NamespacedName{Namespace: peer.Namespace, Name: peer.Name}, peerResource); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to get resource %s/%s: %s", peer.Namespace, peer.Name, err.Error())
continue
}
r = append(r, peerResource)
}
resources = append(resources, r)
}
}
case adoptTypeHelm:
releases, err = opt.HelmConfig.Releases.List(func(release *release.Release) bool {
return true
})
if err != nil {
return err
}
}
for _, r := range resources {
opt.Resources = r
opt.AppName = r[0].GetName()
opt.AppNamespace = r[0].GetNamespace()
if err := opt.Run(f, cmd); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Error: failed to adopt %s/%s: %s", opt.AppNamespace, opt.AppName, err.Error())
continue
}
}
for _, r := range releases {
opt.AppName = r.Name
opt.AppNamespace = r.Namespace
opt.HelmReleaseName = r.Name
opt.HelmReleaseNamespace = r.Namespace
// TODO(fog): filter the helm that already adopted by vela
if err := opt.loadHelm(); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Error: failed to load helm for %s/%s: %s", opt.AppNamespace, opt.AppName, err.Error())
continue
}
if err := opt.Run(f, cmd); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Error: failed to adopt %s/%s: %s", opt.AppNamespace, opt.AppName, err.Error())
continue
}
}
return nil
}
// Complete autofill fields in opts
func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []string) error {
opt.AppNamespace = velacmd.GetNamespace(f, cmd)
@@ -160,6 +367,12 @@ func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []
}) {
opt.AppName = opt.NativeResourceRefs[0].Name
}
if opt.AppNamespace == "" {
opt.AppNamespace = opt.NativeResourceRefs[0].Namespace
}
if err := opt.loadNative(f, cmd); err != nil {
return err
}
case adoptTypeHelm:
if len(args) > 0 {
opt.HelmReleaseName = args[0]
@@ -167,26 +380,27 @@ func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []
if len(args) > 1 {
return fmt.Errorf("helm type adoption only support one helm release by far")
}
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = os.Getenv(helmDriverEnvKey)
}
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = defaultHelmDriver
}
if opt.AppName == "" {
opt.AppName = opt.HelmReleaseName
}
opt.HelmReleaseNamespace = opt.AppNamespace
if err := opt.loadHelm(); err != nil {
return err
}
default:
}
if opt.AdoptTemplateFile != "" {
bs, err := os.ReadFile(opt.AdoptTemplateFile)
if err != nil {
return fmt.Errorf("failed to load file %s", opt.AdoptTemplateFile)
if opt.AppName != "" {
var ctx = context.Background()
app := &v1beta1.Application{}
err := f.Client().Get(ctx, apitypes.NamespacedName{Namespace: opt.AppNamespace, Name: opt.AppName}, app)
if err == nil && app != nil {
if !opt.Yes {
userInput := NewUserInput()
confirm := userInput.AskBool("Application '%s' already exists, apply will override the existing app with the adopted one, please confirm [Y/n]: "+opt.AppName, &UserInputOptions{AssumeYes: false})
if !confirm {
return nil
}
}
}
opt.AdoptTemplate = string(bs)
} else {
opt.AdoptTemplate = defaultAdoptTemplate
}
opt.AdoptTemplateCUEValue = cuecontext.New().CompileString(fmt.Sprintf("%s\n\n%s: %s", opt.AdoptTemplate, adoptCUETempVal, adoptCUETempFunc))
return nil
@@ -202,21 +416,10 @@ func (opt *AdoptOptions) Validate() error {
if opt.AppName == "" {
return fmt.Errorf("app-name flag must be set for native resource adoption when multiple resources have different names")
}
if opt.Recycle {
return fmt.Errorf("native resource adoption does not support --recycle flag")
}
case adoptTypeHelm:
if len(opt.HelmReleaseName) == 0 {
return fmt.Errorf("helm release name must not be empty")
}
default:
return fmt.Errorf("invalid adopt type: %s, available types: [%s]", opt.Type, strings.Join(adoptTypes, ", "))
}
if slices.Index(adoptModes, opt.Mode) < 0 {
return fmt.Errorf("invalid adopt mode: %s, available modes: [%s]", opt.Mode, strings.Join(adoptModes, ", "))
}
if opt.Recycle && !opt.Apply {
return fmt.Errorf("old data can only be recycled when the adoption application is applied")
}
return nil
}
@@ -233,27 +436,18 @@ func (opt *AdoptOptions) loadNative(f velacmd.Factory, cmd *cobra.Command) error
return nil
}
func (opt *AdoptOptions) loadHelm(f velacmd.Factory) error {
actionConfig := new(action.Configuration)
err := actionConfig.Init(
util.NewRestConfigGetterByConfig(f.Config(), opt.HelmReleaseNamespace),
opt.HelmReleaseNamespace,
opt.HelmDriver,
klog.Infof)
if err != nil {
return err
}
opt.HelmStore = actionConfig.Releases
releases, err := opt.HelmStore.History(opt.HelmReleaseName)
func (opt *AdoptOptions) loadHelm() error {
opt.HelmStore = opt.HelmConfig.Releases
revisions, err := opt.HelmStore.History(opt.HelmReleaseName)
if err != nil {
return fmt.Errorf("helm release %s/%s not loaded: %w", opt.HelmReleaseNamespace, opt.HelmReleaseName, err)
}
if len(releases) == 0 {
if len(revisions) == 0 {
return fmt.Errorf("helm release %s/%s not found", opt.HelmReleaseNamespace, opt.HelmReleaseName)
}
releaseutil.SortByRevision(releases)
opt.HelmRelease = releases[len(releases)-1]
opt.HelmReleases = releases
releaseutil.SortByRevision(revisions)
opt.HelmRelease = revisions[len(revisions)-1]
opt.HelmReleaseRevisions = revisions
manifests := releaseutil.SplitManifests(opt.HelmRelease.Manifest)
var objs []*unstructured.Unstructured
for _, val := range manifests {
@@ -278,22 +472,17 @@ func (opt *AdoptOptions) render() (*v1beta1.Application, error) {
if err = json.Unmarshal(bs, app); err != nil {
return nil, fmt.Errorf("failed to parse template $returns into application: %w", err)
}
if app.Name == "" {
app.Name = opt.AppName
}
if app.Namespace == "" {
app.Namespace = opt.AppNamespace
}
return app, nil
}
// Run collect resources, assemble into application and print/apply
func (opt *AdoptOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
switch opt.Type {
case adoptTypeNative:
if err := opt.loadNative(f, cmd); err != nil {
return fmt.Errorf("failed to load native resources: %w", err)
}
case adoptTypeHelm:
if err := opt.loadHelm(f); err != nil {
return fmt.Errorf("failed to load resources from helm release %s/%s: %w", opt.HelmReleaseNamespace, opt.HelmReleaseName, err)
}
default:
}
app, err := opt.render()
if err != nil {
return fmt.Errorf("failed to make adoption application for resources: %w", err)
@@ -308,6 +497,9 @@ func (opt *AdoptOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
if bs, err = yaml.Marshal(app); err != nil {
return fmt.Errorf("failed to encode application into YAML format: %w", err)
}
if opt.All {
_, _ = opt.Out.Write([]byte("\n---\n"))
}
_, _ = opt.Out.Write(bs)
}
if opt.Recycle && opt.Apply {
@@ -328,7 +520,7 @@ func (opt *AdoptOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
}
switch opt.Type {
case adoptTypeHelm:
for _, r := range opt.HelmReleases {
for _, r := range opt.HelmReleaseRevisions {
if _, err = opt.HelmStore.Delete(r.Name, r.Version); err != nil {
return fmt.Errorf("failed to clean up helm release: %w", err)
}
@@ -375,11 +567,21 @@ var (
the command and make your own assemble rules for the adoption application. You can
refer to https://github.com/kubevela/kubevela/blob/master/references/cli/adopt-templates/default.cue
to see the default implementation of adoption rules.
If you want to adopt all resources with resource topology rule to Applications,
you can use: 'vela adopt --all'. The resource topology rule can be customized by
'--resource-topology-rule' flag.
`))
adoptExample = templates.Examples(i18n.T(`
# Native Resources Adoption
## Adopt resources into new application
## Adopt all resources to Applications with resource topology rule
## Use: vela adopt <resources-type> --all
vela adopt --all
vela adopt deployment --all --resource-topology-rule myrule.cue
## Use: vela adopt <resources-type>[/<resource-namespace>]/<resource-name> <resources-type>[/<resource-namespace>]/<resource-name> ...
vela adopt deployment/my-app configmap/my-app
@@ -402,6 +604,11 @@ var (
# Helm Chart Adoption
## Adopt all helm releases to Applications with resource topology rule
## Use: vela adopt <resources-type> --all
vela adopt --all --type helm
vela adopt my-chart --all --resource-topology-rule myrule.cue --type helm
## Adopt resources in a deployed helm chart
vela adopt my-chart -n my-namespace --type helm
@@ -436,8 +643,12 @@ func NewAdoptCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
Annotations: map[string]string{
types.TagCommandType: types.TypeCD,
},
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Init(f, cmd, args))
if o.All {
cmdutil.CheckErr(o.MultipleRun(f, cmd))
return
}
cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.Run(f, cmd))
@@ -447,9 +658,12 @@ func NewAdoptCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
cmd.Flags().StringVarP(&o.Mode, "mode", "m", o.Mode, fmt.Sprintf("The mode of adoption. Available values: [%s]", strings.Join(adoptModes, ", ")))
cmd.Flags().StringVarP(&o.AppName, "app-name", "", o.AppName, "The name of application for adoption. If empty for helm type adoption, it will inherit the helm chart's name.")
cmd.Flags().StringVarP(&o.AdoptTemplateFile, "adopt-template", "", o.AdoptTemplate, "The CUE template for adoption. If not provided, the default template will be used when --auto is switched on.")
cmd.Flags().StringVarP(&o.ResourceTopologyRuleFile, "resource-topology-rule", "", o.ResourceTopologyRule, "The CUE template for specify the rule of the resource topology. If not provided, the default rule will be used.")
cmd.Flags().StringVarP(&o.HelmDriver, "driver", "d", o.HelmDriver, "The storage backend of helm adoption. Only take effect when --type=helm.")
cmd.Flags().BoolVarP(&o.Apply, "apply", "", o.Apply, "If true, the application for adoption will be applied. Otherwise, it will only be printed.")
cmd.Flags().BoolVarP(&o.Recycle, "recycle", "", o.Recycle, "If true, when the adoption application is successfully applied, the old storage (like Helm secret) will be recycled.")
cmd.Flags().BoolVarP(&o.Yes, "yes", "y", o.Yes, "Skip confirmation prompt")
cmd.Flags().BoolVarP(&o.All, "all", "", o.All, "Adopt all resources in the namespace")
return velacmd.NewCommandBuilder(f, cmd).
WithNamespaceFlag().
WithResponsiveWriter().

View File

@@ -0,0 +1,62 @@
/*
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 cli
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/controller-runtime/pkg/client/config"
velacmd "github.com/oam-dev/kubevela/pkg/cmd"
"github.com/oam-dev/kubevela/pkg/utils/util"
)
func TestDefaultNamespace(t *testing.T) {
f := velacmd.NewDeferredFactory(config.GetConfig)
ioStream := util.IOStreams{}
ctx := context.Background()
cmd := NewAdoptCommand(f, ioStream)
cmd.SetContext(ctx)
testcase := []struct {
namespace string
args []string
}{
{
namespace: "kube-system",
args: []string{"deployment/kube-system/metrics-server"},
},
{
namespace: "default",
args: []string{"deployment/metrics-server"},
},
}
for _, c := range testcase {
opt := &AdoptOptions{
Type: adoptTypeNative,
Mode: adoptModeReadOnly,
}
_ = cmd.Flags().Set(FlagNamespace, c.namespace)
err := opt.Init(f, cmd, c.args)
if err != nil {
t.Fatalf("failed to parse resourceRef: %v", err)
}
assert.Equal(t, opt.AppNamespace, c.namespace)
}
}

View File

@@ -307,7 +307,7 @@ func (opt *DeleteOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
app := &v1beta1.Application{}
if err := f.Client().Get(cmd.Context(), apitypes.NamespacedName{Namespace: opt.Namespace, Name: appName}, app); err != nil {
if kerrors.IsNotFound(err) {
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "application %s/%s already deleted", opt.Namespace, appName)
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "application %s/%s already deleted\n", opt.Namespace, appName)
return nil
}
return fmt.Errorf("failed to get application %s/%s: %w", opt.Namespace, appName, err)

View File

@@ -19,6 +19,7 @@ package cli
import (
"context"
"fmt"
"regexp"
"strings"
"github.com/fatih/color"
@@ -34,6 +35,8 @@ import (
"github.com/oam-dev/kubevela/references/appfile"
)
var re = regexp.MustCompile(`"((?:[^"\\]|\\.)*)"`)
// NewLogsCommand creates `logs` command to tail logs of application
func NewLogsCommand(c common.Args, order string, ioStreams util.IOStreams) *cobra.Command {
largs := &Args{Args: c}
@@ -122,6 +125,10 @@ func (l *Args) printPodLogs(ctx context.Context, ioStreams util.IOStreams, selec
}
}
if show {
match := re.FindStringSubmatch(str)
if len(match) > 1 {
str = strings.ReplaceAll(match[1], "\\n", "\n")
}
ioStreams.Infonln(str)
}
case <-ctx.Done():

View File

@@ -0,0 +1,92 @@
rules: [
{
group: "apps"
resource: "deployment"
subResources: [
{
group: "apps"
resource: "replicaSet"
selectors: {
ownerReference: true
}
},
]
peerResources: commonPeerResources
}, {
group: "apps"
resource: "replicaSet"
subResources: [
{
group: ""
resource: "pod"
selectors: {
ownerReference: true
}
},
]
}, {
group: "apps"
resource: "statefulSet"
subResources: [
{
group: ""
resource: "pod"
selectors: {
ownerReference: true
}
},
]
peerResources: commonPeerResources
}, {
group: "apps"
resource: "daemonSet"
subResources: [
{
group: ""
resource: "pod"
selectors: {
ownerReference: true
}
},
]
peerResources: commonPeerResources
},
]
commonPeerResources: [{
group: ""
resource: "configMap"
selectors: {
name: [
if context.data.spec.template.spec.volumes != _|_ {
for v in context.data.spec.template.spec.volumes if v.configMap != _|_ if v.configMap.name != _|_ {
v.configMap.name
},
},
]
}
}, {
group: ""
resource: "secret"
selectors: {
name: [
if context.data.spec.template.spec.volumes != _|_ {
for v in context.data.spec.template.spec.volumes if v.secret != _|_ if v.secret.name != _|_ {
v.secret.name
},
},
]
}
}, {
group: ""
resource: "service"
selectors: {
builtin: "service"
}
}, {
group: "networking.k8s.io"
resource: "ingress"
selectors: {
builtin: "ingress"
}
}]

View File

@@ -19,7 +19,10 @@ package cli
import (
"fmt"
"github.com/go-logr/logr"
"github.com/spf13/cobra"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/log"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/utils/common"
@@ -50,6 +53,7 @@ func NewTopCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *co
if AllNamespace {
namespace = ""
}
klog.SetLogger(logr.New(log.NullLogSink{}))
return launchUI(c, namespace)
},
Annotations: map[string]string{

View File

@@ -291,7 +291,7 @@ func makeThemeConfigFileIfNotExist() bool {
if _, err := os.Open(filepath.Clean(themeConfigFilePath)); err != nil {
if os.IsNotExist(err) {
// make file if not exist
_ = os.MkdirAll(filepath.Clean(velaThemeHome), 0600)
_ = os.MkdirAll(filepath.Clean(velaThemeHome), 0700)
_ = os.WriteFile(filepath.Clean(themeConfigFilePath), []byte("name : "+DefaultTheme), 0600)
}
return false

View File

@@ -17,6 +17,8 @@ limitations under the License.
package config
import (
"os"
"strings"
"testing"
"github.com/gdamore/tcell/v2"
@@ -35,3 +37,11 @@ func TestColor(t *testing.T) {
c2 := Color("red")
assert.Equal(t, c2.Color(), tcell.GetColor("red").TrueColor())
}
func TestPersistentThemeConfig(t *testing.T) {
defer PersistentThemeConfig(DefaultTheme)
PersistentThemeConfig("foo")
bytes, err := os.ReadFile(themeConfigFilePath)
assert.Nil(t, err)
assert.True(t, strings.Contains(string(bytes), "foo"))
}

View File

@@ -243,6 +243,7 @@ type WorkflowArgs struct {
Writer io.Writer
Args common.Args
StepName string
StepID string
ErrMap map[string]string
App *v1beta1.Application
WorkflowRun *workflowv1alpha1.WorkflowRun
@@ -399,7 +400,7 @@ func (w *WorkflowArgs) printStepLogs(ctx context.Context, cli client.Client, ioS
return w.printResourceLogs(ctx, cli, ioStreams, []wfTypes.Resource{{
Namespace: types.DefaultKubeVelaNS,
LabelSelector: w.ControllerLabels,
}}, []string{fmt.Sprintf(`step_name="%s"`, w.StepName), fmt.Sprintf("%s/%s", w.WorkflowInstance.Namespace, w.WorkflowInstance.Name), "cue logs"})
}}, []string{fmt.Sprintf(`stepSessionID="%s"`, w.StepID), fmt.Sprintf("%s/%s", w.WorkflowInstance.Namespace, w.WorkflowInstance.Name), "cue logs"})
case logConfig.Source != nil:
if len(logConfig.Source.Resources) > 0 {
return w.printResourceLogs(ctx, cli, ioStreams, logConfig.Source.Resources, nil)
@@ -454,7 +455,8 @@ func (w *WorkflowArgs) selectWorkflowStep(msg string) error {
if err != nil {
return fmt.Errorf("failed to select step %s: %w", unwrapStepName(w.StepName), err)
}
w.StepName = unwrapStepID(stepName, w.WorkflowInstance)
w.StepName = unwrapStepName(stepName)
w.StepID = unwrapStepID(stepName, w.WorkflowInstance)
return nil
}

View File

@@ -22,6 +22,8 @@ metadata:
name: replica-webservice
namespace: vela-system
spec:
workload:
type: autodetects.core.oam.dev
schematic:
cue:
template: |

View File

@@ -34,9 +34,33 @@ import (
var appName = "app-e2e"
var appProject = "test-app-project"
func prepareEnv(envName string) {
var targetName = testNSprefix + strconv.FormatInt(time.Now().UnixNano(), 10)
// create target
var createTarget = apisv1.CreateTargetRequest{
Name: targetName,
Project: appProject,
Cluster: &apisv1.ClusterTarget{
ClusterName: "local",
Namespace: targetName,
},
}
res := post("/targets", createTarget)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
// create env
var createEnvReq = apisv1.CreateEnvRequest{
Name: envName,
Targets: []string{targetName},
}
res = post("/envs", createEnvReq)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
}
var _ = Describe("Test application rest api", func() {
It("Test create app", func() {
defer GinkgoRecover()
prepareEnv("dev-env")
var req = apisv1.CreateApplicationRequest{
Name: appName,
Project: appProject,
@@ -58,7 +82,7 @@ var _ = Describe("Test application rest api", func() {
Expect(cmp.Diff(appBase.Labels["test"], req.Labels["test"])).Should(BeEmpty())
})
It("Test list components", func() {
It("Test listing components", func() {
defer GinkgoRecover()
res := get("/applications/" + appName + "/components")
var components apisv1.ComponentListResponse
@@ -66,37 +90,42 @@ var _ = Describe("Test application rest api", func() {
Expect(cmp.Diff(len(components.Components), 1)).Should(BeEmpty())
})
It("Test updating a trigger", func() {
defer GinkgoRecover()
res := get("/applications/" + appName + "/triggers")
var triggers apisv1.ListApplicationTriggerResponse
Expect(decodeResponseBody(res, &triggers)).Should(Succeed())
Expect(cmp.Diff(len(triggers.Triggers), 1)).Should(BeEmpty())
old := triggers.Triggers[0]
var req = apisv1.UpdateApplicationTriggerRequest{
Alias: "Update",
Description: "Update the description",
WorkflowName: old.WorkflowName,
PayloadType: old.PayloadType,
ComponentName: old.ComponentName,
Registry: old.Registry,
}
res = put("/applications/"+appName+"/triggers/"+old.Token, req)
var base apisv1.ApplicationTriggerBase
Expect(decodeResponseBody(res, &base)).Should(Succeed())
Expect(cmp.Diff(base.Alias, req.Alias)).Should(BeEmpty())
Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty())
})
It("Test detail application", func() {
defer GinkgoRecover()
res := get("/applications/" + appName)
var detail apisv1.DetailApplicationResponse
Expect(decodeResponseBody(res, &detail)).Should(Succeed())
Expect(cmp.Diff(len(detail.Policies), 0)).Should(BeEmpty())
// The policy for the dev-env environment
Expect(cmp.Diff(len(detail.Policies), 1)).Should(BeEmpty())
})
It("Test deploy application", func() {
defer GinkgoRecover()
var targetName = testNSprefix + strconv.FormatInt(time.Now().UnixNano(), 10)
var envName = "dev"
// create target
var createTarget = apisv1.CreateTargetRequest{
Name: targetName,
Project: appProject,
Cluster: &apisv1.ClusterTarget{
ClusterName: "local",
Namespace: targetName,
},
}
res := post("/targets", createTarget)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
// create env
var createEnvReq = apisv1.CreateEnvRequest{
Name: envName,
Targets: []string{targetName},
}
res = post("/envs", createEnvReq)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
prepareEnv(envName)
// create envbinding
var createEnvbindingReq = apisv1.CreateApplicationEnvbindingRequest{
@@ -104,7 +133,7 @@ var _ = Describe("Test application rest api", func() {
Name: envName,
},
}
res = post("/applications/"+appName+"/envs", createEnvbindingReq)
res := post("/applications/"+appName+"/envs", createEnvbindingReq)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
// deploy app

View File

@@ -153,7 +153,7 @@ var _ = Describe("Test the rest api about the config", func() {
Expect(config.Secret).Should(BeNil())
Expect(config.Properties["registry"]).Should(Equal("kubevela.test.com"))
By("the config name is exist")
By("the config name does exist")
req = v1.CreateConfigRequest{
Name: "test-registry",
Alias: "Test Registry",
@@ -164,7 +164,7 @@ var _ = Describe("Test the rest api about the config", func() {
res = post("/configs", req)
Expect(res.StatusCode).Should(Equal(400))
By("the template is not exist")
By("the template does not exist")
req = v1.CreateConfigRequest{
Name: "test-registry2",
Alias: "Test Registry",

View File

@@ -0,0 +1,42 @@
/*
Copyright 2022 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e_apiserver_test
import (
"io"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Helm rest api test", func() {
Describe("helm repo api test", func() {
It("test fetching chart values in OCI registry", func() {
resp := getWithQuery("/repository/chart/values", map[string]string{
"repoUrl": "oci://ghcr.io",
"chart": "stefanprodan/charts/podinfo",
"repoType": "oci",
"version": "6.1.0",
})
defer resp.Body.Close()
values, err := io.ReadAll(resp.Body)
Expect(err).Should(BeNil())
Expect(len(values)).ShouldNot(BeEquivalentTo(0))
})
})
})

View File

@@ -49,7 +49,7 @@ var token string
const (
baseDomain = "http://127.0.0.1:8001"
baseURL = "http://127.0.0.1:8001/api/v1"
testNSprefix = "api-e2e-test-"
testNSprefix = "api-test-"
)
func TestE2eApiserverTest(t *testing.T) {
@@ -191,6 +191,26 @@ func get(path string) *http.Response {
return response
}
func getWithQuery(path string, params map[string]string) *http.Response {
client := &http.Client{}
if !strings.HasPrefix(path, "/v1") {
path = baseURL + path
} else {
path = baseDomain + path
}
req, err := http.NewRequest(http.MethodGet, path, nil)
Expect(err).Should(BeNil())
req.Header.Add("Authorization", token)
query := req.URL.Query()
for k, v := range params {
query.Set(k, v)
}
req.URL.RawQuery = query.Encode()
response, err := client.Do(req)
Expect(err).Should(BeNil())
return response
}
func delete(path string) *http.Response {
client := &http.Client{}
if !strings.HasPrefix(path, "/v1") {

View File

@@ -7,6 +7,8 @@ metadata:
name: replica-webservice
namespace: vela-system
spec:
workload:
type: autodetects.core.oam.dev
schematic:
cue:
template: |

View File

@@ -9,7 +9,7 @@
template: {
#PolicyRule: {
// +usage=Specify how to select the targets of the rule
selector: [...#RuleSelector]
selector: #RuleSelector
}
#RuleSelector: {

View File

@@ -64,7 +64,7 @@ template: {
}
}
parameter: *#PatchParams | close({
parameter: #PatchParams | close({
// +usage=Specify the container image for multiple containers
containers: [...#PatchParams]
})

View File

@@ -18,7 +18,10 @@ expose: {
}
if service.spec.type == "LoadBalancer" {
status: service.status
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
isHealth: *false | bool
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
isHealth: true
}
if !isHealth {
message: "ExternalIP: Pending"
}
@@ -28,11 +31,16 @@ expose: {
}
"""#
healthPolicy: #"""
isHealth: *true | bool
service: context.outputs.service
if service.spec.type == "LoadBalancer" {
status: service.status
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
isHealth: *false | bool
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
isHealth: true
}
}
if service.spec.type != "LoadBalancer" {
isHealth: true
}
"""#
}

View File

@@ -14,19 +14,20 @@ gateway: {
}
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
let igs = context.outputs.ingress.status.loadBalancer.ingress
let host = context.outputs.ingress.spec.rules[0].host
if igs[0].ip != _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
}
if igs[0].host == _|_ {
if host == _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
}
}
if igs[0].ip == _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
}
if igs[0].host != _|_ {
if host != _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
}
}

View File

@@ -326,7 +326,7 @@ template: {
envName: string
secretKey: string
}]
mountPath?: string
mountPath: string
subPath?: string
defaultMode: *420 | int
readOnly: *false | bool

View File

@@ -113,7 +113,7 @@ template: {
#ECProvider: {
type: "ec"
apiKey: *"" | string
name: "ec-provider" | string
name: *"ec-provider" | string
}
#GCPProvider: {
credentials: string

View File

@@ -51,44 +51,41 @@ template: {
// +usage=Specify the message that you want to sent, refer to [dingtalk messaging](https://developers.dingtalk.com/document/robots/custom-robot-access/title-72m-8ag-pqw)
message: {
// +usage=Specify the message content of dingtalk notification
text?: *null | close({
text?: close({
content: string
})
// +usage=msgType can be text, link, mardown, actionCard, feedCard
msgtype: *"text" | "link" | "markdown" | "actionCard" | "feedCard"
link?: *null | close({
#link: {
text?: string
title?: string
messageUrl?: string
picUrl?: string
})
markdown?: *null | close({
}
link?: #link
markdown?: close({
text: string
title: string
})
at?: *null | close({
atMobiles?: *null | [...string]
isAtAll?: bool
at?: close({
atMobiles?: [...string]
isAtAll?: bool
})
actionCard?: *null | close({
actionCard?: close({
text: string
title: string
hideAvatar: string
btnOrientation: string
singleTitle: string
singleURL: string
btns: *null | close([...*null | close({
btns?: [...close({
title: string
actionURL: string
})])
})]
})
feedCard?: *null | close({
links: *null | close([...*null | close({
text?: string
title?: string
messageUrl?: string
picUrl?: string
})])
feedCard?: close({
links: [...#link]
})
}
}
@@ -109,11 +106,11 @@ template: {
// +usage=Specify the message that you want to sent, refer to [slack messaging](https://api.slack.com/reference/messaging/payload)
message: {
// +usage=Specify the message text for slack notification
text: string
blocks?: *null | close([...block])
attachments?: *null | close({
blocks?: *null | close([...block])
color?: string
text: string
blocks?: [...block]
attachments?: close({
blocks?: [...block]
color?: string
})
thread_ts?: string
// +usage=Specify the message text format in markdown for slack notification