Compare commits

...

69 Commits

Author SHA1 Message Date
github-actions[bot]
29ecc5c0df Feat: support vela show for workflow step definition (#3161)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 23852b3d10)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-01-25 15:05:46 +08:00
github-actions[bot]
20c11f2b84 fix: vela addnon enable cannot support = (#3158)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit ddefb8cb4e)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-01-25 13:58:24 +08:00
github-actions[bot]
e9f7cf7c23 Fix: add context parameters into the error message (#3159)
Signed-off-by: zeed-w-beez <zeed.w.zhao@gmail.com>
(cherry picked from commit 170888063d)

Co-authored-by: zeed-w-beez <zeed.w.zhao@gmail.com>
2022-01-25 13:28:01 +08:00
github-actions[bot]
cebeff867a [Backport release-1.2] Feat: addon parameter support ui-shcema (#3155)
* Feat: addon parameter support ui-shcema

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

fix ci

(cherry picked from commit 8e2bf9c68d)

* add more tests

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

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-01-25 10:47:07 +08:00
github-actions[bot]
7902a19aae [Backport release-1.2] Fix: retrieve Terraform variables from variables.tf (#3153)
* Fix: retrieve Terraform variables from variables.tf

If Terraform modules/resources are stored in remote git repos, get
variables from file `varialbes.tf`, or from `main.tf`.

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit b257825af6)

* set the required field per the variables' property

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit 4b151582c5)

* fix ut issue

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit b52145c8a4)

* fix ut issue

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit 410acc8ae2)

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-24 13:56:59 +08:00
github-actions[bot]
f98b8c7d8a Fix: add providerRef in generated ComponentDefinition (#3151)
If the provider is not provider, append the providerRef section in
the generated ComponentDefinition

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit 34ecc40aad)

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-24 11:00:41 +08:00
github-actions[bot]
ee8773e1cf [Backport release-1.2] Fix: handle workflow cache reconcile (#3148)
* Fix: handle workflow cache reconcile

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

* fix return and move backoff to memory

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

* handle failed to patch case

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

* add store in err case

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

* make reviewable

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

* fix ut

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

* do cleanup in ut

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

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-01-24 10:37:48 +08:00
github-actions[bot]
8cf2f20846 [Backport release-1.2] Fix: workflow skip executing all steps occasionally (#3147)
* fix asi

Signed-off-by: Jian.Li <lj176172@alibaba-inc.com>
(cherry picked from commit 2c26caedd3)

* fix lint

Signed-off-by: Jian.Li <lj176172@alibaba-inc.com>
(cherry picked from commit b63e892eb3)

* add trace tag

(cherry picked from commit 1a6d79642e)

* add args for this feature

Signed-off-by: Jian.Li <lj176172@alibaba-inc.com>
(cherry picked from commit b9181b9fc0)

* enable-asi-compatibility

Signed-off-by: Jian.Li <lj176172@alibaba-inc.com>
(cherry picked from commit 5d013db0bd)

Co-authored-by: Jian.Li <lj176172@alibaba-inc.com>
2022-01-23 10:13:59 +08:00
github-actions[bot]
2c6e8e7de7 [Backport release-1.2] Feat: extend gateway trait to set class in spec (#3146)
* Feat: extend gateway trait to set class in spec

`kubernetes.io/ingress.class` annotation is deprecated in favor of
`.spec.ingressClassName`. However, there is no way to set it through
the gateway trait for now.

This commit extends the gateway trait by adding `classInSpec` to
parameter. Forcing the use of `.spec.ingressClassName` makes sense, but
some ingress controllers (including old versions) may not recognize
this field. Therefore, set default value of `classInSpec` to `false`
for backward compatibility.

Signed-off-by: Sunghoon Kang <hoon@linecorp.com>
(cherry picked from commit ad8bd1c1c4)

* Chore: update classInSpec usage

Signed-off-by: Sunghoon Kang <hoon@linecorp.com>
(cherry picked from commit 721f879e3d)

Co-authored-by: Sunghoon Kang <hoon@linecorp.com>
2022-01-23 10:13:18 +08:00
github-actions[bot]
dbfd6a1d10 [Backport release-1.2] Fix: prioritize namespace flag for vela up (#3137)
* Fix: prioritize namespace flag for `vela up`

Currently, CLI applies application to `default` namespace when there is
no explicit namespace in application spec, even if the namespace flag
is set.

This commit fixes issue by overriding the namespace if the namespace
flag is set.

Signed-off-by: Sunghoon Kang <hoon@linecorp.com>
(cherry picked from commit 4cf07dcd97)

* Test: add test cases for overriding namespaces

Signed-off-by: Sunghoon Kang <hoon@linecorp.com>
(cherry picked from commit 5ba93541e4)

Co-authored-by: Sunghoon Kang <hoon@linecorp.com>
2022-01-21 11:27:11 +08:00
github-actions[bot]
ce8e652802 Fix: support generate Terraform ComponentDefinition from local HCL file (#3134)
Besides generating a Terraform ComponentDefinition from a remote git repo,
support generate one from local HCL file

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit bc06a5343e)

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-20 14:59:24 +08:00
github-actions[bot]
9968211163 add imagePullSecrets for helm templates to support private docker registry (#3129)
Signed-off-by: StevenLeiZhang <zhangleiic@163.com>
(cherry picked from commit cf9eb0ded9)

Co-authored-by: StevenLeiZhang <zhangleiic@163.com>
2022-01-19 13:00:45 +08:00
github-actions[bot]
c86776cca1 [Backport release-1.2] Feat: add port name in webservice (#3120)
* Feat: add port name in webservice

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

* fix port name in container

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

* generate port name if not specified

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

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-01-18 19:43:18 +08:00
github-actions[bot]
11a1b2fa72 Fix: add app samples for Terraform definition (#3119)
Added application samples for all Terraform typed ComponentDefinition,
and also localize the title for AWS and AZure

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
(cherry picked from commit 670a327161)

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-18 18:10:16 +08:00
github-actions[bot]
cd036b87ae Feat: support wild match for env patch (#3116)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit fe0d33c6d9)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2022-01-18 18:07:05 +08:00
github-actions[bot]
7e447c6532 fix revision will change when add new trait with skiprevisionaffect to application (#3117)
Signed-off-by: chwetion <chwetion@foxmail.com>
(cherry picked from commit 86f6fef216)

Co-authored-by: chwetion <chwetion@foxmail.com>
2022-01-18 13:41:48 +08:00
github-actions[bot]
b836f86484 Fix: trait/comp command output without a new line (#3115)
Signed-off-by: qiaozp <chivalry.pp@gmail.com>
(cherry picked from commit 1ba3e1dd62)

Co-authored-by: qiaozp <chivalry.pp@gmail.com>
2022-01-18 13:05:23 +08:00
github-actions[bot]
d34372bf47 [Backport release-1.2] Feat: add JFrog webhook trigger (#3114)
* add jfrog webhook to update application image

Signed-off-by: chwetion <chwetion@foxmail.com>
(cherry picked from commit 962fce6870)

* edit jfrog default request header

Signed-off-by: chwetion <chwetion@foxmail.com>
(cherry picked from commit a977bfc9af)

Co-authored-by: chwetion <chwetion@foxmail.com>
2022-01-18 11:51:15 +08:00
Somefive
12f392cd92 Fix: rollout workload namespace not aligned with rollout (#3107)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
2022-01-17 20:06:27 +08:00
StevenLeiZhang
af27e6a776 ignore vela-system, which is specified in needNamespace for addon metadata information (#3109)
Signed-off-by: StevenLeiZhang <zhangleiic@163.com>
2022-01-17 20:02:05 +08:00
StevenLeiZhang
f57815a5bf ignore files under the addon path of github addon registry (#3099)
Signed-off-by: StevenLeiZhang <zhangleiic@163.com>
2022-01-17 20:01:46 +08:00
Somefive
69527b257c Feat: support external revision in patch component (#3106)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
2022-01-17 19:29:28 +08:00
barnettZQG
d88d4d8eca Fix: clear old data in mongodb unit test case (#3103)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-17 19:06:29 +08:00
Zheng Xi Zhou
4e881b44af Fix: support generate cloud resource docs in Chinese (#3079)
* Fix: support generate cloud resource docs in Chinese

`vela def doc-gen` will also generate Chinese cloud resource docs

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* Continue the development

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* add ut

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* add ut and fix linting issue

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* Address comments

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* Fix `Should not use dot imports. (ST1001) ` issue

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* add copyright

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-17 16:18:59 +08:00
wyike
800b50cf0b fix acr image no version (#3100)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2022-01-17 16:09:21 +08:00
Jianbo Sun
3d9e1c7d80 Fix: use personel token of vela-bot instead of github token for homebrew update (#3096)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-17 11:45:01 +08:00
barnettZQG
fccc5df25e Fix: can't query data from the MongoDB (#3095)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-17 11:25:09 +08:00
yangsoon
6cee468743 Feat: add more performance optimization and prometheus metrics for controller (#3086)
* Feat: add more prometheus metrics

Signed-off-by: yangsoon <yangsoonlx@gmail.com>

* Feat: add detail gc rt duration metrics

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add monitor to client

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add all cache object

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Fix: watch job

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add deleg client

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add optimize for rt list and disable controllerrevision

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add apprev disable optimize

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Fix: optimize log

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add time recorder for app ctrl

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add in-memory workflow context

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add reconcile-reduction & random-pick-gc & optimize rt record

Signed-off-by: Yin Da <yd219913@alibaba-inc.com>

* Feat: add optimize for healthcheck & resourcetracker trigger

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Chore: refactor

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Feat: record the resource-tracker number by informer event-handler

Signed-off-by: yangsoon <songyang.song@alibaba-inc.com>

* Feat: add promethus collect annotation in template

Signed-off-by: yangsoon <songyang.song@alibaba-inc.com>

* Fix: command line comment bug

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Chore: rename args and remove legacy controller metrics

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Fix: make code reviewable

Signed-off-by: yangsoon <songyang.song@alibaba-inc.com>

* Chore: optimize flag descriptions

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Chore: break optimize package

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Fix: gc policy test

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

Co-authored-by: Yin Da <yd219913@alibaba-inc.com>
Co-authored-by: yangsoon <songyang.song@alibaba-inc.com>
2022-01-14 15:18:02 +08:00
wyike
102a155194 fix lost create time and spell error (#3089)
Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-14 15:10:56 +08:00
wyike
f39a3fb792 Feat: system information collection logic in apiserver (#3082)
* Feat: userInfoCollection

Signed-off-by: wangyike <wangyike_wyk@163.com>

* Signed-off-by: wangyike <wangyike_wyk@163.com>

change enable/disable to update interface

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-14 10:16:31 +08:00
Somefive
8b5d7ed395 Feat: reset re-sync time (#3008)
* Feat: set resync

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Fix: rename re-sync period

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* Chore: refactor return value

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
2022-01-13 20:12:54 +08:00
wyike
5b1c47c918 cue template health check skipStandard workload and fix test diverge (#3087)
Signed-off-by: wangyike <wangyike_wyk@163.com>

add annotation

Signed-off-by: wangyike <wangyike_wyk@163.com>

set skipStandardworkload in wl

Signed-off-by: wangyike <wangyike_wyk@163.com>

add annotation

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-13 19:08:43 +08:00
Jianbo Sun
c298c98f25 Fix: vela logs for namespace get from CLI and add container name args (#3084)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-12 21:22:42 +08:00
Jianbo Sun
7f7a9dcac0 Feat: vela up support read from stdin && refine CLI output && fix vela addon command (#3080)
* Feat: vela up support read from stdin

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>

* Fix: addon name missed in output and fix test

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>

* Chore: refine CLI output

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>

Fix: add retry-on conflict on CLI

Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-12 17:43:08 +08:00
barnettZQG
b4732ed275 Feat: add cluster name in service endpoint (#3076)
* Feat: add cluster name in service endpoint

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>

* Feat: add cli unit test

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-12 14:44:22 +08:00
chwetion
bfbdb85503 Feat: add DockerHub webhook trigger (#3081)
* add dockerhub webhook to update application image

Signed-off-by: chwetion <chwetion@foxmail.com>

* fix e2e webhook response return value

Signed-off-by: chwetion <chwetion@foxmail.com>

* add e2e for dockerhub webhook

Signed-off-by: chwetion <chwetion@foxmail.com>

Co-authored-by: chwetion <chwetion@foxmail.com>
2022-01-12 11:37:06 +08:00
Zheng Xi Zhou
f41e0a3bb5 Fix: change vela def gen-doc to vela def doc-gen (#3078)
* Fix: change `vela def gen-doc` to `vela def doc-gen`

Address the comments to change the command line name

Co-authored-by: Jianbo Sun <wonderflow.sun@gmail.com>
Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* fix CI

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

Co-authored-by: Jianbo Sun <wonderflow.sun@gmail.com>
2022-01-12 11:35:41 +08:00
Jianbo Sun
19a542ff11 Feat: support vela up from remote url file (#3075)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-11 17:28:45 +08:00
wyike
d64c78db47 Feat: addon enable support local dir for install offline (#3066)
* local reader

Signed-off-by: wangyike <wangyike_wyk@163.com>

* fix lint

Signed-off-by: wangyike <wangyike_wyk@163.com>

* fix comments and add test

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-11 11:29:10 +08:00
Kingram
ceb95229cd Feat: add Harbor webhook trigger (#3065)
* Feat: add harbor webhook trigger (#3029)

Signed-off-by: kingram <kingram@163.com>

* resolve comments

Signed-off-by: kingram <kingram@163.com>

* fix: add comments

Signed-off-by: kingram <kingram@163.com>
2022-01-10 21:26:43 +08:00
barnettZQG
ece47b5961 Fix: change namespace for the service-endpoints-view velaQL (#3071)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-10 21:25:07 +08:00
Basuotian
8be11a7e7e Feat: Add Lark support for notification (#3053) (#3059)
Signed-off-by: Shuai Tian <tians1@xiaopeng.com>

Co-authored-by: Shuai Tian <tians1@xiaopeng.com>
2022-01-10 19:42:06 +08:00
Zheng Xi Zhou
b354d2faa9 Fix: generate Terraform ComponentDefinition by vela cli (#3067)
* Fix: generate Terraform ComponentDefinition by vela cli

Support generate Terraform typed ComponentDefinition by `vela def init`

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-10 19:12:32 +08:00
Jianbo Sun
3af323365b Chore: refine CLI help message and docs (#3068)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-10 17:45:20 +08:00
Jianbo Sun
6a512c02a6 Chore: add autogen CLI reference doc script (#3063)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-10 15:28:04 +08:00
Minglong Song
b30ca0c8a2 Fix: Do not fiter event triggered by resync for application controller (#3064)
Signed-off-by: songminglong <1247768069@qq.com>
2022-01-10 14:48:58 +08:00
Zheng Xi Zhou
1a50dd76b5 Fix: generate docs for Terraform ComponentDefinition (#3051)
* Fix: generate docs for Terraform ComponentDefinition

Generated kubevela.io docs for Terraform typed ComponentDefinition
with `vela def gen-doc xxx` cli.

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* Refactor code

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* add ut

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* add ut

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* refine cloud resource title

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-10 14:08:48 +08:00
Zheng Xi Zhou
b17abe0081 Fix: add cue binary requirement in Development doc (#3062)
* Fix: add cue binary requirement in Development doc

If the version of cue binary is less than v0.3.0, like v0.2.0, `make reviewable`
will fail due to issue: "make: *** [fmt] Error 1". As `make reviewable` is a
required step for code contribution, add this prerequiste in the doc.

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* Update contribute/developer-guide.md

Co-authored-by: Jianbo Sun <wonderflow.sun@gmail.com>

Co-authored-by: Jianbo Sun <wonderflow.sun@gmail.com>
2022-01-10 13:01:46 +08:00
Jianbo Sun
12a106fcfe Fix: migrate test from crd v1beta1 to v1 (#3061)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-10 10:25:35 +08:00
barnettZQG
53d3ff6915 Fix: security alerts (#3058)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-07 16:27:23 +08:00
barnettZQG
d4762e09cd Feat: support query endpoints in status command and speed up CLI response (#3052)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-07 15:49:27 +08:00
Tianxin Dong
578aae6482 Fix: fix component definition status message (#3054)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-01-06 23:12:29 +08:00
Zheng Xi Zhou
96485ea0db Fix: when a provider is set in ComponentDefinition, it should look for the provider (#3047)
* Fix: when a provider is set in ComponentDefinition, it should look for the provider

Fixed the issue "The error message is not correct when AWS provider is not available"

Fix #3046

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-06 19:02:03 +08:00
Tianxin Dong
251c440453 Feat: add ACR webhook trigger (#3044)
* Feat: add ACR webhook trigger

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

* resolve comments

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

* change to interface

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

* fix payload types

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-01-06 17:31:02 +08:00
wyike
770894412a Chore: deprecate appDeployment related logic (#3050)
* deperecated appDeployment

Signed-off-by: wangyike <wangyike_wyk@163.com>

* delete more code

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-06 16:24:09 +08:00
Tianxin Dong
4d6c0eb9d5 Fix: reset step status to stopped if the workflow is terminated (#3049)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2022-01-06 15:15:28 +08:00
wyike
53081d043b Chore: deprecate and delete approllout related code (#3040)
* Fex: delete useles approllout related code

Signed-off-by: wangyike <wangyike_wyk@163.com>

fix failed test

Signed-off-by: wangyike <wangyike_wyk@163.com>

Fix: failed e2e test

Signed-off-by: wangyike <wangyike_wyk@163.com>

fix-test

Signed-off-by: wangyike <wangyike_wyk@163.com>

fix test

Signed-off-by: wangyike <wangyike_wyk@163.com>

fix e2e-test

Signed-off-by: wangyike <wangyike_wyk@163.com>

fix e2e rollout test

Signed-off-by: wangyike <wangyike_wyk@163.com>

* delete useless test code

Signed-off-by: wangyike <wangyike_wyk@163.com>

* fix failed unit-test

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-06 14:33:11 +08:00
Jianbo Sun
8495465087 Refactor: refine cli commands && align kubectl-vela with vela && use getnamespaceAndEnv for all (#3048)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-06 13:29:02 +08:00
qiaozp
5f31b9aad0 Feat: add test for registry name in addon response (#2858)
* add test for registry name when list addon

Signed-off-by: qiaozp <chivalry.pp@gmail.com>

* revert

Signed-off-by: qiaozp <chivalry.pp@gmail.com>

* fix

Signed-off-by: qiaozp <chivalry.pp@gmail.com>

* fix test

Signed-off-by: qiaozp <chivalry.pp@gmail.com>
2022-01-06 11:48:34 +08:00
barnettZQG
9f2e43756e Feat: support query service endpoints by velaql (#3036)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
2022-01-06 00:35:46 +08:00
Zheng Xi Zhou
8033279751 Fix: Generate doc for Terraform typed ComponentDefinition (#3041)
* Fix: Generate doc for Terraform typed ComponentDefinition

When the configuration of a Terraform Typed ComponentDefinition is in
remote Git, generate the properties for it. And generated outputs for
all Terraform ComponentDefinition

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-05 19:45:30 +08:00
chwetion
070b313897 Feat: support application trigger deletion (#3037)
* support application trigger deletion

Signed-off-by: chwetion <chwetion@foxmail.com>

* add unit test for deleting application trigger

Signed-off-by: chwetion <chwetion@foxmail.com>

Co-authored-by: chwetion <chwetion@foxmail.com>
2022-01-05 14:25:24 +08:00
wyike
c170cecd34 fix addon panic bug (#3026)
Signed-off-by: wangyike <wangyike_wyk@163.com>

Fix lint

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-05 13:40:51 +08:00
Somefive
acac0554f3 Fix: filter managedfields update events (#3043)
Signed-off-by: Yin Da <yd219913@alibaba-inc.com>
2022-01-05 13:30:58 +08:00
wyike
1bceea29be Fix: helm addon demo issues (#3033)
* helm-port-forward

Signed-off-by: wangyike <wangyike_wyk@163.com>

* fix several issues

Signed-off-by: wangyike <wangyike_wyk@163.com>

* Fix comments

Signed-off-by: wangyike <wangyike_wyk@163.com>
2022-01-04 15:57:57 +08:00
Jianbo Sun
3066cde46b Fix: fix vela show --web that can not show elems (#3039)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-04 15:57:24 +08:00
Jianbo Sun
15be6bc388 Fix: check error when client not created (#3038)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2022-01-04 14:52:35 +08:00
qiaozp
ac6b125b7f Fix: error case is not tested when generate api schema (#3035)
Signed-off-by: qiaozp <chivalry.pp@gmail.com>
2022-01-04 11:14:57 +08:00
Zheng Xi Zhou
24c00fc99b Fix: don't skip health check for observability in single cluster (#3031)
* Fix: don't skip health check for observability in single cluster

When there is no clusters, users use cli to enable observability,
we use workflow `apply-application-in-parallel` to enable the addon.
This workflow will skip health check and the addon won't become ready.

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>

* Fix CI issue

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
2022-01-04 11:13:09 +08:00
269 changed files with 9014 additions and 13105 deletions

View File

@@ -57,7 +57,7 @@ jobs:
- name: Build & Pushing vela-core for ACR
run: |
docker build --build-arg GOPROXY=https://proxy.golang.org -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-core:${{ steps.get_version.outputs.VERSION }} .
docker build --build-arg GOPROXY=https://proxy.golang.org --build-arg VERSION=${{ steps.get_version.outputs.VERSION }} --build-arg GITVERSION=git-${{ steps.vars.outputs.git_revision }} -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-core:${{ steps.get_version.outputs.VERSION }} .
docker push kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-core:${{ steps.get_version.outputs.VERSION }}
- uses: docker/build-push-action@v2
name: Build & Pushing vela-core for Dockerhub and GHCR
@@ -79,7 +79,7 @@ jobs:
- name: Build & Pushing vela-apiserver for ACR
run: |
docker build --build-arg GOPROXY=https://proxy.golang.org -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-apiserver:${{ steps.get_version.outputs.VERSION }} -f Dockerfile.apiserver .
docker build --build-arg GOPROXY=https://proxy.golang.org --build-arg VERSION=${{ steps.get_version.outputs.VERSION }} --build-arg GITVERSION=git-${{ steps.vars.outputs.git_revision }} -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-apiserver:${{ steps.get_version.outputs.VERSION }} -f Dockerfile.apiserver .
docker push kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-apiserver:${{ steps.get_version.outputs.VERSION }}
- uses: docker/build-push-action@v2
name: Build & Pushing vela-apiserver for Dockerhub and GHCR
@@ -101,7 +101,7 @@ jobs:
- name: Build & Pushing vela runtime rollout for ACR
run: |
docker build --build-arg GOPROXY=https://proxy.golang.org -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-rollout:${{ steps.get_version.outputs.VERSION }} .
docker build --build-arg GOPROXY=https://proxy.golang.org --build-arg VERSION=${{ steps.get_version.outputs.VERSION }} --build-arg GITVERSION=git-${{ steps.vars.outputs.git_revision }} -t kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-rollout:${{ steps.get_version.outputs.VERSION }} .
docker push kubevela-registry.cn-hangzhou.cr.aliyuncs.com/oamdev/vela-rollout:${{ steps.get_version.outputs.VERSION }}
- uses: docker/build-push-action@v2
name: Build & Pushing runtime rollout for Dockerhub and GHCR

View File

@@ -142,7 +142,7 @@ jobs:
- name: Update Homebrew formula
uses: dawidd6/action-homebrew-bump-formula@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.HOMEBREW_TOKEN }}
formula: kubevela
tag: ${{ github.ref }}
revision: ${{ github.sha }}

View File

@@ -213,6 +213,8 @@ const (
WorkflowStateFinished WorkflowState = "finished"
// WorkflowStateExecuting means workflow is still running or waiting some steps.
WorkflowStateExecuting WorkflowState = "executing"
// WorkflowStateSkipping means it will skip this reconcile and let next reconcile to handle it.
WorkflowStateSkipping WorkflowState = "skipping"
)
// ApplicationComponentStatus record the health status of App component
@@ -289,8 +291,6 @@ type AppStatus struct {
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
Rollout *AppRolloutStatus `json:"rollout,omitempty"`
Phase ApplicationPhase `json:"status,omitempty"`
// Components record the related Components created by Application Controller

View File

@@ -45,11 +45,6 @@ func (in *AppRolloutStatus) DeepCopy() *AppRolloutStatus {
func (in *AppStatus) DeepCopyInto(out *AppStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
if in.Rollout != nil {
in, out := &in.Rollout, &out.Rollout
*out = new(AppRolloutStatus)
(*in).DeepCopyInto(*out)
}
if in.Components != nil {
in, out := &in.Components, &out.Components
*out = make([]v1.ObjectReference, len(*in))

View File

@@ -45,10 +45,11 @@ func (in *EnvTraitPatch) ToApplicationTrait() *common.ApplicationTrait {
// EnvComponentPatch is the patch to component
type EnvComponentPatch struct {
Name string `json:"name"`
Type string `json:"type"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
Traits []EnvTraitPatch `json:"traits,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
Traits []EnvTraitPatch `json:"traits,omitempty"`
ExternalRevision string `json:"externalRevision,omitempty"`
}
// ToApplicationComponent convert EnvComponentPatch into ApplicationComponent

View File

@@ -1,86 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
// AppRolloutSpec defines how to describe an upgrade between different apps
type AppRolloutSpec struct {
// TargetAppRevisionName contains the name of the applicationRevision that we need to upgrade to.
TargetAppRevisionName string `json:"targetAppRevisionName"`
// SourceAppRevisionName contains the name of the applicationRevision that we need to upgrade from.
// it can be empty only when the rolling is only a scale event
SourceAppRevisionName string `json:"sourceAppRevisionName,omitempty"`
// The list of component to upgrade in the application.
// We only support single component application so far
// TODO: (RZ) Support multiple components in an application
// +optional
ComponentList []string `json:"componentList,omitempty"`
// RolloutPlan is the details on how to rollout the resources
RolloutPlan v1alpha1.RolloutPlan `json:"rolloutPlan"`
// RevertOnDelete revert the rollout when the rollout CR is deleted
// It will remove the target app from the kubernetes if it's set to true
// +optional
RevertOnDelete *bool `json:"revertOnDelete,omitempty"`
}
// AppRolloutStatus defines the observed state of AppRollout
type AppRolloutStatus struct {
v1alpha1.RolloutStatus `json:",inline"`
// LastUpgradedTargetAppRevision contains the name of the app that we upgraded to
// We will restart the rollout if this is not the same as the spec
LastUpgradedTargetAppRevision string `json:"lastTargetAppRevision"`
// LastSourceAppRevision contains the name of the app that we need to upgrade from.
// We will restart the rollout if this is not the same as the spec
LastSourceAppRevision string `json:"LastSourceAppRevision,omitempty"`
}
// AppRollout is the Schema for the AppRollout API
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam},shortName=approllout
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="TARGET",type=string,JSONPath=`.status.rolloutStatus.rolloutTargetSize`
// +kubebuilder:printcolumn:name="UPGRADED",type=string,JSONPath=`.status.rolloutStatus.upgradedReplicas`
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.rolloutStatus.upgradedReadyReplicas`
// +kubebuilder:printcolumn:name="BATCH-STATE",type=string,JSONPath=`.status.rolloutStatus.batchRollingState`
// +kubebuilder:printcolumn:name="ROLLING-STATE",type=string,JSONPath=`.status.rolloutStatus.rollingState`
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
type AppRollout struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AppRolloutSpec `json:"spec,omitempty"`
Status AppRolloutStatus `json:"status,omitempty"`
}
// AppRolloutList contains a list of AppRollout
// +kubebuilder:object:root=true
type AppRolloutList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AppRollout `json:"items"`
}

View File

@@ -64,8 +64,6 @@ func ApplicationV1alpha2ToV1beta1(v1a2 *Application, v1b1 *v1beta1.Application)
Scopes: scopes,
})
}
// 3.2) convert Spec.RolloutPlan
v1b1.Spec.RolloutPlan = v1a2.Spec.RolloutPlan.DeepCopy()
// 4) convert Status common.AppStatus
v1b1.Status = *v1a2.Status.DeepCopy()
@@ -131,8 +129,6 @@ func (app *Application) ConvertFrom(src conversion.Hub) error {
Scopes: scopes,
})
}
// 3.2) convert Spec.RolloutPlan
app.Spec.RolloutPlan = sourceApp.Spec.RolloutPlan.DeepCopy()
// 4) convert Status common.AppStatus
app.Status = *sourceApp.Status.DeepCopy()

View File

@@ -109,14 +109,6 @@ var (
ApplicationKindVersionKind = SchemeGroupVersion.WithKind(ApplicationKind)
)
// AppRollout type metadata.
var (
AppRolloutKind = reflect.TypeOf(AppRollout{}).Name()
AppRolloutGroupKind = schema.GroupKind{Group: Group, Kind: AppRolloutKind}.String()
AppRolloutKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String()
AppRolloutKindVersionKind = SchemeGroupVersion.WithKind(AppRolloutKind)
)
// ApplicationRevision type metadata
var (
ApplicationRevisionKind = reflect.TypeOf(ApplicationRevision{}).Name()
@@ -135,6 +127,5 @@ func init() {
SchemeBuilder.Register(&ManualScalerTrait{}, &ManualScalerTraitList{})
SchemeBuilder.Register(&HealthScope{}, &HealthScopeList{})
SchemeBuilder.Register(&Application{}, &ApplicationList{})
SchemeBuilder.Register(&AppRollout{}, &AppRolloutList{})
SchemeBuilder.Register(&ApplicationRevision{}, &ApplicationRevisionList{})
}

View File

@@ -76,107 +76,6 @@ func (in *AppReference) DeepCopy() *AppReference {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRollout) DeepCopyInto(out *AppRollout) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRollout.
func (in *AppRollout) DeepCopy() *AppRollout {
if in == nil {
return nil
}
out := new(AppRollout)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppRollout) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRolloutList) DeepCopyInto(out *AppRolloutList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]AppRollout, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRolloutList.
func (in *AppRolloutList) DeepCopy() *AppRolloutList {
if in == nil {
return nil
}
out := new(AppRolloutList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppRolloutList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRolloutSpec) DeepCopyInto(out *AppRolloutSpec) {
*out = *in
if in.ComponentList != nil {
in, out := &in.ComponentList, &out.ComponentList
*out = make([]string, len(*in))
copy(*out, *in)
}
in.RolloutPlan.DeepCopyInto(&out.RolloutPlan)
if in.RevertOnDelete != nil {
in, out := &in.RevertOnDelete, &out.RevertOnDelete
*out = new(bool)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRolloutSpec.
func (in *AppRolloutSpec) DeepCopy() *AppRolloutSpec {
if in == nil {
return nil
}
out := new(AppRolloutSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRolloutStatus) DeepCopyInto(out *AppRolloutStatus) {
*out = *in
in.RolloutStatus.DeepCopyInto(&out.RolloutStatus)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRolloutStatus.
func (in *AppRolloutStatus) DeepCopy() *AppRolloutStatus {
if in == nil {
return nil
}
out := new(AppRolloutStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppStatus) DeepCopyInto(out *AppStatus) {
*out = *in

View File

@@ -1,176 +0,0 @@
/*
Copyright 2021. The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
)
// AppDeploymentPhase defines the phase that the AppDeployment is undergoing.
type AppDeploymentPhase string
const (
// PhaseRolling is the phase when the AppDeployment is rolling live instances from old revisions to new ones.
PhaseRolling AppDeploymentPhase = "Rolling"
// PhaseCompleted is the phase when the AppDeployment is done with reconciliation.
PhaseCompleted AppDeploymentPhase = "Completed"
// PhaseFailed is the phase when the AppDeployment has failed in reconciliation due to unexpected conditions.
PhaseFailed AppDeploymentPhase = "Failed"
)
// HTTPMatchRequest specifies a set of criterion to be met in order for the
// rule to be applied to the HTTP request. For example, the following
// restricts the rule to match only requests where the URL path
// starts with /ratings/v2/ and the request contains a custom `end-user` header
// with value `jason`.
type HTTPMatchRequest struct {
// URI defines how to match with an URI.
URI *URIMatch `json:"uri,omitempty"`
}
// URIMatch defines the rules to match with an URI.
type URIMatch struct {
Prefix string `json:"prefix,omitempty"`
}
// HTTPRule defines the rules to match and split http traffic across revisions.
type HTTPRule struct {
// Match defines the conditions to be satisfied for the rule to be
// activated. All conditions inside a single match block have AND
// semantics, while the list of match blocks have OR semantics. The rule
// is matched if any one of the match blocks succeed.
Match []*HTTPMatchRequest `json:"match,omitempty"`
// WeightedTargets defines the revision targets to select and route traffic to.
WeightedTargets []WeightedTarget `json:"weightedTargets,omitempty"`
}
// WeightedTarget defines the revision target to select and route traffic to.
type WeightedTarget struct {
// RevisionName is the name of the app revision.
RevisionName string `json:"revisionName,omitempty"`
// ComponentName is the name of the component.
// Note that it is the original component name in the Application. No need to append revision.
ComponentName string `json:"componentName,omitempty"`
// Port is the port to route traffic towards.
Port int `json:"port,omitempty"`
// Weight defines the proportion of traffic to be forwarded to the service
// version. (0-100). Sum of weights across destinations SHOULD BE == 100.
// If there is only one destination in a rule, the weight value is assumed to
// be 100.
Weight int `json:"weight,omitempty"`
}
// Traffic defines the traffic rules to apply across revisions.
type Traffic struct {
// Hosts are the destination hosts to which traffic is being sent. Could
// be a DNS name with wildcard prefix or an IP address.
Hosts []string `json:"hosts,omitempty"`
// Gateways specifies the names of gateways that should apply these rules.
// Gateways in other namespaces may be referred to by
// `<gateway namespace>/<gateway name>`; specifying a gateway with no
// namespace qualifier is the same as specifying the AppDeployment's namespace.
Gateways []string `json:"gateways,omitempty"`
// HTTP defines the rules to match and split http traffoc across revisions.
HTTP []HTTPRule `json:"http,omitempty"`
}
// AppRevision specifies an AppRevision resource to and the rules to apply to it.
type AppRevision struct {
// RevisionName is the name of the AppRevision.
RevisionName string `json:"revisionName,omitempty"`
// Placement defines the cluster placement rules for an app revision.
Placement []common.ClusterPlacement `json:"placement,omitempty"`
}
// ClusterPlacementStatus shows the placement results of a cluster.
type ClusterPlacementStatus struct {
// ClusterName indicates the name of the cluster to deploy apps to.
// If empty, it indicates the host cluster per se.
ClusterName string `json:"clusterName,omitempty"`
// Replicas indicates the replica number of an app revision to deploy to a cluster.
Replicas int `json:"replicas,omitempty"`
}
// PlacementStatus shows the cluster placement results of an app revision.
type PlacementStatus struct {
// RevisionName is the name of the AppRevision.
RevisionName string `json:"revisionName,omitempty"`
// Clusters shows cluster placement results.
Clusters []ClusterPlacementStatus `json:"clusters,omitempty"`
}
// AppDeploymentSpec defines how to describe an upgrade between different apps
type AppDeploymentSpec struct {
// Traffic defines the traffic rules to apply across revisions.
Traffic *Traffic `json:"traffic,omitempty"`
// AppRevision specifies AppRevision resources to and the rules to apply to them.
AppRevisions []AppRevision `json:"appRevisions,omitempty"`
}
// AppDeploymentStatus defines the observed state of AppDeployment
type AppDeploymentStatus struct {
// Conditions represents the latest available observations of a CloneSet's current state.
condition.ConditionedStatus `json:",inline"`
// Phase shows the phase that the AppDeployment is undergoing.
// If Phase is Rolling, no update should be made to the spec.
Phase AppDeploymentPhase `json:"phase,omitempty"`
// Placement shows the cluster placement results of the app revisions.
Placement []PlacementStatus `json:"placement,omitempty"`
}
// AppDeployment is the Schema for the AppDeployment API
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam},shortName=appdeploy
// +kubebuilder:subresource:status
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AppDeployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AppDeploymentSpec `json:"spec,omitempty"`
Status AppDeploymentStatus `json:"status,omitempty"`
}
// AppDeploymentList contains a list of AppDeployment
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AppDeploymentList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AppDeployment `json:"items"`
}

View File

@@ -17,12 +17,14 @@
package v1beta1
import (
"encoding/json"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
const (
@@ -86,11 +88,6 @@ type ApplicationSpec struct {
Workflow *Workflow `json:"workflow,omitempty"`
// TODO(wonderflow): we should have application level scopes supported here
// RolloutPlan is the details on how to rollout the resources
// The controller simply replace the old resources with the new one if there is no rollout plan involved
// +optional
RolloutPlan *v1alpha1.RolloutPlan `json:"rolloutPlan,omitempty"`
}
// +kubebuilder:object:root=true
@@ -144,3 +141,36 @@ func (app *Application) GetComponent(workloadType string) *common.ApplicationCom
}
return nil
}
// Unstructured convert application to unstructured.Unstructured.
func (app *Application) Unstructured() (*unstructured.Unstructured, error) {
var obj = &unstructured.Unstructured{}
app.SetGroupVersionKind(ApplicationKindVersionKind)
bt, err := json.Marshal(app)
if err != nil {
return nil, err
}
if err := obj.UnmarshalJSON(bt); err != nil {
return nil, err
}
if app.Status.Services == nil {
if err := unstructured.SetNestedSlice(obj.Object, []interface{}{}, "status", "services"); err != nil {
return nil, err
}
}
if app.Status.AppliedResources == nil {
if err := unstructured.SetNestedSlice(obj.Object, []interface{}{}, "status", "appliedResources"); err != nil {
return nil, err
}
}
if wfStatus := app.Status.Workflow; wfStatus != nil && wfStatus.Steps == nil {
if err := unstructured.SetNestedSlice(obj.Object, []interface{}{}, "status", "workflow", "steps"); err != nil {
return nil, err
}
}
return obj, nil
}

View File

@@ -1,81 +0,0 @@
/*
Copyright 2021. The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
// AppRolloutSpec defines how to describe an upgrade between different apps
type AppRolloutSpec struct {
// TargetAppRevisionName contains the name of the applicationConfiguration that we need to upgrade to.
// Here we use an applicationConfiguration as a revision of an application, thus the name alone is suffice
TargetAppRevisionName string `json:"targetAppRevisionName"`
// SourceAppRevisionName contains the name of the applicationConfiguration that we need to upgrade from.
// it can be empty only when it's the first time to deploy the application
SourceAppRevisionName string `json:"sourceAppRevisionName,omitempty"`
// The list of component to upgrade in the application.
// We only support single component application so far
// TODO: (RZ) Support multiple components in an application
// +optional
ComponentList []string `json:"componentList,omitempty"`
// RolloutPlan is the details on how to rollout the resources
RolloutPlan v1alpha1.RolloutPlan `json:"rolloutPlan"`
// RevertOnDelete revert the failed rollout when the rollout CR is deleted
// It will revert the change back to the source version at once (not in batches)
// Default is false
// +optional
RevertOnDelete bool `json:"revertOnDelete,omitempty"`
}
// AppRollout is the Schema for the AppRollout API
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam},shortName=approllout
// +kubebuilder:subresource:status
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="TARGET",type=string,JSONPath=`.status.rolloutTargetSize`
// +kubebuilder:printcolumn:name="UPGRADED",type=string,JSONPath=`.status.upgradedReplicas`
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.upgradedReadyReplicas`
// +kubebuilder:printcolumn:name="BATCH-STATE",type=string,JSONPath=`.status.batchRollingState`
// +kubebuilder:printcolumn:name="ROLLING-STATE",type=string,JSONPath=`.status.rollingState`
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AppRollout struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AppRolloutSpec `json:"spec,omitempty"`
Status common.AppRolloutStatus `json:"status,omitempty"`
}
// AppRolloutList contains a list of AppRollout
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AppRolloutList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AppRollout `json:"items"`
}

View File

@@ -1,64 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ClusterSpec defines the desired state of Cluster
type ClusterSpec struct {
// KubeconfigSecretRef specifies the reference to the secret
// that contains the kubeconfig in field `config`.
KubeconfigSecretRef LocalSecretReference `json:"kubeconfigSecretRef,omitempty"`
}
// LocalSecretReference is a reference to a secret within the enclosing
// namespace.
type LocalSecretReference struct {
// Name of a secret within the enclosing namespace.
Name string `json:"name"`
}
// ClusterStatus defines the observed state of Cluster
type ClusterStatus struct {
}
// +kubebuilder:object:root=true
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Cluster is the Schema for the clusters API
type Cluster struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ClusterSpec `json:"spec,omitempty"`
Status ClusterStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterList contains a list of Cluster
type ClusterList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Cluster `json:"items"`
}

View File

@@ -96,14 +96,6 @@ var (
ApplicationKindVersionKind = SchemeGroupVersion.WithKind(ApplicationKind)
)
// AppRollout type metadata.
var (
AppRolloutKind = reflect.TypeOf(AppRollout{}).Name()
AppRolloutGroupKind = schema.GroupKind{Group: Group, Kind: AppRolloutKind}.String()
AppRolloutKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String()
AppRolloutKindVersionKind = SchemeGroupVersion.WithKind(AppRolloutKind)
)
// ApplicationRevision type metadata
var (
ApplicationRevisionKind = reflect.TypeOf(ApplicationRevision{}).Name()
@@ -128,22 +120,6 @@ var (
ResourceTrackerKindVersionKind = SchemeGroupVersion.WithKind(ResourceTrackerKind)
)
// AppDeployment type metadata.
var (
AppDeploymentKind = reflect.TypeOf(AppDeployment{}).Name()
AppDeploymentGroupKind = schema.GroupKind{Group: Group, Kind: AppDeploymentKind}.String()
AppDeploymentKindAPIVersion = AppDeploymentKind + "." + SchemeGroupVersion.String()
AppDeploymentKindVersionKind = SchemeGroupVersion.WithKind(AppDeploymentKind)
)
// Cluster type metadata.
var (
ClusterKind = reflect.TypeOf(Cluster{}).Name()
ClusterGroupKind = schema.GroupKind{Group: Group, Kind: ClusterKind}.String()
ClusterKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String()
ClusterKindVersionKind = SchemeGroupVersion.WithKind(ClusterKind)
)
func init() {
SchemeBuilder.Register(&ComponentDefinition{}, &ComponentDefinitionList{})
SchemeBuilder.Register(&WorkloadDefinition{}, &WorkloadDefinitionList{})
@@ -153,10 +129,7 @@ func init() {
SchemeBuilder.Register(&DefinitionRevision{}, &DefinitionRevisionList{})
SchemeBuilder.Register(&ScopeDefinition{}, &ScopeDefinitionList{})
SchemeBuilder.Register(&Application{}, &ApplicationList{})
SchemeBuilder.Register(&AppRollout{}, &AppRolloutList{})
SchemeBuilder.Register(&ApplicationRevision{}, &ApplicationRevisionList{})
SchemeBuilder.Register(&AppDeployment{}, &AppDeploymentList{})
SchemeBuilder.Register(&Cluster{}, &ClusterList{})
SchemeBuilder.Register(&ResourceTracker{}, &ResourceTrackerList{})
}

View File

@@ -187,7 +187,7 @@ func (in *ResourceTracker) findMangedResourceIndex(mr ManagedResource) int {
}
// AddManagedResource add object to managed resources, if exists, update
func (in *ResourceTracker) AddManagedResource(rsc client.Object, metaOnly bool) {
func (in *ResourceTracker) AddManagedResource(rsc client.Object, metaOnly bool) (updated bool) {
gvk := rsc.GetObjectKind().GroupVersionKind()
mr := ManagedResource{
ClusterObjectReference: common.ClusterObjectReference{
@@ -206,17 +206,21 @@ func (in *ResourceTracker) AddManagedResource(rsc client.Object, metaOnly bool)
mr.Data = &runtime.RawExtension{Object: rsc}
}
if idx := in.findMangedResourceIndex(mr); idx >= 0 {
if reflect.DeepEqual(in.Spec.ManagedResources[idx], mr) {
return false
}
in.Spec.ManagedResources[idx] = mr
} else {
in.Spec.ManagedResources = append(in.Spec.ManagedResources, mr)
}
return true
}
// DeleteManagedResource if remove flag is on, it will remove the object from recorded resources.
// otherwise, it will mark the object as deleted instead of removing it
// workflow stage: resources are marked as deleted (and execute the deletion action)
// state-keep stage: resources marked as deleted and successfully deleted will be removed from resourcetracker
func (in *ResourceTracker) DeleteManagedResource(rsc client.Object, remove bool) {
func (in *ResourceTracker) DeleteManagedResource(rsc client.Object, remove bool) (updated bool) {
gvk := rsc.GetObjectKind().GroupVersionKind()
mr := ManagedResource{
ClusterObjectReference: common.ClusterObjectReference{
@@ -234,6 +238,9 @@ func (in *ResourceTracker) DeleteManagedResource(rsc client.Object, remove bool)
if remove {
in.Spec.ManagedResources = append(in.Spec.ManagedResources[:idx], in.Spec.ManagedResources[idx+1:]...)
} else {
if reflect.DeepEqual(in.Spec.ManagedResources[idx], mr) {
return false
}
in.Spec.ManagedResources[idx] = mr
}
} else {
@@ -241,6 +248,7 @@ func (in *ResourceTracker) DeleteManagedResource(rsc client.Object, remove bool)
in.Spec.ManagedResources = append(in.Spec.ManagedResources, mr)
}
}
return true
}
// addClusterObjectReference

View File

@@ -25,118 +25,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppDeployment) DeepCopyInto(out *AppDeployment) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppDeployment.
func (in *AppDeployment) DeepCopy() *AppDeployment {
if in == nil {
return nil
}
out := new(AppDeployment)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppDeployment) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppDeploymentList) DeepCopyInto(out *AppDeploymentList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]AppDeployment, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppDeploymentList.
func (in *AppDeploymentList) DeepCopy() *AppDeploymentList {
if in == nil {
return nil
}
out := new(AppDeploymentList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppDeploymentList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppDeploymentSpec) DeepCopyInto(out *AppDeploymentSpec) {
*out = *in
if in.Traffic != nil {
in, out := &in.Traffic, &out.Traffic
*out = new(Traffic)
(*in).DeepCopyInto(*out)
}
if in.AppRevisions != nil {
in, out := &in.AppRevisions, &out.AppRevisions
*out = make([]AppRevision, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppDeploymentSpec.
func (in *AppDeploymentSpec) DeepCopy() *AppDeploymentSpec {
if in == nil {
return nil
}
out := new(AppDeploymentSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppDeploymentStatus) DeepCopyInto(out *AppDeploymentStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
if in.Placement != nil {
in, out := &in.Placement, &out.Placement
*out = make([]PlacementStatus, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppDeploymentStatus.
func (in *AppDeploymentStatus) DeepCopy() *AppDeploymentStatus {
if in == nil {
return nil
}
out := new(AppDeploymentStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppPolicy) DeepCopyInto(out *AppPolicy) {
*out = *in
@@ -157,108 +47,6 @@ func (in *AppPolicy) DeepCopy() *AppPolicy {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRevision) DeepCopyInto(out *AppRevision) {
*out = *in
if in.Placement != nil {
in, out := &in.Placement, &out.Placement
*out = make([]common.ClusterPlacement, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRevision.
func (in *AppRevision) DeepCopy() *AppRevision {
if in == nil {
return nil
}
out := new(AppRevision)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRollout) DeepCopyInto(out *AppRollout) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRollout.
func (in *AppRollout) DeepCopy() *AppRollout {
if in == nil {
return nil
}
out := new(AppRollout)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppRollout) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRolloutList) DeepCopyInto(out *AppRolloutList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]AppRollout, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRolloutList.
func (in *AppRolloutList) DeepCopy() *AppRolloutList {
if in == nil {
return nil
}
out := new(AppRolloutList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppRolloutList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppRolloutSpec) DeepCopyInto(out *AppRolloutSpec) {
*out = *in
if in.ComponentList != nil {
in, out := &in.ComponentList, &out.ComponentList
*out = make([]string, len(*in))
copy(*out, *in)
}
in.RolloutPlan.DeepCopyInto(&out.RolloutPlan)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppRolloutSpec.
func (in *AppRolloutSpec) DeepCopy() *AppRolloutSpec {
if in == nil {
return nil
}
out := new(AppRolloutSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Application) DeepCopyInto(out *Application) {
*out = *in
@@ -472,11 +260,6 @@ func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
*out = new(Workflow)
(*in).DeepCopyInto(*out)
}
if in.RolloutPlan != nil {
in, out := &in.RolloutPlan, &out.RolloutPlan
*out = new(v1alpha1.RolloutPlan)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec.
@@ -489,111 +272,6 @@ func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Cluster) DeepCopyInto(out *Cluster) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
out.Status = in.Status
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster.
func (in *Cluster) DeepCopy() *Cluster {
if in == nil {
return nil
}
out := new(Cluster)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Cluster) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterList) DeepCopyInto(out *ClusterList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Cluster, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterList.
func (in *ClusterList) DeepCopy() *ClusterList {
if in == nil {
return nil
}
out := new(ClusterList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterPlacementStatus) DeepCopyInto(out *ClusterPlacementStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPlacementStatus.
func (in *ClusterPlacementStatus) DeepCopy() *ClusterPlacementStatus {
if in == nil {
return nil
}
out := new(ClusterPlacementStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = *in
out.KubeconfigSecretRef = in.KubeconfigSecretRef
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSpec.
func (in *ClusterSpec) DeepCopy() *ClusterSpec {
if in == nil {
return nil
}
out := new(ClusterSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
if in == nil {
return nil
}
out := new(ClusterStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ComponentDefinition) DeepCopyInto(out *ComponentDefinition) {
*out = *in
@@ -789,72 +467,6 @@ func (in *DefinitionRevisionSpec) DeepCopy() *DefinitionRevisionSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPMatchRequest) DeepCopyInto(out *HTTPMatchRequest) {
*out = *in
if in.URI != nil {
in, out := &in.URI, &out.URI
*out = new(URIMatch)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPMatchRequest.
func (in *HTTPMatchRequest) DeepCopy() *HTTPMatchRequest {
if in == nil {
return nil
}
out := new(HTTPMatchRequest)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPRule) DeepCopyInto(out *HTTPRule) {
*out = *in
if in.Match != nil {
in, out := &in.Match, &out.Match
*out = make([]*HTTPMatchRequest, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(HTTPMatchRequest)
(*in).DeepCopyInto(*out)
}
}
}
if in.WeightedTargets != nil {
in, out := &in.WeightedTargets, &out.WeightedTargets
*out = make([]WeightedTarget, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRule.
func (in *HTTPRule) DeepCopy() *HTTPRule {
if in == nil {
return nil
}
out := new(HTTPRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LocalSecretReference) DeepCopyInto(out *LocalSecretReference) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalSecretReference.
func (in *LocalSecretReference) DeepCopy() *LocalSecretReference {
if in == nil {
return nil
}
out := new(LocalSecretReference)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedResource) DeepCopyInto(out *ManagedResource) {
*out = *in
@@ -877,26 +489,6 @@ func (in *ManagedResource) DeepCopy() *ManagedResource {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PlacementStatus) DeepCopyInto(out *PlacementStatus) {
*out = *in
if in.Clusters != nil {
in, out := &in.Clusters, &out.Clusters
*out = make([]ClusterPlacementStatus, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementStatus.
func (in *PlacementStatus) DeepCopy() *PlacementStatus {
if in == nil {
return nil
}
out := new(PlacementStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyDefinition) DeepCopyInto(out *PolicyDefinition) {
*out = *in
@@ -1178,38 +770,6 @@ func (in *ScopeDefinitionSpec) DeepCopy() *ScopeDefinitionSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Traffic) DeepCopyInto(out *Traffic) {
*out = *in
if in.Hosts != nil {
in, out := &in.Hosts, &out.Hosts
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Gateways != nil {
in, out := &in.Gateways, &out.Gateways
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.HTTP != nil {
in, out := &in.HTTP, &out.HTTP
*out = make([]HTTPRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Traffic.
func (in *Traffic) DeepCopy() *Traffic {
if in == nil {
return nil
}
out := new(Traffic)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TraitDefinition) DeepCopyInto(out *TraitDefinition) {
*out = *in
@@ -1331,36 +891,6 @@ func (in *TraitDefinitionStatus) DeepCopy() *TraitDefinitionStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *URIMatch) DeepCopyInto(out *URIMatch) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new URIMatch.
func (in *URIMatch) DeepCopy() *URIMatch {
if in == nil {
return nil
}
out := new(URIMatch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WeightedTarget) DeepCopyInto(out *WeightedTarget) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedTarget.
func (in *WeightedTarget) DeepCopy() *WeightedTarget {
if in == nil {
return nil
}
out := new(WeightedTarget)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Workflow) DeepCopyInto(out *Workflow) {
*out = *in

View File

@@ -179,6 +179,8 @@ type Capability struct {
// Terraform
TerraformConfiguration string `json:"terraformConfiguration,omitempty"`
ConfigurationType string `json:"configurationType,omitempty"`
Path string `json:"path,omitempty"`
// KubeTemplate
KubeTemplate runtime.RawExtension `json:"kubetemplate,omitempty"`

View File

@@ -48,6 +48,14 @@ const (
LabelDefinitionDeprecated = "custom.definition.oam.dev/deprecated"
// LabelDefinitionHidden is the label which describe whether the capability is hidden by UI
LabelDefinitionHidden = "custom.definition.oam.dev/ui-hidden"
// LabelNodeRoleGateway gateway role of node
LabelNodeRoleGateway = "node-role.kubernetes.io/gateway"
// LabelNodeRoleWorker worker role of node
LabelNodeRoleWorker = "node-role.kubernetes.io/worker"
// AnnoIngressControllerHTTPSPort define ingress controller listen port for https
AnnoIngressControllerHTTPSPort = "ingress.controller/https-port"
// AnnoIngressControllerHTTPPort define ingress controller listen port for http
AnnoIngressControllerHTTPPort = "ingress.controller/http-port"
)
const (
@@ -70,20 +78,27 @@ type EnvMeta struct {
const (
// TagCommandType used for tag cli category
TagCommandType = "commandType"
// TagCommandOrder defines the order
TagCommandOrder = "commandOrder"
// TypeStart defines one category
TypeStart = "Getting Started"
// TypeApp defines one category
TypeApp = "Managing Applications"
// TypeCap defines one category
TypeCap = "Managing Capabilities"
// TypeCD defines workflow Management operations
TypeCD = "Continuous Delivery"
// TypeExtension defines one category
TypeExtension = "Managing Extension"
// TypeSystem defines one category
TypeSystem = "System"
// TypeDefinition defines one category
TypeDefinition = "Managing Definitions"
TypeSystem = "Others"
// TypePlugin defines one category used in Kubectl Plugin
TypePlugin = "Plugin Command"
// TypeUISchema defines one category
TypeUISchema = "Managing UISchema"
)
// LabelArg is the argument `label` of a definition

View File

@@ -1,246 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: appdeployments.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: AppDeployment
listKind: AppDeploymentList
plural: appdeployments
shortNames:
- appdeploy
singular: appdeployment
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: AppDeployment is the Schema for the AppDeployment API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AppDeploymentSpec defines how to describe an upgrade between
different apps
properties:
appRevisions:
description: AppRevision specifies AppRevision resources to and the
rules to apply to them.
items:
description: AppRevision specifies an AppRevision resource to and
the rules to apply to it.
properties:
placement:
description: Placement defines the cluster placement rules for
an app revision.
items:
description: ClusterPlacement defines the cluster placement
rules for an app revision.
properties:
clusterSelector:
description: ClusterSelector selects the cluster to deploy
apps to. If not specified, it indicates the host cluster
per se.
properties:
labels:
additionalProperties:
type: string
description: Labels defines the label selector to
select the cluster.
type: object
name:
description: Name is the name of the cluster.
type: string
type: object
distribution:
description: Distribution defines the replica distribution
of an AppRevision to a cluster.
properties:
replicas:
description: Replicas is the replica number.
type: integer
type: object
type: object
type: array
revisionName:
description: RevisionName is the name of the AppRevision.
type: string
type: object
type: array
traffic:
description: Traffic defines the traffic rules to apply across revisions.
properties:
gateways:
description: Gateways specifies the names of gateways that should
apply these rules. Gateways in other namespaces may be referred
to by `<gateway namespace>/<gateway name>`; specifying a gateway
with no namespace qualifier is the same as specifying the AppDeployment's
namespace.
items:
type: string
type: array
hosts:
description: Hosts are the destination hosts to which traffic
is being sent. Could be a DNS name with wildcard prefix or an
IP address.
items:
type: string
type: array
http:
description: HTTP defines the rules to match and split http traffoc
across revisions.
items:
description: HTTPRule defines the rules to match and split http
traffic across revisions.
properties:
match:
description: Match defines the conditions to be satisfied
for the rule to be activated. All conditions inside a
single match block have AND semantics, while the list
of match blocks have OR semantics. The rule is matched
if any one of the match blocks succeed.
items:
description: HTTPMatchRequest specifies a set of criterion
to be met in order for the rule to be applied to the
HTTP request. For example, the following restricts the
rule to match only requests where the URL path starts
with /ratings/v2/ and the request contains a custom
`end-user` header with value `jason`.
properties:
uri:
description: URI defines how to match with an URI.
properties:
prefix:
type: string
type: object
type: object
type: array
weightedTargets:
description: WeightedTargets defines the revision targets
to select and route traffic to.
items:
description: WeightedTarget defines the revision target
to select and route traffic to.
properties:
componentName:
description: ComponentName is the name of the component.
Note that it is the original component name in the
Application. No need to append revision.
type: string
port:
description: Port is the port to route traffic towards.
type: integer
revisionName:
description: RevisionName is the name of the app revision.
type: string
weight:
description: Weight defines the proportion of traffic
to be forwarded to the service version. (0-100).
Sum of weights across destinations SHOULD BE ==
100. If there is only one destination in a rule,
the weight value is assumed to be 100.
type: integer
type: object
type: array
type: object
type: array
type: object
type: object
status:
description: AppDeploymentStatus defines the observed state of AppDeployment
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
phase:
description: Phase shows the phase that the AppDeployment is undergoing.
If Phase is Rolling, no update should be made to the spec.
type: string
placement:
description: Placement shows the cluster placement results of the
app revisions.
items:
description: PlacementStatus shows the cluster placement results
of an app revision.
properties:
clusters:
description: Clusters shows cluster placement results.
items:
description: ClusterPlacementStatus shows the placement results
of a cluster.
properties:
clusterName:
description: ClusterName indicates the name of the cluster
to deploy apps to. If empty, it indicates the host cluster
per se.
type: string
replicas:
description: Replicas indicates the replica number of
an app revision to deploy to a cluster.
type: integer
type: object
type: array
revisionName:
description: RevisionName is the name of the AppRevision.
type: string
type: object
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -677,113 +677,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of
AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of
the app that we need to upgrade from. We will restart
the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the
Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time
this condition transitioned from one status to
another.
format: date-time
type: string
message:
description: A Message containing details about
this condition's last transition from one status
to another, if any.
type: string
reason:
description: A Reason for this condition's last
transition from one status to another.
type: string
status:
description: Status of this condition; is it currently
True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one
of each condition type may apply to a resource
at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working
on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string
that uniquely represent the last pod template each workload
type could use different ways to identify that so we
cannot compare between resources We update this field
only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the
name of the app that we upgraded to We will restart
the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that
uniquely represent the new pod template each workload
type could use different ways to identify that so we
cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods
upgraded by the rollout controller that have a Ready
Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded
by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application
services
@@ -2324,324 +2217,6 @@ spec:
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout
the resources The controller simply replace the old resources
with the new one if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification
while the rest still have the source resource This is
designed for the operators to manually rollout Default
is the the number of batches which will rollout all
the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout
process to automatically check certain metrics before
complete the process
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an
object instead of an entire object, this string
should contain a valid JSON/Go field access
statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to
a container within a pod, this would take
on a value like: "spec.containers{name}" (where
"name" refers to the name of the container
that triggered the event) or if no container
name is specified "spec.containers[2]" (container
with index 2 in this pod). This syntax is
chosen only to have some well-defined way
of referencing a part of an object. TODO:
this design is not final and this field is
subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which
this reference is made, if any. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its
size has to be exactly the same as the NumBatches (if
set) The total number cannot exceed the targetSize or
the size of the source resource We will IGNORE the last
batch's replica field if it's a percentage since round
errors can lead to inaccurate sum We highly recommend
to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the
each batch rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for
the batch rollout to interact with an external
process
items:
description: RolloutWebhook holds the reference
to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the
expected http status code that we will accept
as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for
this webhook
type: object
method:
description: Method the HTTP call method,
default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the
batch rollout process to automatically check certain
metrics before moving to the next batch
items:
description: CanaryMetric holds the reference
to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows
size
type: string
metricsRange:
description: Range value accepted for this
metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric
template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece
of an object instead of an entire object,
this string should contain a valid JSON/Go
field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference
is to a container within a pod, this
would take on a value like: "spec.containers{name}"
(where "name" refers to the name of
the container that triggered the event)
or if no container name is specified
"spec.containers[2]" (container with
index 2 in this pod). This syntax is
chosen only to have some well-defined
way of referencing a part of an object.
TODO: this design is not final and this
field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More
info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion
to which this reference is made, if
any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between
instances upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number
of pods that is unavailable during the upgrade.
We will mark the batch as ready as long as there
are less or equal number of pods unavailable than
this number. default = 0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it
is mutually exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to
upgrade in this batch it can be an absolute number
(ex: 5) or a percentage of total pods we will
ignore the percentage of the last batch to just
fill the gap it is mutually exclusive with the
PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the
rollout plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout
to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this
webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default
is the same as the size of the source resource.
format: int32
type: integer
type: object
workflow:
description: 'Workflow defines how to customize the control
logic. If workflow is specified, Vela won''t apply any resource,
@@ -2937,113 +2512,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of
AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of
the app that we need to upgrade from. We will restart
the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the
Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time
this condition transitioned from one status to
another.
format: date-time
type: string
message:
description: A Message containing details about
this condition's last transition from one status
to another, if any.
type: string
reason:
description: A Reason for this condition's last
transition from one status to another.
type: string
status:
description: Status of this condition; is it currently
True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one
of each condition type may apply to a resource
at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working
on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string
that uniquely represent the last pod template each workload
type could use different ways to identify that so we
cannot compare between resources We update this field
only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the
name of the app that we upgraded to We will restart
the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that
uniquely represent the new pod template each workload
type could use different ways to identify that so we
cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods
upgraded by the rollout controller that have a Ready
Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded
by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application
services

View File

@@ -485,82 +485,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that we need to upgrade from. We will restart the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from one status to another.
type: string
status:
description: Status of this condition; is it currently True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely represent the last pod template each workload type could use different ways to identify that so we cannot compare between resources We update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the app that we upgraded to We will restart the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent the new pod template each workload type could use different ways to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application services
items:
@@ -876,234 +800,6 @@ spec:
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources The controller simply replace the old resources with the new one if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition (included) will have the target resource specification while the rest still have the source resource This is designed for the operators to manually rollout Default is the the number of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has to be exactly the same as the NumBatches (if set) The total number cannot exceed the targetSize or the size of the source resource We will IGNORE the last batch's replica field if it's a percentage since round errors can lead to inaccurate sum We highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout process to automatically check certain metrics before moving to the next batch
items:
description: CanaryMetric holds the reference to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of pods that is unavailable during the upgrade. We will mark the batch as ready as long as there are less or equal number of pods unavailable than this number. default = 0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade in this batch it can be an absolute number (ex: 5) or a percentage of total pods we will ignore the percentage of the last batch to just fill the gap it is mutually exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the same as the size of the source resource.
format: int32
type: integer
type: object
workflow:
description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.'
properties:
@@ -1311,82 +1007,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that we need to upgrade from. We will restart the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from one status to another.
type: string
status:
description: Status of this condition; is it currently True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely represent the last pod template each workload type could use different ways to identify that so we cannot compare between resources We update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the app that we upgraded to We will restart the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent the new pod template each workload type could use different ways to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application services
items:

View File

@@ -1,954 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: approllouts.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: AppRollout
listKind: AppRolloutList
plural: approllouts
shortNames:
- approllout
singular: approllout
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.rolloutStatus.rolloutTargetSize
name: TARGET
type: string
- jsonPath: .status.rolloutStatus.upgradedReplicas
name: UPGRADED
type: string
- jsonPath: .status.rolloutStatus.upgradedReadyReplicas
name: READY
type: string
- jsonPath: .status.rolloutStatus.batchRollingState
name: BATCH-STATE
type: string
- jsonPath: .status.rolloutStatus.rollingState
name: ROLLING-STATE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1alpha2
schema:
openAPIV3Schema:
description: AppRollout is the Schema for the AppRollout API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AppRolloutSpec defines how to describe an upgrade between
different apps
properties:
componentList:
description: 'The list of component to upgrade in the application.
We only support single component application so far TODO: (RZ) Support
multiple components in an application'
items:
type: string
type: array
revertOnDelete:
description: RevertOnDelete revert the rollout when the rollout CR
is deleted It will remove the target app from the kubernetes if
it's set to true
type: boolean
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification while
the rest still have the source resource This is designed for
the operators to manually rollout Default is the the number
of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process
to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used
for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a
valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container
within a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container
that triggered the event) or if no container name
is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to
have some well-defined way of referencing a part of
an object. TODO: this design is not final and this
field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this
reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has
to be exactly the same as the NumBatches (if set) The total
number cannot exceed the targetSize or the size of the source
resource We will IGNORE the last batch's replica field if it's
a percentage since round errors can lead to inaccurate sum We
highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch
rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch
rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout
process to automatically check certain metrics before
moving to the next batch
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object
instead of an entire object, this string should
contain a valid JSON/Go field access statement,
such as desiredState.manifest.containers[2].
For example, if the object reference is to a
container within a pod, this would take on a
value like: "spec.containers{name}" (where "name"
refers to the name of the container that triggered
the event) or if no container name is specified
"spec.containers[2]" (container with index 2
in this pod). This syntax is chosen only to
have some well-defined way of referencing a
part of an object. TODO: this design is not
final and this field is subject to change in
the future.'
type: string
kind:
description: 'Kind of the referent. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which
this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances
upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of
pods that is unavailable during the upgrade. We will mark
the batch as ready as long as there are less or equal
number of pods unavailable than this number. default =
0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually
exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade
in this batch it can be an absolute number (ex: 5) or
a percentage of total pods we will ignore the percentage
of the last batch to just fill the gap it is mutually
exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout
plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to
interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http
status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the
same as the size of the source resource.
format: int32
type: integer
type: object
sourceAppRevisionName:
description: SourceAppRevisionName contains the name of the applicationRevision
that we need to upgrade from. it can be empty only when the rolling
is only a scale event
type: string
targetAppRevisionName:
description: TargetAppRevisionName contains the name of the applicationRevision
that we need to upgrade to.
type: string
required:
- rolloutPlan
- targetAppRevisionName
type: object
status:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that
we need to upgrade from. We will restart the rollout if this is
not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is
rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked it
starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely
represent the last pod template each workload type could use different
ways to identify that so we cannot compare between resources We
update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the
app that we upgraded to We will restart the rollout if this is not
the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent
the new pod template each workload type could use different ways
to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded
by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the
rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .status.rolloutTargetSize
name: TARGET
type: string
- jsonPath: .status.upgradedReplicas
name: UPGRADED
type: string
- jsonPath: .status.upgradedReadyReplicas
name: READY
type: string
- jsonPath: .status.batchRollingState
name: BATCH-STATE
type: string
- jsonPath: .status.rollingState
name: ROLLING-STATE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: AppRollout is the Schema for the AppRollout API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AppRolloutSpec defines how to describe an upgrade between
different apps
properties:
componentList:
description: 'The list of component to upgrade in the application.
We only support single component application so far TODO: (RZ) Support
multiple components in an application'
items:
type: string
type: array
revertOnDelete:
description: RevertOnDelete revert the failed rollout when the rollout
CR is deleted It will revert the change back to the source version
at once (not in batches) Default is false
type: boolean
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification while
the rest still have the source resource This is designed for
the operators to manually rollout Default is the the number
of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process
to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used
for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a
valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container
within a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container
that triggered the event) or if no container name
is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to
have some well-defined way of referencing a part of
an object. TODO: this design is not final and this
field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this
reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has
to be exactly the same as the NumBatches (if set) The total
number cannot exceed the targetSize or the size of the source
resource We will IGNORE the last batch's replica field if it's
a percentage since round errors can lead to inaccurate sum We
highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch
rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch
rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout
process to automatically check certain metrics before
moving to the next batch
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object
instead of an entire object, this string should
contain a valid JSON/Go field access statement,
such as desiredState.manifest.containers[2].
For example, if the object reference is to a
container within a pod, this would take on a
value like: "spec.containers{name}" (where "name"
refers to the name of the container that triggered
the event) or if no container name is specified
"spec.containers[2]" (container with index 2
in this pod). This syntax is chosen only to
have some well-defined way of referencing a
part of an object. TODO: this design is not
final and this field is subject to change in
the future.'
type: string
kind:
description: 'Kind of the referent. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which
this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances
upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of
pods that is unavailable during the upgrade. We will mark
the batch as ready as long as there are less or equal
number of pods unavailable than this number. default =
0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually
exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade
in this batch it can be an absolute number (ex: 5) or
a percentage of total pods we will ignore the percentage
of the last batch to just fill the gap it is mutually
exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout
plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to
interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http
status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the
same as the size of the source resource.
format: int32
type: integer
type: object
sourceAppRevisionName:
description: SourceAppRevisionName contains the name of the applicationConfiguration
that we need to upgrade from. it can be empty only when it's the
first time to deploy the application
type: string
targetAppRevisionName:
description: TargetAppRevisionName contains the name of the applicationConfiguration
that we need to upgrade to. Here we use an applicationConfiguration
as a revision of an application, thus the name alone is suffice
type: string
required:
- rolloutPlan
- targetAppRevisionName
type: object
status:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that
we need to upgrade from. We will restart the rollout if this is
not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is
rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked it
starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely
represent the last pod template each workload type could use different
ways to identify that so we cannot compare between resources We
update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the
app that we upgraded to We will restart the rollout if this is not
the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent
the new pod template each workload type could use different ways
to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded
by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the
rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,60 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: clusters.core.oam.dev
spec:
group: core.oam.dev
names:
kind: Cluster
listKind: ClusterList
plural: clusters
singular: cluster
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: Cluster is the Schema for the clusters API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ClusterSpec defines the desired state of Cluster
properties:
kubeconfigSecretRef:
description: KubeconfigSecretRef specifies the reference to the secret
that contains the kubeconfig in field `config`.
properties:
name:
description: Name of a secret within the enclosing namespace.
type: string
required:
- name
type: object
type: object
status:
description: ClusterStatus defines the observed state of Cluster
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -22,6 +22,10 @@ spec:
app: {{ template "kubevela.name" . }}-admission-create
{{- include "kubevela.labels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: create
image: {{ .Values.imageRegistry }}{{ .Values.admissionWebhooks.patch.image.repository }}:{{ .Values.admissionWebhooks.patch.image.tag }}

View File

@@ -22,6 +22,10 @@ spec:
app: {{ template "kubevela.name" . }}-admission-patch
{{- include "kubevela.labels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: patch
image: {{ .Values.imageRegistry }}{{ .Values.admissionWebhooks.patch.image.repository }}:{{ .Values.admissionWebhooks.patch.image.tag }}

View File

@@ -198,6 +198,10 @@ spec:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
{{- include "kubevela.labels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: create
image: {{ .Values.imageRegistry }}{{ .Values.admissionWebhooks.patch.image.repository }}:{{ .Values.admissionWebhooks.patch.image.tag }}
@@ -241,6 +245,10 @@ spec:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
{{- include "kubevela.labels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: patch
image: {{ .Values.imageRegistry }}{{ .Values.multicluster.clusterGateway.image.repository }}:{{ .Values.multicluster.clusterGateway.image.tag }}

View File

@@ -32,21 +32,30 @@ spec:
kind: "Ingress"
metadata: {
name: context.name
annotations: "kubernetes.io/ingress.class": parameter.class
annotations: {
if !parameter.classInSpec {
"kubernetes.io/ingress.class": parameter.class
}
}
}
spec: {
if parameter.classInSpec {
ingressClassName: parameter.class
}
rules: [{
host: parameter.domain
http: paths: [
for k, v in parameter.http {
path: k
pathType: "ImplementationSpecific"
backend: service: {
name: context.name
port: number: v
}
},
]
}]
}
spec: rules: [{
host: parameter.domain
http: paths: [
for k, v in parameter.http {
path: k
pathType: "ImplementationSpecific"
backend: service: {
name: context.name
port: number: v
}
},
]
}]
}
parameter: {
// +usage=Specify the domain you want to expose
@@ -57,6 +66,9 @@ spec:
// +usage=Specify the class of ingress to use
class: *"nginx" | string
// +usage=Set ingress class in '.spec.ingressClassName' instead of 'kubernetes.io/ingress.class' annotation.
classInSpec: *false | bool
}
status:
customStatus: |-

View File

@@ -17,6 +17,27 @@ spec:
)
parameter: {
lark?: {
// +usage=Specify the the lark url, you can either sepcify it in value or use secretRef
url: {
value: string
} | {
secretRef: {
// +usage=name is the name of the secret
name: string
// +usage=key is the key in the secret
key: string
}
}
// +useage=Specify the message that you want to sent
message: {
// +usage=msg_type can be text, post, image, interactive, share_chat, share_user, audio, media, file, sticker
msg_type: string
// +usage=content should be json encode string
content: string
}
}
dingding?: {
// +usage=Specify the the dingding url, you can either sepcify it in value or use secretRef
url: {
@@ -207,6 +228,35 @@ spec:
}
}
}
lark: op.#Steps & {
if parameter.lark != _|_ {
if parameter.lark.url.value != _|_ {
lark1: op.#Lark & {
message: parameter.lark.message
larkUrl: parameter.lark.url.value
}
}
if parameter.lark.url.secretRef != _|_ && parameter.lark.url.value == _|_ {
read: op.#Read & {
value: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: parameter.lark.url.secretRef.name
namespace: context.namespace
}
}
}
decoded: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key])
stringValue: op.#ConvertString & {bt: decoded}
lark2: op.#Lark & {
message: parameter.lark.message
larkUrl: stringValue.str
}
}
}
}
slack: op.#Steps & {
if parameter.slack != _|_ {
if parameter.slack.url.value != _|_ {

View File

@@ -109,10 +109,10 @@ spec:
}
parameter: {
// +usage=Specify the labels in the workload
labels?: {...}
labels?: [string]: string
// +usage=Specify the annotations in the workload
annotations?: {...}
annotations?: [string]: string
// +usage=Specify number of tasks to run in parallel
// +short=c

View File

@@ -11,6 +11,10 @@ spec:
schematic:
cue:
template: |
import (
"strconv"
)
mountsArray: {
pvc: *[
for v in parameter.volumeMounts.pvc {
@@ -152,6 +156,12 @@ spec:
{
containerPort: v.port
protocol: v.protocol
if v.name != _|_ {
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
}
}}]
}
@@ -262,6 +272,12 @@ spec:
for v in parameter.ports if v.expose == true {
port: v.port
targetPort: v.port
if v.name != _|_ {
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
}
},
]
outputs: {
@@ -280,10 +296,10 @@ spec:
}
parameter: {
// +usage=Specify the labels in the workload
labels?: {...}
labels?: [string]: string
// +usage=Specify the annotations in the workload
annotations?: {...}
annotations?: [string]: string
// +usage=Which image would you like to use for your service
// +short=i
@@ -304,6 +320,8 @@ spec:
ports?: [...{
// +usage=Number of port to expose on the pod's IP address
port: int
// +usage=Name of the port
name?: string
// +usage=Protocol for port. Must be UDP, TCP, or SCTP
protocol: *"TCP" | "UDP" | "SCTP"
// +usage=Specify if the port should be exposed
@@ -494,12 +512,7 @@ spec:
replica: strconv.FormatInt(context.output.status.readyReplicas, 10)
}
}
if context.output.status.replicas != _|_ {
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.status.replicas, 10)
}
if context.output.status.replicas == _|_ {
message: ""
}
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
healthPolicy: |-
ready: {
if context.output.status.readyReplicas == _|_ {
@@ -509,12 +522,7 @@ spec:
replica: context.output.status.readyReplicas
}
}
if context.output.status.replicas != _|_ {
isHealth: context.output.status.replicas == ready.replica
}
if context.output.status.replicas == _|_ {
isHealth: false
}
isHealth: context.output.spec.replicas == ready.replica
workload:
definition:
apiVersion: apps/v1

View File

@@ -405,12 +405,7 @@ spec:
replica: strconv.FormatInt(context.output.status.readyReplicas, 10)
}
}
if context.output.status.replicas != _|_ {
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.status.replicas, 10)
}
if context.output.status.replicas == _|_ {
message: ""
}
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
healthPolicy: |-
ready: {
if context.output.status.readyReplicas == _|_ {
@@ -420,12 +415,7 @@ spec:
replica: context.output.status.readyReplicas
}
}
if context.output.status.replicas != _|_ {
isHealth: context.output.status.replicas == ready.replica
}
if context.output.status.replicas == _|_ {
isHealth: false
}
isHealth: context.output.spec.replicas == ready.replica
workload:
definition:
apiVersion: apps/v1

View File

@@ -90,6 +90,10 @@ spec:
metadata:
labels:
{{- include "kubevela.selectorLabels" . | nindent 8 }}
annotations:
prometheus.io/path: /metrics
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
@@ -130,6 +134,7 @@ spec:
{{ if .Values.multicluster.enabled }}
- "--enable-cluster-gateway"
{{ end }}
- "--application-re-sync-period={{ .Values.controllerArgs.reSyncPeriod }}"
image: {{ .Values.imageRegistry }}{{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ quote .Values.image.pullPolicy }}
resources:

View File

@@ -0,0 +1,40 @@
apiVersion: "v1"
kind: "ConfigMap"
metadata:
name: "service-endpoints-view"
namespace: {{.Values.systemDefinitionNamespace}}
data:
template: |
import (
"vela/ql"
)
parameter: {
appName: string
appNs: string
cluster?: string
clusterNs?: string
}
resources: ql.#CollectServiceEndpoints & {
app: {
name: parameter.appName
namespace: parameter.appNs
filter: {
if parameter.cluster != _|_ {
cluster: parameter.cluster
}
if parameter.clusterNs != _|_ {
clusterNamespace: parameter.clusterNs
}
}
}
}
if resources.err == _|_ {
status: {
endpoints: resources.list
}
}
if resources.err != _|_ {
status: {
error: resources.err
}
}

View File

@@ -62,6 +62,9 @@ affinity: {}
rbac:
create: true
controllerArgs:
reSyncPeriod: 5m
admissionWebhooks:
enabled: true
failurePolicy: Fail

View File

@@ -677,113 +677,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of
AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of
the app that we need to upgrade from. We will restart
the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the
Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time
this condition transitioned from one status to
another.
format: date-time
type: string
message:
description: A Message containing details about
this condition's last transition from one status
to another, if any.
type: string
reason:
description: A Reason for this condition's last
transition from one status to another.
type: string
status:
description: Status of this condition; is it currently
True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one
of each condition type may apply to a resource
at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working
on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string
that uniquely represent the last pod template each workload
type could use different ways to identify that so we
cannot compare between resources We update this field
only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the
name of the app that we upgraded to We will restart
the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that
uniquely represent the new pod template each workload
type could use different ways to identify that so we
cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods
upgraded by the rollout controller that have a Ready
Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded
by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application
services
@@ -2324,324 +2217,6 @@ spec:
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout
the resources The controller simply replace the old resources
with the new one if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification
while the rest still have the source resource This is
designed for the operators to manually rollout Default
is the the number of batches which will rollout all
the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout
process to automatically check certain metrics before
complete the process
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an
object instead of an entire object, this string
should contain a valid JSON/Go field access
statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to
a container within a pod, this would take
on a value like: "spec.containers{name}" (where
"name" refers to the name of the container
that triggered the event) or if no container
name is specified "spec.containers[2]" (container
with index 2 in this pod). This syntax is
chosen only to have some well-defined way
of referencing a part of an object. TODO:
this design is not final and this field is
subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which
this reference is made, if any. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its
size has to be exactly the same as the NumBatches (if
set) The total number cannot exceed the targetSize or
the size of the source resource We will IGNORE the last
batch's replica field if it's a percentage since round
errors can lead to inaccurate sum We highly recommend
to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the
each batch rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for
the batch rollout to interact with an external
process
items:
description: RolloutWebhook holds the reference
to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the
expected http status code that we will accept
as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for
this webhook
type: object
method:
description: Method the HTTP call method,
default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the
batch rollout process to automatically check certain
metrics before moving to the next batch
items:
description: CanaryMetric holds the reference
to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows
size
type: string
metricsRange:
description: Range value accepted for this
metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric
template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece
of an object instead of an entire object,
this string should contain a valid JSON/Go
field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference
is to a container within a pod, this
would take on a value like: "spec.containers{name}"
(where "name" refers to the name of
the container that triggered the event)
or if no container name is specified
"spec.containers[2]" (container with
index 2 in this pod). This syntax is
chosen only to have some well-defined
way of referencing a part of an object.
TODO: this design is not final and this
field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More
info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion
to which this reference is made, if
any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between
instances upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number
of pods that is unavailable during the upgrade.
We will mark the batch as ready as long as there
are less or equal number of pods unavailable than
this number. default = 0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it
is mutually exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to
upgrade in this batch it can be an absolute number
(ex: 5) or a percentage of total pods we will
ignore the percentage of the last batch to just
fill the gap it is mutually exclusive with the
PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the
rollout plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout
to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this
webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default
is the same as the size of the source resource.
format: int32
type: integer
type: object
workflow:
description: 'Workflow defines how to customize the control
logic. If workflow is specified, Vela won''t apply any resource,
@@ -2937,113 +2512,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of
AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of
the app that we need to upgrade from. We will restart
the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the
Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time
this condition transitioned from one status to
another.
format: date-time
type: string
message:
description: A Message containing details about
this condition's last transition from one status
to another, if any.
type: string
reason:
description: A Reason for this condition's last
transition from one status to another.
type: string
status:
description: Status of this condition; is it currently
True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one
of each condition type may apply to a resource
at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working
on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string
that uniquely represent the last pod template each workload
type could use different ways to identify that so we
cannot compare between resources We update this field
only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the
name of the app that we upgraded to We will restart
the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that
uniquely represent the new pod template each workload
type could use different ways to identify that so we
cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods
upgraded by the rollout controller that have a Ready
Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded
by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application
services

View File

@@ -485,82 +485,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that we need to upgrade from. We will restart the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from one status to another.
type: string
status:
description: Status of this condition; is it currently True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely represent the last pod template each workload type could use different ways to identify that so we cannot compare between resources We update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the app that we upgraded to We will restart the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent the new pod template each workload type could use different ways to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application services
items:
@@ -876,234 +800,6 @@ spec:
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources The controller simply replace the old resources with the new one if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition (included) will have the target resource specification while the rest still have the source resource This is designed for the operators to manually rollout Default is the the number of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has to be exactly the same as the NumBatches (if set) The total number cannot exceed the targetSize or the size of the source resource We will IGNORE the last batch's replica field if it's a percentage since round errors can lead to inaccurate sum We highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout process to automatically check certain metrics before moving to the next batch
items:
description: CanaryMetric holds the reference to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of pods that is unavailable during the upgrade. We will mark the batch as ready as long as there are less or equal number of pods unavailable than this number. default = 0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade in this batch it can be an absolute number (ex: 5) or a percentage of total pods we will ignore the percentage of the last batch to just fill the gap it is mutually exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the same as the size of the source resource.
format: int32
type: integer
type: object
workflow:
description: 'Workflow defines how to customize the control logic. If workflow is specified, Vela won''t apply any resource, but provide rendered output in AppRevision. Workflow steps are executed in array order, and each step: - will have a context in annotation. - should mark "finish" phase in status.conditions.'
properties:
@@ -1311,82 +1007,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that we need to upgrade from. We will restart the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from one status to another.
type: string
status:
description: Status of this condition; is it currently True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely represent the last pod template each workload type could use different ways to identify that so we cannot compare between resources We update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the app that we upgraded to We will restart the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent the new pod template each workload type could use different ways to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application services
items:

View File

@@ -32,21 +32,30 @@ spec:
kind: "Ingress"
metadata: {
name: context.name
annotations: "kubernetes.io/ingress.class": parameter.class
annotations: {
if !parameter.classInSpec {
"kubernetes.io/ingress.class": parameter.class
}
}
}
spec: {
if parameter.classInSpec {
ingressClassName: parameter.class
}
rules: [{
host: parameter.domain
http: paths: [
for k, v in parameter.http {
path: k
pathType: "ImplementationSpecific"
backend: service: {
name: context.name
port: number: v
}
},
]
}]
}
spec: rules: [{
host: parameter.domain
http: paths: [
for k, v in parameter.http {
path: k
pathType: "ImplementationSpecific"
backend: service: {
name: context.name
port: number: v
}
},
]
}]
}
parameter: {
// +usage=Specify the domain you want to expose
@@ -57,6 +66,9 @@ spec:
// +usage=Specify the class of ingress to use
class: *"nginx" | string
// +usage=Set ingress class in '.spec.ingressClassName' instead of 'kubernetes.io/ingress.class' annotation.
classInSpec: *false | bool
}
status:
customStatus: |-

View File

@@ -17,6 +17,27 @@ spec:
)
parameter: {
lark?: {
// +usage=Specify the the lark url, you can either sepcify it in value or use secretRef
url: {
value: string
} | {
secretRef: {
// +usage=name is the name of the secret
name: string
// +usage=key is the key in the secret
key: string
}
}
// +useage=Specify the message that you want to sent
message: {
// +usage=msg_type can be text, post, image, interactive, share_chat, share_user, audio, media, file, sticker
msg_type: string
// +usage=content should be json encode string
content: string
}
}
dingding?: {
// +usage=Specify the the dingding url, you can either sepcify it in value or use secretRef
url: {
@@ -207,6 +228,35 @@ spec:
}
}
}
lark: op.#Steps & {
if parameter.lark != _|_ {
if parameter.lark.url.value != _|_ {
lark1: op.#Lark & {
message: parameter.lark.message
larkUrl: parameter.lark.url.value
}
}
if parameter.lark.url.secretRef != _|_ && parameter.lark.url.value == _|_ {
read: op.#Read & {
value: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: parameter.lark.url.secretRef.name
namespace: context.namespace
}
}
}
decoded: base64.Decode(null, read.value.data[parameter.lark.url.secretRef.key])
stringValue: op.#ConvertString & {bt: decoded}
lark2: op.#Lark & {
message: parameter.lark.message
larkUrl: stringValue.str
}
}
}
}
slack: op.#Steps & {
if parameter.slack != _|_ {
if parameter.slack.url.value != _|_ {

View File

@@ -109,10 +109,10 @@ spec:
}
parameter: {
// +usage=Specify the labels in the workload
labels?: {...}
labels?: [string]: string
// +usage=Specify the annotations in the workload
annotations?: {...}
annotations?: [string]: string
// +usage=Specify number of tasks to run in parallel
// +short=c

View File

@@ -11,6 +11,10 @@ spec:
schematic:
cue:
template: |
import (
"strconv"
)
mountsArray: {
pvc: *[
for v in parameter.volumeMounts.pvc {
@@ -152,6 +156,12 @@ spec:
{
containerPort: v.port
protocol: v.protocol
if v.name != _|_ {
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
}
}}]
}
@@ -262,6 +272,12 @@ spec:
for v in parameter.ports if v.expose == true {
port: v.port
targetPort: v.port
if v.name != _|_ {
name: v.name
}
if v.name == _|_ {
name: "port-" + strconv.FormatInt(v.port, 10)
}
},
]
outputs: {
@@ -280,10 +296,10 @@ spec:
}
parameter: {
// +usage=Specify the labels in the workload
labels?: {...}
labels?: [string]: string
// +usage=Specify the annotations in the workload
annotations?: {...}
annotations?: [string]: string
// +usage=Which image would you like to use for your service
// +short=i
@@ -304,6 +320,8 @@ spec:
ports?: [...{
// +usage=Number of port to expose on the pod's IP address
port: int
// +usage=Name of the port
name?: string
// +usage=Protocol for port. Must be UDP, TCP, or SCTP
protocol: *"TCP" | "UDP" | "SCTP"
// +usage=Specify if the port should be exposed
@@ -494,12 +512,7 @@ spec:
replica: strconv.FormatInt(context.output.status.readyReplicas, 10)
}
}
if context.output.status.replicas != _|_ {
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.status.replicas, 10)
}
if context.output.status.replicas == _|_ {
message: ""
}
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
healthPolicy: |-
ready: {
if context.output.status.readyReplicas == _|_ {
@@ -509,12 +522,7 @@ spec:
replica: context.output.status.readyReplicas
}
}
if context.output.status.replicas != _|_ {
isHealth: context.output.status.replicas == ready.replica
}
if context.output.status.replicas == _|_ {
isHealth: false
}
isHealth: context.output.spec.replicas == ready.replica
workload:
definition:
apiVersion: apps/v1

View File

@@ -405,12 +405,7 @@ spec:
replica: strconv.FormatInt(context.output.status.readyReplicas, 10)
}
}
if context.output.status.replicas != _|_ {
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.status.replicas, 10)
}
if context.output.status.replicas == _|_ {
message: ""
}
message: "Ready:" + ready.replica + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
healthPolicy: |-
ready: {
if context.output.status.readyReplicas == _|_ {
@@ -420,12 +415,7 @@ spec:
replica: context.output.status.readyReplicas
}
}
if context.output.status.replicas != _|_ {
isHealth: context.output.status.replicas == ready.replica
}
if context.output.status.replicas == _|_ {
isHealth: false
}
isHealth: context.output.spec.replicas == ready.replica
workload:
definition:
apiVersion: apps/v1

View File

@@ -92,6 +92,10 @@ spec:
metadata:
labels:
{{- include "kubevela.selectorLabels" . | nindent 8 }}
annotations:
prometheus.io/path: /metrics
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:

View File

@@ -30,13 +30,12 @@ import (
"strings"
"time"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/klog/v2"
"k8s.io/klog/v2/klogr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
ctrlClient "github.com/oam-dev/kubevela/pkg/client"
standardcontroller "github.com/oam-dev/kubevela/pkg/controller"
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
@@ -74,7 +73,6 @@ func main() {
var healthAddr string
var disableCaps string
var storageDriver string
var syncPeriod time.Duration
var applyOnceOnly string
var qps float64
var burst int
@@ -110,8 +108,8 @@ func main() {
"For the purpose of some production environment that workload or trait should not be affected if no spec change, available options: on, off, force.")
flag.StringVar(&disableCaps, "disable-caps", "", "To be disabled builtin capability list.")
flag.StringVar(&storageDriver, "storage-driver", "Local", "Application file save to the storage driver")
flag.DurationVar(&syncPeriod, "informer-re-sync-interval", 60*time.Minute,
"controller shared informer lister full re-sync period")
flag.DurationVar(&commonconfig.ApplicationReSyncPeriod, "application-re-sync-period", 5*time.Minute,
"Re-sync period for application to re-sync, also known as the state-keep interval.")
flag.DurationVar(&commonconfig.ReconcileTimeout, "reconcile-timeout", time.Minute*3,
"the timeout for controller reconcile")
flag.StringVar(&oam.SystemDefinitonNamespace, "system-definition-namespace", "vela-system", "define the namespace of the system-level definition")
@@ -131,6 +129,8 @@ func main() {
flag.DurationVar(&retryPeriod, "leader-election-retry-period", 2*time.Second,
"The duration the LeaderElector clients should wait between tries of actions")
flag.BoolVar(&enableClusterGateway, "enable-cluster-gateway", false, "Enable cluster-gateway to use multicluster, disabled by default.")
flag.BoolVar(&controllerArgs.EnableCompatibility, "enable-asi-compatibility", false, "enable compatibility for asi")
standardcontroller.AddOptimizeFlags()
flag.Parse()
// setup logging
@@ -205,12 +205,16 @@ func main() {
Port: webhookPort,
CertDir: certDir,
HealthProbeBindAddress: healthAddr,
SyncPeriod: &syncPeriod,
LeaderElectionResourceLock: leaderElectionResourceLock,
LeaseDuration: &leaseDuration,
RenewDeadline: &renewDeadline,
RetryPeriod: &retryPeriod,
ClientDisableCacheFor: []client.Object{&appsv1.ControllerRevision{}},
// SyncPeriod is configured with default value, aka. 10h. First, controller-runtime does not
// recommend use it as a time trigger, instead, it is expected to work for failure tolerance
// of controller-runtime. Additionally, set this value will affect not only application
// controller but also all other controllers like definition controller. Therefore, for
// functionalities like state-keep, they should be invented in other ways.
NewClient: ctrlClient.DefaultNewControllerClient,
})
if err != nil {
klog.ErrorS(err, "Unable to create a controller manager")

View File

@@ -21,7 +21,7 @@ import (
"os"
"time"
"github.com/oam-dev/kubevela/pkg/plugin/cli"
"github.com/oam-dev/kubevela/references/cli"
)
func main() {

View File

@@ -9,6 +9,7 @@ This guide helps you get started developing KubeVela.
3. ginkgo 1.14.0+ (just for [E2E test](./developer-guide.md#e2e-test))
4. golangci-lint 1.38.0+, it will install automatically if you run `make`, you can [install it manually](https://golangci-lint.run/usage/install/#local-installation) if the installation is too slow.
5. kubebuilder v3.1.0+ and you need to manually install the dependency tools for unit test.
6. [CUE binary](https://github.com/cue-lang/cue/releases) v0.3.0+
<details>
<summary>Install Kubebuilder manually</summary>

View File

@@ -21,7 +21,7 @@
| apply-once-only | string | false | For the purpose of some production environment that workload or trait should not be affected if no spec change, available options: on, off, force. |
| disable-caps | string | "" | To be disabled builtin capability list. |
| storage-driver | string | Local | Application file save to the storage driver |
| informer-re-sync-interval | time | 1h | Controller shared informer lister full re-sync period, the interval between two routinely reconciles for one CR (like Application) if no changes made to it. |
| application-re-sync-period | time | 5m | Re-sync period for application to re-sync, also known as the state-keep interval. |
| reconcile-timeout | time | 3m | The timeout for controller reconcile. |
| system-definition-namespace | string | vela-system | define the namespace of the system-level definition |
| concurrent-reconciles | int | 4 | The concurrent reconcile number of the controller. You can increase the degree of concurrency if a large number of CPU cores are provided to the controller. |

View File

@@ -504,6 +504,31 @@
}
}
},
"/api/v1/applications/payload_types": {
"get": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "list application trigger payload types",
"operationId": "ListPayloadTypes",
"responses": {
"200": {},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/applications/{name}": {
"get": {
"consumes": [
@@ -1707,6 +1732,133 @@
}
}
},
"/api/v1/applications/{name}/triggers": {
"get": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "list application triggers",
"operationId": "listApplicationTriggers",
"parameters": [
{
"type": "string",
"description": "identifier of the application ",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.ListApplicationTriggerResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
},
"post": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "create one application trigger",
"operationId": "createApplicationTrigger",
"parameters": [
{
"type": "string",
"description": "identifier of the application ",
"name": "name",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1.CreateApplicationTriggerRequest"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.ApplicationTriggerBase"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/applications/{name}/triggers/{token}": {
"delete": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "delete one application trigger",
"operationId": "deleteApplicationTrigger",
"parameters": [
{
"type": "string",
"description": "identifier of the application ",
"name": "name",
"in": "path",
"required": true
},
{
"type": "string",
"description": "identifier of the trigger",
"name": "token",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.EmptyResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/applications/{name}/workflows": {
"get": {
"consumes": [
@@ -2738,9 +2890,9 @@
"parameters": [
{
"enum": [
"workflowstep",
"component",
"trait"
"trait",
"workflowstep"
],
"type": "string",
"description": "query the definition type",
@@ -2817,7 +2969,7 @@
}
}
},
"/api/v1/enabled-addon": {
"/api/v1/enabled_addon": {
"get": {
"consumes": [
"application/xml",
@@ -3302,6 +3454,52 @@
}
}
},
"/api/v1/webhook/{token}": {
"post": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"webhook"
],
"summary": "handle application webhook request",
"operationId": "handleApplicationWebhook",
"parameters": [
{
"type": "string",
"description": "identifier of the application ",
"name": "name",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1.HandleApplicationTriggerWebhookRequest"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.ApplicationDeployResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/v1/namespaces/{namespace}/applications/{appname}": {
"get": {
"consumes": [
@@ -3424,6 +3622,8 @@
}
},
"definitions": {
"*v1.ApplicationTriggerBase": {},
"*v1.EmptyResponse": {},
"addon.Dependency": {
"properties": {
"name": {
@@ -3604,11 +3804,11 @@
},
"common.AppRolloutStatus": {
"required": [
"batchRollingState",
"currentBatch",
"upgradedReadyReplicas",
"rollingState",
"upgradedReadyReplicas",
"currentBatch",
"upgradedReplicas",
"batchRollingState",
"lastTargetAppRevision"
],
"properties": {
@@ -4204,6 +4404,9 @@
"applyAppConfig": {
"type": "string"
},
"codeInfo": {
"$ref": "#/definitions/model.CodeInfo"
},
"createTime": {
"type": "string",
"format": "date-time"
@@ -4214,6 +4417,9 @@
"envName": {
"type": "string"
},
"imageInfo": {
"$ref": "#/definitions/model.ImageInfo"
},
"note": {
"type": "string"
},
@@ -4290,8 +4496,8 @@
},
"model.Cluster": {
"required": [
"updateTime",
"createTime",
"updateTime",
"name",
"alias",
"description",
@@ -4355,6 +4561,86 @@
}
}
},
"model.CodeInfo": {
"properties": {
"branch": {
"type": "string"
},
"commit": {
"type": "string"
},
"user": {
"type": "string"
}
}
},
"model.ImageInfo": {
"required": [
"type"
],
"properties": {
"repository": {
"$ref": "#/definitions/model.ImageRepository"
},
"resource": {
"$ref": "#/definitions/model.ImageResource"
},
"type": {
"type": "string"
}
}
},
"model.ImageRepository": {
"required": [
"name",
"namespace",
"fullName",
"type"
],
"properties": {
"createTime": {
"type": "string",
"format": "date-time"
},
"fullName": {
"type": "string"
},
"name": {
"type": "string"
},
"namespace": {
"type": "string"
},
"region": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"model.ImageResource": {
"required": [
"digest",
"tag",
"url"
],
"properties": {
"createTime": {
"type": "string",
"format": "date-time"
},
"digest": {
"type": "string"
},
"tag": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"model.JSONStruct": {
"type": "object"
},
@@ -4601,6 +4887,20 @@
}
}
},
"v1.AddonBaseStatus": {
"required": [
"name",
"phase"
],
"properties": {
"name": {
"type": "string"
},
"phase": {
"type": "string"
}
}
},
"v1.AddonDefinition": {
"properties": {
"description": {
@@ -4614,6 +4914,20 @@
}
}
},
"v1.AddonInfo": {
"required": [
"Meta",
"registryName"
],
"properties": {
"Meta": {
"$ref": "#/definitions/addon.Meta"
},
"registryName": {
"type": "string"
}
}
},
"v1.AddonRegistry": {
"required": [
"name"
@@ -4716,9 +5030,15 @@
"force"
],
"properties": {
"codeInfo": {
"$ref": "#/definitions/model.CodeInfo"
},
"force": {
"type": "boolean"
},
"imageInfo": {
"$ref": "#/definitions/model.ImageInfo"
},
"note": {
"type": "string"
},
@@ -4732,16 +5052,17 @@
},
"v1.ApplicationDeployResponse": {
"required": [
"createTime",
"version",
"status",
"reason",
"deployUser",
"note",
"envName",
"triggerType"
"triggerType",
"version",
"createTime"
],
"properties": {
"codeInfo": {
"$ref": "#/definitions/model.CodeInfo"
},
"createTime": {
"type": "string",
"format": "date-time"
@@ -4752,6 +5073,9 @@
"envName": {
"type": "string"
},
"imageInfo": {
"$ref": "#/definitions/model.ImageInfo"
},
"note": {
"type": "string"
},
@@ -4829,13 +5153,14 @@
"createTime",
"version",
"status",
"reason",
"deployUser",
"note",
"envName",
"triggerType"
],
"properties": {
"codeInfo": {
"$ref": "#/definitions/model.CodeInfo"
},
"createTime": {
"type": "string",
"format": "date-time"
@@ -4846,6 +5171,9 @@
"envName": {
"type": "string"
},
"imageInfo": {
"$ref": "#/definitions/model.ImageInfo"
},
"note": {
"type": "string"
},
@@ -4991,6 +5319,51 @@
}
}
},
"v1.ApplicationTriggerBase": {
"required": [
"name",
"workflowName",
"type",
"payloadType",
"token",
"createTime",
"updateTime"
],
"properties": {
"alias": {
"type": "string"
},
"componentName": {
"type": "string"
},
"createTime": {
"type": "string",
"format": "date-time"
},
"description": {
"type": "string"
},
"name": {
"type": "string"
},
"payloadType": {
"type": "string"
},
"token": {
"type": "string"
},
"type": {
"type": "string"
},
"updateTime": {
"type": "string",
"format": "date-time"
},
"workflowName": {
"type": "string"
}
}
},
"v1.ClusterBase": {
"required": [
"name",
@@ -5339,6 +5712,37 @@
}
}
},
"v1.CreateApplicationTriggerRequest": {
"required": [
"name",
"workflowName",
"type",
"payloadType"
],
"properties": {
"alias": {
"type": "string"
},
"componentName": {
"type": "string"
},
"description": {
"type": "string"
},
"name": {
"type": "string"
},
"payloadType": {
"type": "string"
},
"type": {
"type": "string"
},
"workflowName": {
"type": "string"
}
}
},
"v1.CreateCloudClusterRequest": {
"required": [
"accessKeyID",
@@ -5637,10 +6041,10 @@
"v1.DetailAddonResponse": {
"required": [
"name",
"description",
"invisible",
"version",
"description",
"icon",
"invisible",
"schema",
"uiSchema",
"definitions"
@@ -5682,6 +6086,9 @@
"type": "string"
}
},
"registryName": {
"type": "string"
},
"schema": {
"type": "string"
},
@@ -5707,13 +6114,13 @@
},
"v1.DetailApplicationResponse": {
"required": [
"name",
"alias",
"project",
"description",
"createTime",
"updateTime",
"icon",
"name",
"policies",
"envBindings",
"status",
@@ -5775,20 +6182,20 @@
},
"v1.DetailClusterResponse": {
"required": [
"apiServerURL",
"icon",
"createTime",
"status",
"provider",
"reason",
"alias",
"description",
"labels",
"dashboardURL",
"kubeConfig",
"updateTime",
"createTime",
"name",
"kubeConfigSecret",
"alias",
"icon",
"reason",
"apiServerURL",
"dashboardURL",
"name",
"description",
"labels",
"resourceInfo"
],
"properties": {
@@ -5846,13 +6253,13 @@
},
"v1.DetailComponentResponse": {
"required": [
"type",
"createTime",
"creator",
"updateTime",
"name",
"alias",
"appPrimaryKey"
"updateTime",
"appPrimaryKey",
"type"
],
"properties": {
"alias": {
@@ -5983,16 +6390,16 @@
},
"v1.DetailRevisionResponse": {
"required": [
"reason",
"status",
"workflowName",
"triggerType",
"createTime",
"version",
"deployUser",
"note",
"workflowName",
"updateTime",
"version",
"reason",
"triggerType",
"envName",
"createTime",
"updateTime",
"appPrimaryKey"
],
"properties": {
@@ -6002,6 +6409,9 @@
"applyAppConfig": {
"type": "string"
},
"codeInfo": {
"$ref": "#/definitions/model.CodeInfo"
},
"createTime": {
"type": "string",
"format": "date-time"
@@ -6012,6 +6422,9 @@
"envName": {
"type": "string"
},
"imageInfo": {
"$ref": "#/definitions/model.ImageInfo"
},
"note": {
"type": "string"
},
@@ -6041,9 +6454,9 @@
},
"v1.DetailTargetResponse": {
"required": [
"name",
"createTime",
"updateTime"
"updateTime",
"name"
],
"properties": {
"alias": {
@@ -6137,14 +6550,14 @@
},
"v1.DetailWorkflowResponse": {
"required": [
"alias",
"description",
"default",
"updateTime",
"createTime",
"name",
"description",
"enable",
"default",
"alias",
"envName",
"createTime"
"updateTime"
],
"properties": {
"alias": {
@@ -6323,6 +6736,19 @@
}
}
},
"v1.HandleApplicationTriggerWebhookRequest": {
"properties": {
"codeInfo": {
"$ref": "#/definitions/model.CodeInfo"
},
"upgrade": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/model.JSONStruct"
}
}
}
},
"v1.ListAddonRegistryResponse": {
"required": [
"registries"
@@ -6344,7 +6770,7 @@
"addons": {
"type": "array",
"items": {
"$ref": "#/definitions/addon.Meta"
"$ref": "#/definitions/v1.AddonInfo"
}
},
"message": {
@@ -6391,6 +6817,19 @@
}
}
},
"v1.ListApplicationTriggerResponse": {
"required": [
"triggers"
],
"properties": {
"triggers": {
"type": "array",
"items": {
"$ref": "#/definitions/v1.ApplicationTriggerBase"
}
}
}
},
"v1.ListCloudClusterCreationResponse": {
"required": [
"creations"

View File

@@ -14,8 +14,12 @@ spec:
ports:
- port: 8000
- port: 8001
name: exposeport1
protocol: UDP
expose: true
expose: true
- port: 8002
protocol: UDP
expose: true
volumeMounts:
pvc:
- name: my-mount

View File

@@ -0,0 +1,74 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: example-app
namespace: default
spec:
components:
- name: podinfo
type: webservice
properties:
image: stefanprodan/podinfo
traits:
- type: scaler
properties:
replicas: 1
- name: hello-world
type: webservice
properties:
image: crccheck/hello-world
traits:
- type: scaler
properties:
replicas: 1
- name: nginx
type: worker
properties:
image: nginx
traits:
- type: scaler
properties:
replicas: 1
policies:
- name: example-multi-env-policy
type: env-binding
properties:
envs:
- name: test
placement:
clusterSelector:
name: local
namespaceSelector:
name: test
patch:
components:
- name: podinfo # patch to component named podinfo, no type check
traits:
- type: scaler
properties:
replicas: 2
- name: staging
placement:
clusterSelector:
name: remote
patch:
components: # patch to all webservice components
- type: webservice
traits:
- type: scaler
properties:
replicas: 3
- name: prod
placement:
clusterSelector:
name: remote
namespaceSelector:
name: prod
patch:
components: # patch to all components
- traits:
- type: scaler
properties:
replicas: 3

View File

@@ -0,0 +1,14 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: app-aws-s3
spec:
components:
- name: sample-s3
type: aws-s3
properties:
bucket: vela-website-202110191745
acl: private
writeConnectionSecretToRef:
name: s3-conn

View File

@@ -29,6 +29,12 @@ spec:
msgtype: text
text:
content: Hello KubeVela
lark:
url:
value: <lark-url>
message:
msg_type: "text"
content: "{\"text\":\" Hello KubeVela\"}"
slack:
url:
# use url in secret

View File

@@ -47,13 +47,13 @@ var _ = Describe("Addon Test", func() {
It("Enable addon test-addon", func() {
output, err := e2e.Exec("vela addon enable test-addon")
Expect(err).NotTo(HaveOccurred())
Expect(output).To(ContainSubstring("Successfully enable addon"))
Expect(output).To(ContainSubstring("enabled Successfully."))
})
It("Upgrade addon test-addon", func() {
output, err := e2e.Exec("vela addon upgrade test-addon")
Expect(err).NotTo(HaveOccurred())
Expect(output).To(ContainSubstring("Successfully enable addon"))
Expect(output).To(ContainSubstring("enabled Successfully."))
})
It("Disable addon test-addon", func() {
@@ -68,7 +68,7 @@ var _ = Describe("Addon Test", func() {
It("Enable addon with input", func() {
output, err := e2e.LongTimeExec("vela addon enable test-addon example=redis", 300*time.Second)
Expect(err).NotTo(HaveOccurred())
Expect(output).To(ContainSubstring("Successfully enable addon"))
Expect(output).To(ContainSubstring("enabled Successfully."))
})
It("Disable addon test-addon", func() {

View File

@@ -119,25 +119,25 @@ var _ = Describe("Test Kubectl Plugin", func() {
Context("Test kubectl vela show", func() {
It("Test show componentDefinition reference", func() {
cdName := "test-show-task"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", cdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", cdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring(showCdResult))
})
It("Test show traitDefinition reference", func() {
tdName := "test-sidecar"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring(showTdResult))
})
It("Test show componentDefinition use Helm Charts as Workload", func() {
cdName := "test-webapp-chart"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", cdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", cdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring("Properties"))
})
It("Test show componentDefinition def with raw Kube mode", func() {
cdName := "kube-worker"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", cdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", cdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring("image"))
Expect(output).Should(ContainSubstring("The value will be applied to fields: [spec.template.spec.containers[0].image]."))
@@ -146,26 +146,26 @@ var _ = Describe("Test Kubectl Plugin", func() {
})
It("Test show traitDefinition def with raw Kube mode", func() {
tdName := "service-kube"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring("targetPort"))
Expect(output).Should(ContainSubstring("target port num for service provider."))
})
It("Test show traitDefinition def with cue single map parameter", func() {
tdName := "annotations"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring("map[string]string"))
})
It("Test show webservice def with cue ignore annotation ", func() {
tdName := "webservice"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).ShouldNot(ContainSubstring("addRevisionLabel"))
})
It("Test show webservice def with cue ignore annotation ", func() {
tdName := "mywebservice"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName))
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName))
Expect(err).NotTo(HaveOccurred())
Expect(output).ShouldNot(ContainSubstring("addRevisionLabel"))
Expect(output).ShouldNot(ContainSubstring("mySecretKey"))

1
go.mod
View File

@@ -70,7 +70,6 @@ require (
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gotest.tools v2.2.0+incompatible
helm.sh/helm/v3 v3.6.1
istio.io/api v0.0.0-20210128181506-0c4b8e54850f
istio.io/client-go v0.0.0-20210128182905-ee2edd059e02
k8s.io/api v0.22.1
k8s.io/apiextensions-apiserver v0.22.1

31
hack/docgen/REDAME.md Normal file
View File

@@ -0,0 +1,31 @@
# KubeVela.io CLI Reference Doc
1. step up these two projects in the same folder.
```shell
$ tree -L 1
.
├── kubevela
└── kubevela.io
```
2. Run generate command in kubevela root dir.
```shell
cd kubevela/
go run ./hack/docgen/gen.go
```
3. Update more docs such as i18n zh
```shell
$ go run ./hack/docgen/gen.go ../kubevela.io/i18n/zh/docusaurus-plugin-content-docs/current/cli
scanning rootPath of CLI docs for replace: ../kubevela.io/i18n/zh/docusaurus-plugin-content-docs/current/cli
```
4. Then you can check the difference in kubevela.io.
```shell
cd ../kubevela.io
git status
```

View File

@@ -17,16 +17,156 @@ limitations under the License.
package main
import (
"fmt"
"io"
"io/fs"
"io/ioutil"
"log"
"os"
"path/filepath"
"sort"
"strings"
"github.com/spf13/cobra"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/references/cli"
"github.com/spf13/cobra/doc"
)
// PrintCLIByTag print custom defined index
func PrintCLIByTag(cmd *cobra.Command, all []*cobra.Command, tag string) string {
var result string
pl := cli.PrintList{}
for _, c := range all {
if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
if val, ok := c.Annotations[types.TagCommandType]; !ok || val != tag {
continue
}
cname := cmd.Name() + " " + c.Name()
link := cname
link = strings.Replace(link, " ", "_", -1)
pl = append(pl, cli.Printable{Order: c.Annotations[types.TagCommandOrder], Long: fmt.Sprintf("* [%s](%s)\t - %s\n", cname, link, c.Long)})
}
sort.Sort(pl)
for _, v := range pl {
result += v.Long
}
result += "\n"
return result
}
// GenMarkdownTreeForIndex will generate the markdown doc for vela index
func GenMarkdownTreeForIndex(cmd *cobra.Command, dir string) error {
basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".md"
filename := filepath.Join(dir, basename)
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
if _, err = io.WriteString(f, "---\ntitle: CLI Commands\n---\n\n\n"); err != nil {
return err
}
for _, tp := range []string{types.TypeStart, types.TypeApp, types.TypeCD, types.TypeExtension, types.TypeSystem} {
// write header of type
_, err = io.WriteString(f, "## "+tp+"\n\n")
if err != nil {
return err
}
str := PrintCLIByTag(cmd, cmd.Commands(), tp)
// write header of type
_, err = io.WriteString(f, str)
if err != nil {
return err
}
}
_, err = io.WriteString(f, "###### Auto generated by [script in KubeVela](https://github.com/oam-dev/kubevela/tree/master/hack/docgen).")
if err != nil {
return err
}
return nil
}
func main() {
rootPath := "../kubevela.io/docs/cli/"
if len(os.Args) > 1 {
rootPath = os.Args[1]
}
fmt.Println("scanning rootPath of CLI docs for replace: ", rootPath)
vela := cli.NewCommand()
err := doc.GenMarkdownTree(vela, "./docs/en/cli/")
err := doc.GenMarkdownTree(vela, rootPath)
if err != nil {
log.Fatal(err)
}
err = GenMarkdownTreeForIndex(vela, rootPath)
if err != nil {
log.Fatal("generate docs for vela index fail", err)
}
err = filepath.Walk(rootPath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
lines := strings.Split(string(data), "\n")
if len(lines) < 1 {
return nil
}
// check first line to make sure it's autogenerated docs
firstL := lines[0]
if !strings.HasPrefix(firstL, "## vela") {
return nil
}
// find the last line and add some link.
var lastIdx int
for idx := len(lines) - 1; idx >= 0; idx-- {
if strings.Contains(lines[idx], "Auto generated") {
lastIdx = idx
break
}
}
if lastIdx == 0 {
return nil
}
lastL := lines[lastIdx]
lines[lastIdx] = "#### Go Back to [CLI Commands](vela) Homepage.\n\n\n" + lastL + ", refer to [script in KubeVela](https://github.com/oam-dev/kubevela/tree/master/hack/docgen)."
// update the title format
title := strings.TrimPrefix(firstL, "## ")
lines[0] = "---"
newlines := []string{"---", "title: " + title}
for idx, line := range lines {
if strings.Contains(line, "[vela](vela.md)") {
lines[idx] = ""
continue
}
if strings.Contains(line, ".md") && strings.Contains(line, "](") {
lines[idx] = strings.Replace(line, ".md", "", -1)
}
}
newlines = append(newlines, lines...)
newcontent := strings.Join(newlines, "\n")
return ioutil.WriteFile(path, []byte(newcontent), info.Mode())
})
if err != nil {
log.Fatal(err)
}

View File

@@ -21,13 +21,28 @@ import (
"fmt"
"os"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/references/plugins"
)
func main() {
ref := &plugins.MarkdownReference{}
ctx := context.Background()
if err := ref.GenerateReferenceDocs(ctx, plugins.BaseRefPath); err != nil {
path := plugins.BaseRefPath
if len(os.Args) == 2 {
ref.DefinitionName = os.Args[1]
path = plugins.KubeVelaIOTerraformPath
}
c, err := common.InitBaseRestConfig()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if err := ref.GenerateReferenceDocs(ctx, c, path, types.DefaultKubeVelaNS); err != nil {
fmt.Println(err)
os.Exit(1)
}

View File

@@ -677,113 +677,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of
AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of
the app that we need to upgrade from. We will restart
the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the
Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time
this condition transitioned from one status to
another.
format: date-time
type: string
message:
description: A Message containing details about
this condition's last transition from one status
to another, if any.
type: string
reason:
description: A Reason for this condition's last
transition from one status to another.
type: string
status:
description: Status of this condition; is it currently
True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one
of each condition type may apply to a resource
at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working
on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string
that uniquely represent the last pod template each workload
type could use different ways to identify that so we
cannot compare between resources We update this field
only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the
name of the app that we upgraded to We will restart
the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that
uniquely represent the new pod template each workload
type could use different ways to identify that so we
cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods
upgraded by the rollout controller that have a Ready
Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded
by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application
services
@@ -2324,324 +2217,6 @@ spec:
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout
the resources The controller simply replace the old resources
with the new one if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification
while the rest still have the source resource This is
designed for the operators to manually rollout Default
is the the number of batches which will rollout all
the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout
process to automatically check certain metrics before
complete the process
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an
object instead of an entire object, this string
should contain a valid JSON/Go field access
statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to
a container within a pod, this would take
on a value like: "spec.containers{name}" (where
"name" refers to the name of the container
that triggered the event) or if no container
name is specified "spec.containers[2]" (container
with index 2 in this pod). This syntax is
chosen only to have some well-defined way
of referencing a part of an object. TODO:
this design is not final and this field is
subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which
this reference is made, if any. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its
size has to be exactly the same as the NumBatches (if
set) The total number cannot exceed the targetSize or
the size of the source resource We will IGNORE the last
batch's replica field if it's a percentage since round
errors can lead to inaccurate sum We highly recommend
to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the
each batch rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for
the batch rollout to interact with an external
process
items:
description: RolloutWebhook holds the reference
to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the
expected http status code that we will accept
as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for
this webhook
type: object
method:
description: Method the HTTP call method,
default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the
batch rollout process to automatically check certain
metrics before moving to the next batch
items:
description: CanaryMetric holds the reference
to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows
size
type: string
metricsRange:
description: Range value accepted for this
metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric
template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece
of an object instead of an entire object,
this string should contain a valid JSON/Go
field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference
is to a container within a pod, this
would take on a value like: "spec.containers{name}"
(where "name" refers to the name of
the container that triggered the event)
or if no container name is specified
"spec.containers[2]" (container with
index 2 in this pod). This syntax is
chosen only to have some well-defined
way of referencing a part of an object.
TODO: this design is not final and this
field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More
info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion
to which this reference is made, if
any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between
instances upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number
of pods that is unavailable during the upgrade.
We will mark the batch as ready as long as there
are less or equal number of pods unavailable than
this number. default = 0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it
is mutually exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to
upgrade in this batch it can be an absolute number
(ex: 5) or a percentage of total pods we will
ignore the percentage of the last batch to just
fill the gap it is mutually exclusive with the
PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the
rollout plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout
to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this
webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default
is the same as the size of the source resource.
format: int32
type: integer
type: object
workflow:
description: 'Workflow defines how to customize the control
logic. If workflow is specified, Vela won''t apply any resource,
@@ -2937,113 +2512,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of
AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of
the app that we need to upgrade from. We will restart
the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the
Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time
this condition transitioned from one status to
another.
format: date-time
type: string
message:
description: A Message containing details about
this condition's last transition from one status
to another, if any.
type: string
reason:
description: A Reason for this condition's last
transition from one status to another.
type: string
status:
description: Status of this condition; is it currently
True, False, or Unknown?
type: string
type:
description: Type of this condition. At most one
of each condition type may apply to a resource
at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working
on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string
that uniquely represent the last pod template each workload
type could use different ways to identify that so we
cannot compare between resources We update this field
only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the
name of the app that we upgraded to We will restart
the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target
resources. This is determined once the initial spec
verification and does not change until the rollout is
restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that
uniquely represent the new pod template each workload
type could use different ways to identify that so we
cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods
upgraded by the rollout controller that have a Ready
Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded
by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application
services

View File

@@ -617,107 +617,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app
that we need to upgrade from. We will restart the rollout if
this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status
is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition
from one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each
condition type may apply to a resource at any point in
time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked
it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that
uniquely represent the last pod template each workload type
could use different ways to identify that so we cannot compare
between resources We update this field only after a successful
rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of
the app that we upgraded to We will restart the rollout if this
is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does
not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does
not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely
represent the new pod template each workload type could use
different ways to identify that so we cannot compare between
resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded
by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by
the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application services
items:
@@ -1135,303 +1034,6 @@ spec:
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
The controller simply replace the old resources with the new one
if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification while
the rest still have the source resource This is designed for
the operators to manually rollout Default is the the number
of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process
to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used
for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a
valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container
within a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container
that triggered the event) or if no container name
is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to
have some well-defined way of referencing a part of
an object. TODO: this design is not final and this
field is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this
reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has
to be exactly the same as the NumBatches (if set) The total
number cannot exceed the targetSize or the size of the source
resource We will IGNORE the last batch's replica field if it's
a percentage since round errors can lead to inaccurate sum We
highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch
rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch
rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout
process to automatically check certain metrics before
moving to the next batch
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object
instead of an entire object, this string should
contain a valid JSON/Go field access statement,
such as desiredState.manifest.containers[2].
For example, if the object reference is to a
container within a pod, this would take on a
value like: "spec.containers{name}" (where "name"
refers to the name of the container that triggered
the event) or if no container name is specified
"spec.containers[2]" (container with index 2
in this pod). This syntax is chosen only to
have some well-defined way of referencing a
part of an object. TODO: this design is not
final and this field is subject to change in
the future.'
type: string
kind:
description: 'Kind of the referent. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which
this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances
upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of
pods that is unavailable during the upgrade. We will mark
the batch as ready as long as there are less or equal
number of pods unavailable than this number. default =
0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually
exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade
in this batch it can be an absolute number (ex: 5) or
a percentage of total pods we will ignore the percentage
of the last batch to just fill the gap it is mutually
exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout
plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to
interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http
status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the
same as the size of the source resource.
format: int32
type: integer
type: object
workflow:
description: 'Workflow defines how to customize the control logic.
If workflow is specified, Vela won''t apply any resource, but provide
@@ -1710,107 +1312,6 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
rollout:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app
that we need to upgrade from. We will restart the rollout if
this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status
is rolling
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition
from one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each
condition type may apply to a resource at any point in
time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked
it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that
uniquely represent the last pod template each workload type
could use different ways to identify that so we cannot compare
between resources We update this field only after a successful
rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of
the app that we upgraded to We will restart the rollout if this
is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does
not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does
not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely
represent the new pod template each workload type could use
different ways to identify that so we cannot compare between
resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded
by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by
the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
services:
description: Services record the status of the application services
items:

View File

@@ -42,6 +42,7 @@ import (
k8syaml "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
types2 "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/retry"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
@@ -109,6 +110,8 @@ const (
ObservabilityAddonEndpointComponent = "grafana"
// ObservabilityAddonDomainArg is the domain argument name of the observability addon
ObservabilityAddonDomainArg = "domain"
// LocalAddonRegistryName is the addon-registry name for those installed by local dir
LocalAddonRegistryName = "local"
)
// ObservabilityEnvironment contains the Observability addon's domain for each cluster
@@ -464,6 +467,10 @@ func RenderApp(ctx context.Context, addon *InstallPackage, config *rest.Config,
}
app.Labels = util.MergeMapOverrideWithDst(app.Labels, map[string]string{oam.LabelAddonName: addon.Name})
for _, namespace := range addon.NeedNamespace {
// vela-system must exist before rendering vela addon
if namespace == types.DefaultKubeVelaNS {
continue
}
comp := common2.ApplicationComponent{
Type: "raw",
Name: fmt.Sprintf("%s-namespace", namespace),
@@ -505,20 +512,34 @@ func RenderApp(ctx context.Context, addon *InstallPackage, config *rest.Config,
Type: "deploy2runtime",
})
case addon.Name == ObservabilityAddon:
policies, err := preparePolicies4Observability(ctx, k8sClient)
clusters, err := allocateDomainForAddon(ctx, k8sClient)
if err != nil {
return nil, err
}
policies, err := preparePolicies4Observability(clusters)
if err != nil {
return nil, errors.Wrap(err, "fail to render the policies for Add-on Observability")
}
app.Spec.Policies = policies
app.Spec.Workflow = &v1beta1.Workflow{
Steps: []v1beta1.WorkflowStep{{
Name: "deploy-control-plane",
Type: "apply-application-in-parallel",
}},
if len(clusters) > 0 {
app.Spec.Workflow = &v1beta1.Workflow{
Steps: []v1beta1.WorkflowStep{{
Name: "deploy-control-plane",
Type: "apply-application-in-parallel",
}},
}
} else {
app.Spec.Workflow = &v1beta1.Workflow{
Steps: []v1beta1.WorkflowStep{{
Name: "deploy-control-plane",
Type: "apply-application",
}},
}
}
workflowSteps, err := prepareWorkflow4Observability(ctx, k8sClient)
workflowSteps, err := prepareWorkflow4Observability(clusters)
if err != nil {
return nil, errors.Wrap(err, "fail to prepare the workflow for Add-on Observability")
}
@@ -625,12 +646,10 @@ func allocateDomainForAddon(ctx context.Context, k8sClient client.Client) ([]Obs
return envs, nil
}
func preparePolicies4Observability(ctx context.Context, k8sClient client.Client) ([]v1beta1.AppPolicy, error) {
clusters, err := allocateDomainForAddon(ctx, k8sClient)
if err != nil {
return nil, err
func preparePolicies4Observability(clusters []ObservabilityEnvironment) ([]v1beta1.AppPolicy, error) {
if clusters == nil {
return nil, nil
}
envProperties, err := render(clusters, ObservabilityEnvBindingEnvTmpl)
if err != nil {
return nil, err
@@ -656,12 +675,7 @@ func preparePolicies4Observability(ctx context.Context, k8sClient client.Client)
return policies, nil
}
func prepareWorkflow4Observability(ctx context.Context, k8sClient client.Client) ([]v1beta1.WorkflowStep, error) {
clusters, err := allocateDomainForAddon(ctx, k8sClient)
if err != nil {
return nil, err
}
func prepareWorkflow4Observability(clusters []ObservabilityEnvironment) ([]v1beta1.WorkflowStep, error) {
envBindingWorkflow, err := render(clusters, ObservabilityWorkflow4EnvBindingTmpl)
if err != nil {
return nil, err
@@ -865,7 +879,7 @@ func (h *Installer) enableAddon(addon *InstallPackage) error {
}
// we shouldn't put continue func into dispatchAddonResource, because the re-apply app maybe already update app and
// the suspend will set with false automatically
if err := h.continueIfSuspend(); err != nil {
if err := h.continueOrRestartWorkflow(); err != nil {
return err
}
return nil
@@ -943,6 +957,8 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
}
app.Name = appName
app.SetLabels(util.MergeMapOverrideWithDst(app.GetLabels(), map[string]string{oam.LabelAddonRegistry: h.r.Name}))
defs, err := RenderDefinitions(h.addon, h.config)
if err != nil {
return errors.Wrap(err, "render addon definitions fail")
@@ -986,17 +1002,39 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
return nil
}
func (h *Installer) continueIfSuspend() error {
// this func will handle such two case
// 1. if last apply failed an workflow have suspend, this func will continue the workflow
// 2. restart the workflow, if the new cluster have been added in KubeVela
func (h *Installer) continueOrRestartWorkflow() error {
app, err := FetchAddonRelatedApp(h.ctx, h.cli, h.addon.Name)
if err != nil {
return err
}
if app.Status.Workflow != nil && app.Status.Workflow.Suspend {
mergePatch := client.MergeFrom(app.DeepCopy())
app.Status.Workflow.Suspend = false
if err := h.cli.Status().Patch(h.ctx, app, mergePatch); err != nil {
return err
}
switch {
// this case means user add a new cluster and user want to restart workflow to dispatch addon resources to new cluster
// re-apply app won't help app restart workflow
case app.Status.Phase == common2.ApplicationRunning:
// we can use retry on conflict here in CLI, because we want to update the status in this CLI operation.
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
if err = h.cli.Get(h.ctx, client.ObjectKey{Namespace: app.Namespace, Name: app.Name}, app); err != nil {
return
}
app.Status.Workflow = nil
return h.cli.Status().Update(h.ctx, app)
})
// this case means addon last installation meet some error and workflow has been suspended by app controller
// re-apply app won't help app workflow continue
case app.Status.Workflow != nil && app.Status.Workflow.Suspend:
// we can use retry on conflict here in CLI, because we want to update the status in this CLI operation.
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
if err = h.cli.Get(h.ctx, client.ObjectKey{Namespace: app.Namespace, Name: app.Name}, app); err != nil {
return
}
mergePatch := client.MergeFrom(app.DeepCopy())
app.Status.Workflow.Suspend = false
return h.cli.Status().Patch(h.ctx, app, mergePatch)
})
}
return nil
}

View File

@@ -40,7 +40,7 @@ var _ = Describe("Addon test", func() {
Expect(k8sClient.Delete(ctx, &app)).Should(BeNil())
})
It("continueIfSuspend func test", func() {
It("continueOrRestartWorkflow func test", func() {
app = v1beta1.Application{}
Expect(yaml.Unmarshal([]byte(appYaml), &app)).Should(BeNil())
app.SetNamespace(testns)
@@ -69,7 +69,7 @@ var _ = Describe("Addon test", func() {
}
h := Installer{ctx: ctx, cli: k8sClient, addon: &InstallPackage{Meta: Meta{Name: "test-app"}}}
if err := h.continueIfSuspend(); err != nil {
if err := h.continueOrRestartWorkflow(); err != nil {
return err
}
return nil
@@ -87,6 +87,54 @@ var _ = Describe("Addon test", func() {
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
})
It("continueOrRestartWorkflow func test, test restart workflow", func() {
app = v1beta1.Application{}
Expect(yaml.Unmarshal([]byte(appYaml), &app)).Should(BeNil())
app.SetNamespace(testns)
Expect(k8sClient.Create(ctx, &app)).Should(BeNil())
Eventually(func() error {
checkApp := &v1beta1.Application{}
if err := k8sClient.Get(ctx, types2.NamespacedName{Namespace: app.Namespace, Name: app.Name}, checkApp); err != nil {
return err
}
appPatch := client.MergeFrom(checkApp.DeepCopy())
checkApp.Status.Workflow = &common.WorkflowStatus{Message: "someMessage", AppRevision: "test-revision"}
checkApp.Status.Phase = common.ApplicationRunning
if err := k8sClient.Status().Patch(ctx, checkApp, appPatch); err != nil {
return err
}
return nil
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
Eventually(func() error {
checkApp := &v1beta1.Application{}
if err := k8sClient.Get(ctx, types2.NamespacedName{Namespace: app.Namespace, Name: app.Name}, checkApp); err != nil {
return err
}
if checkApp.Status.Phase != common.ApplicationRunning {
return fmt.Errorf("app haven't not running")
}
h := Installer{ctx: ctx, cli: k8sClient, addon: &InstallPackage{Meta: Meta{Name: "test-app"}}}
if err := h.continueOrRestartWorkflow(); err != nil {
return err
}
return nil
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
Eventually(func() error {
checkApp := &v1beta1.Application{}
if err := k8sClient.Get(ctx, types2.NamespacedName{Namespace: app.Namespace, Name: app.Name}, checkApp); err != nil {
return err
}
if checkApp.Status.Workflow != nil {
return fmt.Errorf("app workflow havenot been restart")
}
return nil
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
})
It(" FetchAddonRelatedApp func test", func() {
app = v1beta1.Application{}
Expect(yaml.Unmarshal([]byte(legacyAppYaml), &app)).Should(BeNil())

View File

@@ -122,9 +122,11 @@ func testReaderFunc(t *testing.T, reader AsyncReader) {
assert.True(t, len(uiData.Definitions) > 0)
// test get ui data
uiDataList, err := ListAddonUIDataFromReader(reader, registryMeta, "KubeVela", UIMetaOptions)
rName := "KubeVela"
uiDataList, err := ListAddonUIDataFromReader(reader, registryMeta, rName, UIMetaOptions)
assert.True(t, strings.Contains(err.Error(), "#parameter.example: preference mark not allowed at this position"))
assert.Equal(t, len(uiDataList), 3)
assert.Equal(t, uiDataList[0].RegistryName, rName)
// test get install package
installPkg, err := GetInstallPackageFromReader(reader, &testAddonMeta, uiData)
@@ -224,6 +226,17 @@ func TestRenderApp(t *testing.T) {
assert.Equal(t, len(app.Spec.Components), 2)
}
func TestRenderAppWithNeedNamespace(t *testing.T) {
addon := baseAddon
addon.NeedNamespace = append(addon.NeedNamespace, types.DefaultKubeVelaNS)
app, err := RenderApp(ctx, &addon, nil, nil, map[string]interface{}{})
assert.NoError(t, err, "render app fail")
assert.Equal(t, len(app.Spec.Components), 2)
for _, c := range app.Spec.Components {
assert.NotEqual(t, types.DefaultKubeVelaNS+"-namespace", c.Name, "namespace vela-system should not be rendered")
}
}
func TestRenderDeploy2RuntimeAddon(t *testing.T) {
addonDeployToRuntime := baseAddon
addonDeployToRuntime.Meta.DeployTo = &DeployTo{
@@ -435,7 +448,7 @@ func TestRenderApp4Observability(t *testing.T) {
},
},
args: map[string]interface{}{},
application: `{"kind":"Application","apiVersion":"core.oam.dev/v1beta1","metadata":{"name":"addon-observability","namespace":"vela-system","creationTimestamp":null,"labels":{"addons.oam.dev/name":"observability"}},"spec":{"components":[],"policies":[{"name":"domain","type":"env-binding","properties":{"envs":null}}],"workflow":{"steps":[{"name":"deploy-control-plane","type":"apply-application-in-parallel"}]}},"status":{}}`,
application: `{"kind":"Application","apiVersion":"core.oam.dev/v1beta1","metadata":{"name":"addon-observability","namespace":"vela-system","creationTimestamp":null,"labels":{"addons.oam.dev/name":"observability"}},"spec":{"components":[],"policies":[{"name":"domain","type":"env-binding","properties":{"envs":null}}],"workflow":{"steps":[{"name":"deploy-control-plane","type":"apply-application"}]}},"status":{}}`,
},
}
for _, tc := range testcases {
@@ -537,3 +550,8 @@ func TestGetPatternFromItem(t *testing.T) {
assert.Equal(t, res, tc.meetPattern, tc.caseName)
}
}
func TestGitLabReaderNotPanic(t *testing.T) {
_, err := NewAsyncReader("https://gitlab.com/test/catalog", "", "addons", "", gitType)
assert.EqualError(t, err, "git type repository only support github for now")
}

View File

@@ -75,6 +75,30 @@ func DisableAddon(ctx context.Context, cli client.Client, name string) error {
return nil
}
// EnableAddonByLocalDir enable an addon from local dir
func EnableAddonByLocalDir(ctx context.Context, name string, dir string, cli client.Client, applicator apply.Applicator, config *rest.Config, args map[string]interface{}) error {
r := localReader{dir: dir, name: name}
metas, err := r.ListAddonMeta()
if err != nil {
return err
}
meta := metas[r.name]
UIData, err := GetUIDataFromReader(r, &meta, UIMetaOptions)
if err != nil {
return err
}
pkg, err := GetInstallPackageFromReader(r, &meta, UIData)
if err != nil {
return err
}
h := NewAddonInstaller(ctx, cli, applicator, config, &Registry{Name: LocalAddonRegistryName}, args, nil)
err = h.enableAddon(pkg)
if err != nil {
return err
}
return nil
}
// GetAddonStatus is genrall func for cli and apiServer get addon status
func GetAddonStatus(ctx context.Context, cli client.Client, name string) (Status, error) {
app, err := FetchAddonRelatedApp(ctx, cli, name)

View File

@@ -48,6 +48,9 @@ func (g *gitReader) ListAddonMeta() (map[string]SourceMeta, error) {
}
for _, item := range items {
// single addon
if item.GetType() != DirType {
continue
}
addonName := path.Base(item.GetPath())
addonMeta, err := g.listAddonMeta(g.RelativePath(item))
if err != nil {

67
pkg/addon/reader_local.go Normal file
View File

@@ -0,0 +1,67 @@
/*
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 addon
import (
"fmt"
"io/ioutil"
"path/filepath"
"strings"
)
type localReader struct {
dir string
name string
}
func (l localReader) ListAddonMeta() (map[string]SourceMeta, error) {
metas := SourceMeta{Name: l.name}
if err := recursiveFetchFiles(l.dir, &metas); err != nil {
return nil, err
}
return map[string]SourceMeta{l.name: metas}, nil
}
func (l localReader) ReadFile(path string) (string, error) {
file := strings.TrimPrefix(path, l.name+"/")
b, err := ioutil.ReadFile(filepath.Clean(filepath.Join(l.dir, file)))
if err != nil {
return "", err
}
return string(b), nil
}
func (l localReader) RelativePath(item Item) string {
return filepath.Join(l.name, strings.TrimPrefix(item.GetPath()+"/", l.dir))
}
func recursiveFetchFiles(path string, metas *SourceMeta) error {
files, err := ioutil.ReadDir(path)
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
if err := recursiveFetchFiles(fmt.Sprintf("%s/%s", path, file.Name()), metas); err != nil {
return err
}
} else {
metas.Items = append(metas.Items, OSSItem{tp: "file", path: fmt.Sprintf("%s/%s", path, file.Name()), name: file.Name()})
}
}
return nil
}

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 addon
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestLocalReader(t *testing.T) {
r := localReader{name: "local", dir: "./testdata/local"}
m, err := r.ListAddonMeta()
assert.NoError(t, err)
assert.Equal(t, len(m["local"].Items), 2)
file, err := r.ReadFile("metadata.yaml")
assert.NoError(t, err)
assert.Equal(t, file, metaFile)
file, err = r.ReadFile("resources/parameter.cue")
assert.NoError(t, err)
assert.Equal(t, true, strings.Contains(file, parameterFile))
}
const (
metaFile = `name: test-local-addon
version: 1.0.0
description: This is a addon for test when install addon from local
icon: https://www.terraform.io/assets/images/logo-text-8c3ba8a6.svg
url: https://terraform.io/
tags: []
deployTo:
control_plane: true
runtime_cluster: false
dependencies: []
invisible: false`
parameterFile = `parameter: {
// test wrong parameter
example: *"default"
}`
)

View File

@@ -127,8 +127,8 @@ func NewAsyncReader(baseURL, bucket, subPath, token string, rdType ReaderType) (
return nil, errors.New("addon registry invalid")
}
u.Path = path.Join(u.Path, subPath)
tp, content, err := utils.Parse(u.String())
if err != nil || tp != utils.TypeGithub {
_, content, err := utils.Parse(u.String())
if err != nil {
return nil, err
}
gith := createGitHelper(content, token)

View File

@@ -22,11 +22,11 @@ import (
"time"
v12 "k8s.io/api/core/v1"
crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
@@ -75,7 +75,7 @@ var _ = BeforeSuite(func(done Done) {
scheme = runtime.NewScheme()
Expect(coreoam.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(clientgoscheme.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(v1beta1.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(crdv1.AddToScheme(scheme)).NotTo(HaveOccurred())
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).ToNot(HaveOccurred())
Expect(k8sClient).ToNot(BeNil())

15
pkg/addon/testdata/local/metadata.yaml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: test-local-addon
version: 1.0.0
description: This is a addon for test when install addon from local
icon: https://www.terraform.io/assets/images/logo-text-8c3ba8a6.svg
url: https://terraform.io/
tags: []
deployTo:
control_plane: true
runtime_cluster: false
dependencies: []
invisible: false

View File

@@ -0,0 +1,4 @@
parameter: {
// test wrong parameter
example: *"default"
}

View File

@@ -41,6 +41,9 @@ var (
// ErrIndexInvalid Error that entity index is invalid
ErrIndexInvalid = NewDBError(fmt.Errorf("entity index is invalid"))
// ErrEntityInvalid Error that entity is invalid
ErrEntityInvalid = NewDBError(fmt.Errorf("entity is invalid"))
)
// DBError datastore error

View File

@@ -37,6 +37,9 @@ type mongodb struct {
database string
}
// PrimaryKey primary key
const PrimaryKey = "_name"
// New new mongodb datastore instance
func New(ctx context.Context, cfg datastore.Config) (datastore.DataStore, error) {
if !strings.HasPrefix(cfg.URL, "mongodb://") {
@@ -67,8 +70,13 @@ func (m *mongodb) Add(ctx context.Context, entity datastore.Entity) error {
if err := m.Get(ctx, entity); err == nil {
return datastore.ErrRecordExist
}
model, err := convertToMap(entity)
if err != nil {
return datastore.ErrEntityInvalid
}
model[PrimaryKey] = entity.PrimaryKey()
collection := m.client.Database(m.database).Collection(entity.TableName())
_, err := collection.InsertOne(ctx, entity)
_, err = collection.InsertOne(ctx, model)
if err != nil {
return datastore.NewDBError(err)
}
@@ -203,7 +211,7 @@ func (m *mongodb) List(ctx context.Context, entity datastore.Entity, op *datasto
if entity.Index() != nil {
for k, v := range entity.Index() {
filter = append(filter, bson.E{
Key: k,
Key: strings.ToLower(k),
Value: v,
})
}
@@ -279,9 +287,21 @@ func (m *mongodb) Count(ctx context.Context, entity datastore.Entity, filterOpti
}
func makeNameFilter(name string) bson.D {
return bson.D{{Key: "name", Value: name}}
return bson.D{{Key: PrimaryKey, Value: name}}
}
func makeEntityUpdate(entity interface{}) bson.M {
return bson.M{"$set": entity}
}
func convertToMap(model interface{}) (bson.M, error) {
b, err := bson.Marshal(model)
if err != nil {
return nil, err
}
var re = make(bson.M)
if err := bson.Unmarshal(b, &re); err != nil {
return nil, err
}
return re, nil
}

View File

@@ -26,6 +26,8 @@ import (
"github.com/google/go-cmp/cmp/cmpopts"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
"github.com/oam-dev/kubevela/pkg/apiserver/model"
@@ -35,7 +37,11 @@ var mongodbDriver datastore.DataStore
var _ = BeforeSuite(func(done Done) {
rand.Seed(time.Now().UnixNano())
By("bootstrapping mongodb test environment")
var err error
clientOpts := options.Client().ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(context.TODO(), clientOpts)
Expect(err).ToNot(HaveOccurred())
client.Database("kubevela").Drop(context.TODO())
mongodbDriver, err = New(context.TODO(), datastore.Config{
URL: "mongodb://localhost:27017",
Database: "kubevela",
@@ -65,6 +71,8 @@ var _ = Describe("Test mongodb datastore driver", func() {
&model.Application{Name: "kubevela-app-2", Description: "this is demo 2"},
&model.Application{Name: "kubevela-app-3", Description: "this is demo 3"},
&model.Application{Name: "kubevela-app-4", Description: "this is demo 4"},
&model.Workflow{Name: "kubevela-app-workflow", AppPrimaryKey: "kubevela-app-2", Description: "this is workflow"},
&model.ApplicationTrigger{Name: "kubevela-app-trigger", AppPrimaryKey: "kubevela-app-2", Token: "token-test", Description: "this is demo 4"},
}
err := mongodbDriver.BatchAdd(context.TODO(), datas)
Expect(err).ToNot(HaveOccurred())
@@ -84,6 +92,12 @@ var _ = Describe("Test mongodb datastore driver", func() {
Expect(err).Should(BeNil())
diff := cmp.Diff(app.Description, "default")
Expect(diff).Should(BeEmpty())
workflow := &model.Workflow{Name: "kubevela-app-workflow", AppPrimaryKey: "kubevela-app-2"}
err = mongodbDriver.Get(context.TODO(), workflow)
Expect(err).Should(BeNil())
diff = cmp.Diff(workflow.Description, "this is workflow")
Expect(diff).Should(BeEmpty())
})
It("Test put function", func() {
@@ -111,6 +125,14 @@ var _ = Describe("Test mongodb datastore driver", func() {
Expect(err).ShouldNot(HaveOccurred())
diff = cmp.Diff(len(list), 4)
Expect(diff).Should(BeEmpty())
var workflow = model.Workflow{
AppPrimaryKey: "kubevela-app-2",
}
list, err = mongodbDriver.List(context.TODO(), &workflow, nil)
Expect(err).ShouldNot(HaveOccurred())
diff = cmp.Diff(len(list), 1)
Expect(diff).Should(BeEmpty())
})
It("Test list clusters with sort and fuzzy query", func() {
@@ -213,5 +235,13 @@ var _ = Describe("Test mongodb datastore driver", func() {
err = mongodbDriver.Delete(context.TODO(), &app)
equal := cmp.Equal(err, datastore.ErrRecordNotExist, cmpopts.EquateErrors())
Expect(equal).Should(BeTrue())
workflow := model.Workflow{Name: "kubevela-app-workflow", AppPrimaryKey: "kubevela-app-2", Description: "this is workflow"}
err = mongodbDriver.Delete(context.TODO(), &workflow)
Expect(err).ShouldNot(HaveOccurred())
trigger := model.ApplicationTrigger{Name: "kubevela-app-trigger", AppPrimaryKey: "kubevela-app-2", Token: "token-test", Description: "this is demo 4"}
err = mongodbDriver.Delete(context.TODO(), &trigger)
Expect(err).ShouldNot(HaveOccurred())
})
})

View File

@@ -213,6 +213,8 @@ type ApplicationRevision struct {
EnvName string `json:"envName"`
// CodeInfo is the code info of this application revision
CodeInfo *CodeInfo `json:"codeInfo,omitempty"`
// ImageInfo is the image info of this application revision
ImageInfo *ImageInfo `json:"imageInfo,omitempty"`
}
// CodeInfo is the code info for webhook request
@@ -225,6 +227,44 @@ type CodeInfo struct {
User string `json:"user,omitempty"`
}
// ImageInfo is the image info for webhook request
type ImageInfo struct {
// Type is the image type, ACR or Harbor or DockerHub
Type string `json:"type"`
// Resource is the image resource
Resource *ImageResource `json:"resource,omitempty"`
// Repository is the image repository
Repository *ImageRepository `json:"repository,omitempty"`
}
// ImageResource is the image resource
type ImageResource struct {
// Digest is the image digest
Digest string `json:"digest"`
// Tag is the image tag
Tag string `json:"tag"`
// URL is the image url
URL string `json:"url"`
// CreateTime is the image create time
CreateTime time.Time `json:"createTime,omitempty"`
}
// ImageRepository is the image repository
type ImageRepository struct {
// Name is the image repository name
Name string `json:"name"`
// Namespace is the image repository namespace
Namespace string `json:"namespace"`
// FullName is the image repository full name
FullName string `json:"fullName"`
// Region is the image repository region
Region string `json:"region,omitempty"`
// Type is the image repository type, public or private
Type string `json:"type"`
// CreateTime is the image repository create time
CreateTime time.Time `json:"createTime,omitempty"`
}
// TableName return custom table name
func (a *ApplicationRevision) TableName() string {
return tableNamePrefix + "application_revision"
@@ -280,6 +320,28 @@ const (
PayloadTypeCustom = "custom"
// PayloadTypeDockerhub is the payload type dockerhub
PayloadTypeDockerhub = "dockerhub"
// PayloadTypeACR is the payload type acr
PayloadTypeACR = "acr"
// PayloadTypeHarbor is the payload type harbor
PayloadTypeHarbor = "harbor"
// PayloadTypeJFrog is the payload type jfrog
PayloadTypeJFrog = "jfrog"
// ComponentTypeWebservice is the component type webservice
ComponentTypeWebservice = "webservice"
// ComponentTypeWorker is the component type worker
ComponentTypeWorker = "worker"
// ComponentTypeTask is the component type task
ComponentTypeTask = "task"
)
const (
// HarborEventTypePushArtifact is the event type PUSH_ARTIFACT
HarborEventTypePushArtifact = "PUSH_ARTIFACT"
// JFrogEventTypePush is push event type of jfrog webhook
JFrogEventTypePush = "pushed"
// JFrogDomainDocker is webhook domain of jfrog docker
JFrogDomainDocker = "docker"
)
// TableName return custom table name

View File

@@ -0,0 +1,47 @@
/*
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 model
func init() {
RegistModel(&SystemInfo{})
}
// SystemInfo systemInfo model
type SystemInfo struct {
BaseModel
InstallID string `json:"installID"`
EnableCollection bool `json:"enableCollection"`
}
// TableName return custom table name
func (u *SystemInfo) TableName() string {
return tableNamePrefix + "system_info"
}
// PrimaryKey return custom primary key
func (u *SystemInfo) PrimaryKey() string {
return u.InstallID
}
// Index return custom index
func (u *SystemInfo) Index() map[string]string {
index := make(map[string]string)
if u.InstallID != "" {
index["installID"] = u.InstallID
}
return index
}

View File

@@ -341,25 +341,27 @@ type UpdateApplicationRequest struct {
// CreateApplicationTriggerRequest create application trigger
type CreateApplicationTriggerRequest struct {
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
WorkflowName string `json:"workflowName"`
Type string `json:"type" validate:"oneof=webhook"`
PayloadType string `json:"payloadType" validate:"oneof=custom"`
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
WorkflowName string `json:"workflowName"`
Type string `json:"type" validate:"oneof=webhook"`
PayloadType string `json:"payloadType" validate:"checkpayloadtype"`
ComponentName string `json:"componentName,omitempty" optional:"true"`
}
// ApplicationTriggerBase application trigger base model
type ApplicationTriggerBase struct {
Name string `json:"name"`
Alias string `json:"alias,omitempty"`
Description string `json:"description,omitempty"`
WorkflowName string `json:"workflowName"`
Type string `json:"type"`
PayloadType string `json:"payloadType"`
Token string `json:"token"`
CreateTime time.Time `json:"createTime"`
UpdateTime time.Time `json:"updateTime"`
Name string `json:"name"`
Alias string `json:"alias,omitempty"`
Description string `json:"description,omitempty"`
WorkflowName string `json:"workflowName"`
Type string `json:"type"`
PayloadType string `json:"payloadType"`
Token string `json:"token"`
ComponentName string `json:"componentName,omitempty"`
CreateTime time.Time `json:"createTime"`
UpdateTime time.Time `json:"updateTime"`
}
// ListApplicationTriggerResponse list application triggers response body
@@ -367,16 +369,123 @@ type ListApplicationTriggerResponse struct {
Triggers []*ApplicationTriggerBase `json:"triggers"`
}
// HandleApplicationWebhookRequest handles application webhook request
type HandleApplicationWebhookRequest struct {
// HandleApplicationTriggerWebhookRequest handles application trigger webhook request
type HandleApplicationTriggerWebhookRequest struct {
Upgrade map[string]*model.JSONStruct `json:"upgrade,omitempty"`
CodeInfo *model.CodeInfo `json:"codeInfo,omitempty"`
}
// HandleApplicationTriggerACRRequest handles application trigger ACR request
type HandleApplicationTriggerACRRequest struct {
PushData ACRPushData `json:"push_data"`
Repository ACRRepository `json:"repository"`
}
// ACRPushData is the push data of ACR
type ACRPushData struct {
Digest string `json:"digest"`
PushedAt string `json:"pushed_at"`
Tag string `json:"tag"`
}
// ACRRepository is the repository of ACR
type ACRRepository struct {
DateCreated string `json:"date_created"`
Name string `json:"name"`
Namespace string `json:"namespace"`
Region string `json:"region"`
RepoAuthenticationType string `json:"repo_authentication_type"`
RepoFullName string `json:"repo_full_name"`
RepoOriginType string `json:"repo_origin_type"`
RepoType string `json:"repo_type"`
}
// HandleApplicationHarborReq handles application trigger harbor request
type HandleApplicationHarborReq struct {
Type string `json:"type"`
OccurAt int64 `json:"occur_at"`
Operator string `json:"operator"`
EventData EventData `json:"event_data"`
}
// Resources is the image info of harbor
type Resources struct {
Digest string `json:"digest"`
Tag string `json:"tag"`
ResourceURL string `json:"resource_url"`
}
// Repository is the repository of harbor
type Repository struct {
DateCreated int64 `json:"date_created"`
Name string `json:"name"`
Namespace string `json:"namespace"`
RepoFullName string `json:"repo_full_name"`
RepoType string `json:"repo_type"`
}
// EventData is the event info of harbor
type EventData struct {
Resources []Resources `json:"resources"`
Repository Repository `json:"repository"`
}
// HandleApplicationTriggerDockerHubRequest application trigger DockerHub webhook request
type HandleApplicationTriggerDockerHubRequest struct {
CallbackURL string `json:"callback_url"`
PushData DockerHubData `json:"push_data"`
Repository DockerHubRepository `json:"repository"`
}
// DockerHubData is the push data of dockerhub
type DockerHubData struct {
Images []string `json:"images"`
PushedAt int64 `json:"pushed_at"`
Pusher string `json:"pusher"`
Tag string `json:"tag"`
}
// DockerHubRepository is the repository of dockerhub
type DockerHubRepository struct {
CommentCount int `json:"comment_count"`
DateCreated int64 `json:"date_created"`
Description string `json:"description"`
Dockerfile string `json:"dockerfile"`
FullDescription string `json:"full_description"`
IsOfficial bool `json:"is_official"`
IsPrivate bool `json:"is_private"`
IsTrusted bool `json:"is_trusted"`
Name string `json:"name"`
Namespace string `json:"namespace"`
Owner string `json:"owner"`
RepoName string `json:"repo_name"`
RepoURL string `json:"repo_url"`
StartCount int `json:"star_count"`
Status string `json:"status"`
}
// HandleApplicationTriggerJFrogRequest application trigger JFrog webhook request
type HandleApplicationTriggerJFrogRequest struct {
Domain string `json:"domain"`
EventType string `json:"event_type"`
Data JFrogWebhookData `json:"data"`
}
// JFrogWebhookData is the data of JFrog webhook request
type JFrogWebhookData struct {
URL string
ImageName string `json:"image_name"`
Name string `json:"name"`
Path string `json:"path"`
RepoKey string `json:"repo_key"`
Digest string `json:"sha256"`
Tag string `json:"tag"`
}
// EnvBinding application env binding
type EnvBinding struct {
Name string `json:"name" validate:"checkname"`
//TODO: support componentsPatch
// TODO: support componentsPatch
}
// EnvBindingTarget the target struct in the envbinding base struct
@@ -761,7 +870,9 @@ type ApplicationDeployRequest struct {
// Force set to True to ignore unfinished events.
Force bool `json:"force"`
// CodeInfo is the source code info of this deploy
CodeInfo *model.CodeInfo `json:"gitInfo,omitempty"`
CodeInfo *model.CodeInfo `json:"codeInfo,omitempty"`
// ImageInfo is the image code info of this deploy
ImageInfo *model.ImageInfo `json:"imageInfo,omitempty"`
}
// ApplicationDeployResponse application deploy response body
@@ -769,6 +880,14 @@ type ApplicationDeployResponse struct {
ApplicationRevisionBase
}
// ApplicationDockerhubWebhookResponse dockerhub webhook response body
type ApplicationDockerhubWebhookResponse struct {
State string `json:"state,omitempty"`
Description string `json:"description,omitempty"`
Context string `json:"context,omitempty"`
TargetURL string `json:"target_url,omitempty"`
}
// VelaQLViewResponse query response
type VelaQLViewResponse map[string]interface{}
@@ -872,6 +991,8 @@ type ApplicationRevisionBase struct {
TriggerType string `json:"triggerType"`
// CodeInfo is the code info of this application revision
CodeInfo *model.CodeInfo `json:"codeInfo,omitempty"`
// ImageInfo is the image info of this application revision
ImageInfo *model.ImageInfo `json:"imageInfo,omitempty"`
}
// ListRevisionsResponse list application revisions
@@ -884,3 +1005,20 @@ type ListRevisionsResponse struct {
type DetailRevisionResponse struct {
model.ApplicationRevision
}
// SystemInfoResponse get SystemInfo
type SystemInfoResponse struct {
model.SystemInfo
SystemVersion SystemVersion `json:"systemVersion"`
}
// SystemInfoRequest request by update SystemInfo
type SystemInfoRequest struct {
EnableCollection bool
}
// SystemVersion contains KubeVela version
type SystemVersion struct {
VelaVersion string `json:"velaVersion"`
GitVersion string `json:"gitVersion"`
}

View File

@@ -39,6 +39,7 @@ import (
"github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/webservice"
utils2 "github.com/oam-dev/kubevela/pkg/utils"
)
var _ APIServer = &restServer{}
@@ -214,8 +215,8 @@ func (s *restServer) requestLog(req *restful.Request, resp *restful.Response, ch
chain.ProcessFilter(req, resp)
takeTime := time.Since(start)
log.Logger.With(
"clientIP", utils.ClientIP(req.Request),
"path", req.Request.URL.Path,
"clientIP", utils2.Sanitize(utils.ClientIP(req.Request)),
"path", utils2.Sanitize(req.Request.URL.Path),
"method", req.Request.Method,
"status", c.StatusCode(),
"time", takeTime.String(),

View File

@@ -18,6 +18,7 @@ package usecase
import (
"context"
"encoding/json"
"errors"
"fmt"
"sort"
@@ -25,6 +26,8 @@ import (
"sync"
"time"
k8stypes "k8s.io/apimachinery/pkg/types"
v1 "k8s.io/api/core/v1"
errors2 "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -39,6 +42,7 @@ import (
"github.com/oam-dev/kubevela/pkg/apiserver/clients"
"github.com/oam-dev/kubevela/pkg/apiserver/log"
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/utils/apply"
@@ -155,7 +159,9 @@ func (u *defaultAddonHandler) GetAddon(ctx context.Context, name string, registr
if addon == nil {
return nil, bcode.ErrAddonNotExist
}
addon.UISchema = renderDefaultUISchema(addon.APISchema)
addon.UISchema = renderAddonCustomUISchema(ctx, u.kubeClient, name, renderDefaultUISchema(addon.APISchema))
a, err := AddonImpl2AddonRes(addon)
if err != nil {
return nil, err
@@ -455,6 +461,29 @@ func convertAppStateToAddonPhase(state common2.ApplicationPhase) apis.AddonPhase
}
}
func renderAddonCustomUISchema(ctx context.Context, cli client.Client, addonName string, defaultSchema []*utils.UIParameter) []*utils.UIParameter {
var cm v1.ConfigMap
if err := cli.Get(ctx, k8stypes.NamespacedName{
Namespace: types.DefaultKubeVelaNS,
Name: fmt.Sprintf("addon-uischema-%s", addonName),
}, &cm); err != nil {
if !errors2.IsNotFound(err) {
log.Logger.Errorf("find uischema configmap from cluster failure %s", err.Error())
}
return defaultSchema
}
data, ok := cm.Data[types.UISchema]
if !ok {
return defaultSchema
}
schema := []*utils.UIParameter{}
if err := json.Unmarshal([]byte(data), &schema); err != nil {
log.Logger.Errorf("unmarshal ui schema failure %s", err.Error())
return defaultSchema
}
return patchSchema(defaultSchema, schema)
}
// ConvertAddonRegistryModel2AddonRegistryMeta will convert from model to AddonRegistry
func ConvertAddonRegistryModel2AddonRegistryMeta(r pkgaddon.Registry) apis.AddonRegistry {
return apis.AddonRegistry{

View File

@@ -0,0 +1,106 @@
/*
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 usecase
import (
"context"
"fmt"
"io/ioutil"
"github.com/oam-dev/kubevela/pkg/oam/util"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils"
)
var _ = Describe("addon usecase test", func() {
var ctx context.Context
BeforeEach(func() {
ctx = context.Background()
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: types.DefaultKubeVelaNS}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
})
It("Test render customize ui-schema", func() {
schemaData, err := ioutil.ReadFile("testdata/addon-uischema-test.yaml")
addonName := "test"
Expect(err).Should(BeNil())
jsonData, err := yaml.YAMLToJSON(schemaData)
Expect(err).Should(BeNil())
cm := v1.ConfigMap{
TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
ObjectMeta: metav1.ObjectMeta{Namespace: types.DefaultKubeVelaNS, Name: fmt.Sprintf("addon-uischema-%s", addonName)},
Data: map[string]string{
types.UISchema: string(jsonData),
}}
Expect(k8sClient.Create(ctx, &cm)).Should(BeNil())
defaultSchema := []*utils.UIParameter{
{
JSONKey: "version",
Sort: 3,
},
{
JSONKey: "domain",
Sort: 8,
},
}
res := renderAddonCustomUISchema(ctx, k8sClient, addonName, defaultSchema)
Expect(len(res)).Should(BeEquivalentTo(2))
for _, re := range res {
if re.JSONKey == "version" {
Expect(re.Validate.DefaultValue.(string)).Should(BeEquivalentTo("1.2.0-rc1"))
Expect(re.Sort).Should(BeEquivalentTo(1))
}
if re.JSONKey == "domain" {
Expect(re.Sort).Should(BeEquivalentTo(9))
}
}
})
It("Test render without ui-schema", func() {
addonName := "test-without-schema"
defaultSchema := []*utils.UIParameter{
{
JSONKey: "version",
Sort: 3,
},
{
JSONKey: "domain",
Sort: 8,
},
}
res := renderAddonCustomUISchema(ctx, k8sClient, addonName, defaultSchema)
Expect(len(res)).Should(BeEquivalentTo(2))
for _, re := range res {
if re.JSONKey == "version" {
Expect(re.Validate).Should(BeNil())
Expect(re.Sort).Should(BeEquivalentTo(3))
}
if re.JSONKey == "domain" {
Expect(re.Sort).Should(BeEquivalentTo(8))
}
}
})
})

View File

@@ -93,6 +93,7 @@ type ApplicationUsecase interface {
ListRecords(ctx context.Context, appName string) (*apisv1.ListWorkflowRecordsResponse, error)
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
}
type applicationUsecaseImpl struct {
@@ -143,7 +144,7 @@ func listApp(ctx context.Context, ds datastore.DataStore, listOptions apisv1.Lis
if listOptions.Env != "" || listOptions.TargetName != "" {
envBinding, err = listFullEnvBinding(ctx, ds, envListOption{})
if err != nil {
log.Logger.Errorf("list envbinding for list application in env %s err %v", listOptions.Env, err)
log.Logger.Errorf("list envbinding for list application in env %s err %v", utils2.Sanitize(listOptions.Env), err)
return nil, err
}
}
@@ -385,16 +386,35 @@ func (c *applicationUsecaseImpl) CreateApplicationTrigger(ctx context.Context, a
}
return &apisv1.ApplicationTriggerBase{
WorkflowName: req.WorkflowName,
Name: req.Name,
Alias: req.Alias,
Description: req.Description,
Type: req.Type,
PayloadType: req.PayloadType,
Token: trigger.Token,
WorkflowName: req.WorkflowName,
Name: req.Name,
Alias: req.Alias,
Description: req.Description,
Type: req.Type,
PayloadType: req.PayloadType,
Token: trigger.Token,
ComponentName: req.ComponentName,
CreateTime: trigger.CreateTime,
UpdateTime: trigger.UpdateTime,
}, nil
}
// DeleteApplicationTrigger delete application trigger
func (c *applicationUsecaseImpl) DeleteApplicationTrigger(ctx context.Context, app *model.Application, token string) error {
trigger := model.ApplicationTrigger{
AppPrimaryKey: app.PrimaryKey(),
Token: token,
}
if err := c.ds.Delete(ctx, &trigger); err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return bcode.ErrApplicationTriggerNotExist
}
log.Logger.Warnf("delete app trigger failure %s", err.Error())
return err
}
return nil
}
// ListApplicationTrigger list application triggers
func (c *applicationUsecaseImpl) ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error) {
trigger := &model.ApplicationTrigger{
@@ -686,8 +706,8 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat
WorkflowName: oamApp.Annotations[oam.AnnotationWorkflowName],
EnvName: workflow.EnvName,
CodeInfo: req.CodeInfo,
ImageInfo: req.ImageInfo,
}
if err := c.ds.Add(ctx, appRevision); err != nil {
return nil, err
}
@@ -903,6 +923,7 @@ func (c *applicationUsecaseImpl) converRevisionModelToBase(revision *model.Appli
CreateTime: revision.CreateTime,
EnvName: revision.EnvName,
CodeInfo: revision.CodeInfo,
ImageInfo: revision.ImageInfo,
}
}

View File

@@ -164,6 +164,34 @@ var _ = Describe("Test application usecase function", func() {
Expect(len(triggers)).Should(Equal(2))
})
It("Test DeleteTrigger function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), testApp)
Expect(err).Should(BeNil())
triggers, err := appUsecase.ListApplicationTriggers(context.TODO(), appModel)
Expect(err).Should(BeNil())
Expect(len(triggers)).Should(Equal(2))
var trigger *v1.ApplicationTriggerBase
for _, t := range triggers {
if t.Name == "trigger-name" {
trigger = t
break
}
}
Expect(trigger).ShouldNot(BeNil())
Expect(appUsecase.DeleteApplicationTrigger(context.TODO(), appModel, trigger.Token)).Should(BeNil())
triggers, err = appUsecase.ListApplicationTriggers(context.TODO(), appModel)
Expect(err).Should(BeNil())
Expect(len(triggers)).Should(Equal(1))
trigger = nil
for _, t := range triggers {
if t.Name == "trigger-name" {
trigger = t
break
}
}
Expect(trigger).Should(BeNil())
})
It("Test ListComponents function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), testApp)
Expect(err).Should(BeNil())

View File

@@ -33,6 +33,7 @@ import (
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
utils2 "github.com/oam-dev/kubevela/pkg/utils"
)
const (
@@ -184,7 +185,7 @@ func (e *envBindingUsecaseImpl) BatchCreateEnvBinding(ctx context.Context, app *
continue
}
if err := e.ds.Add(ctx, envBindingModel); err != nil {
log.Logger.Errorf("add envbinding %s failure %s", envBindingModel.Name, err.Error())
log.Logger.Errorf("add envbinding %s failure %s", utils2.Sanitize(envBindingModel.Name), err.Error())
continue
}
err = e.createEnvWorkflow(ctx, app, env, i == 0)

View File

@@ -0,0 +1,93 @@
/*
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 usecase
import (
"context"
"github.com/oam-dev/kubevela/version"
v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
"k8s.io/apimachinery/pkg/util/rand"
"github.com/oam-dev/kubevela/pkg/apiserver/model"
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
)
// SystemInfoUsecase is usecase for systemInfoCollection
type SystemInfoUsecase interface {
GetSystemInfo(ctx context.Context) (*v1.SystemInfoResponse, error)
DeleteSystemInfo(ctx context.Context) error
UpdateSystemInfo(ctx context.Context, sysInfo v1.SystemInfoRequest) (*v1.SystemInfoResponse, error)
}
type systemInfoUsecaseImpl struct {
ds datastore.DataStore
}
// NewSystemInfoUsecase return a systemInfoCollectionUsecase
func NewSystemInfoUsecase(ds datastore.DataStore) SystemInfoUsecase {
return &systemInfoUsecaseImpl{ds: ds}
}
func (u systemInfoUsecaseImpl) GetSystemInfo(ctx context.Context) (*v1.SystemInfoResponse, error) {
// first get request will init systemInfoCollection{installId: {random}, enableCollection: true}
info := &model.SystemInfo{}
entities, err := u.ds.List(ctx, info, &datastore.ListOptions{})
if err != nil {
return nil, err
}
if len(entities) != 0 {
info := entities[0].(*model.SystemInfo)
return &v1.SystemInfoResponse{SystemInfo: *info, SystemVersion: v1.SystemVersion{VelaVersion: version.VelaVersion, GitVersion: version.GitRevision}}, nil
}
installID := rand.String(16)
info.InstallID = installID
info.EnableCollection = true
err = u.ds.Add(ctx, info)
if err != nil {
return nil, err
}
return &v1.SystemInfoResponse{SystemInfo: *info, SystemVersion: v1.SystemVersion{VelaVersion: version.VelaVersion, GitVersion: version.GitRevision}}, nil
}
func (u systemInfoUsecaseImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1.SystemInfoRequest) (*v1.SystemInfoResponse, error) {
info, err := u.GetSystemInfo(ctx)
if err != nil {
return nil, err
}
modifiedInfo := model.SystemInfo{InstallID: info.InstallID, EnableCollection: sysInfo.EnableCollection, BaseModel: model.BaseModel{CreateTime: info.CreateTime}}
err = u.ds.Put(ctx, &modifiedInfo)
if err != nil {
return nil, err
}
return &v1.SystemInfoResponse{SystemInfo: modifiedInfo, SystemVersion: v1.SystemVersion{VelaVersion: version.VelaVersion, GitVersion: version.GitRevision}}, nil
}
func (u systemInfoUsecaseImpl) DeleteSystemInfo(ctx context.Context) error {
info, err := u.GetSystemInfo(ctx)
if err != nil {
return err
}
err = u.ds.Delete(ctx, info)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,18 @@
- jsonKey: version
validate:
defaultValue: 1.2.0-rc1
sort: 1
- jsonKey: dbType
label: DBType
validate:
defaultValue: kubeapi
sort: 3
- jsonKey: dbURL
label: DBURL
sort: 5
- jsonKey: database
sort: 7
validate:
defaultValue: kubevela
- jsonKey: domain
sort: 9

View File

@@ -19,10 +19,14 @@ package usecase
import (
"context"
"errors"
"fmt"
"time"
"github.com/emicklei/go-restful/v3"
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
"github.com/oam-dev/kubevela/pkg/apiserver/log"
"github.com/oam-dev/kubevela/pkg/apiserver/model"
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
@@ -31,7 +35,7 @@ import (
// WebhookUsecase webhook usecase
type WebhookUsecase interface {
HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (*apisv1.ApplicationDeployResponse, error)
HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (interface{}, error)
}
type webhookUsecaseImpl struct {
@@ -39,17 +43,82 @@ type webhookUsecaseImpl struct {
applicationUsecase ApplicationUsecase
}
// WebhookHandlers is the webhook handlers
var WebhookHandlers []string
// NewWebhookUsecase new webhook usecase
func NewWebhookUsecase(ds datastore.DataStore,
applicationUsecase ApplicationUsecase,
) WebhookUsecase {
registerHandlers()
return &webhookUsecaseImpl{
ds: ds,
applicationUsecase: applicationUsecase,
}
}
func (c *webhookUsecaseImpl) HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (*apisv1.ApplicationDeployResponse, error) {
func registerHandlers() {
new(customHandlerImpl).install()
new(acrHandlerImpl).install()
new(dockerHubHandlerImpl).install()
new(harborHandlerImpl).install()
new(jfrogHandlerImpl).install()
}
type webhookHandler interface {
handle(ctx context.Context, trigger *model.ApplicationTrigger, app *model.Application) (interface{}, error)
install()
}
type customHandlerImpl struct {
req apisv1.HandleApplicationTriggerWebhookRequest
w *webhookUsecaseImpl
}
type acrHandlerImpl struct {
req apisv1.HandleApplicationTriggerACRRequest
w *webhookUsecaseImpl
}
type dockerHubHandlerImpl struct {
req apisv1.HandleApplicationTriggerDockerHubRequest
w *webhookUsecaseImpl
}
func (c *webhookUsecaseImpl) newCustomHandler(req *restful.Request) (webhookHandler, error) {
var webhookReq apisv1.HandleApplicationTriggerWebhookRequest
if err := req.ReadEntity(&webhookReq); err != nil {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
return &customHandlerImpl{
req: webhookReq,
w: c,
}, nil
}
func (c *webhookUsecaseImpl) newACRHandler(req *restful.Request) (webhookHandler, error) {
var acrReq apisv1.HandleApplicationTriggerACRRequest
if err := req.ReadEntity(&acrReq); err != nil {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
return &acrHandlerImpl{
req: acrReq,
w: c,
}, nil
}
func (c *webhookUsecaseImpl) newDockerHubHandler(req *restful.Request) (webhookHandler, error) {
var dockerHubReq apisv1.HandleApplicationTriggerDockerHubRequest
if err := req.ReadEntity(&dockerHubReq); err != nil {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
return &dockerHubHandlerImpl{
req: dockerHubReq,
w: c,
}, nil
}
func (c *webhookUsecaseImpl) HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (interface{}, error) {
webhookTrigger := &model.ApplicationTrigger{
Token: token,
}
@@ -68,44 +137,366 @@ func (c *webhookUsecaseImpl) HandleApplicationWebhook(ctx context.Context, token
}
return nil, err
}
var handler webhookHandler
var err error
switch webhookTrigger.PayloadType {
case model.PayloadTypeCustom:
var webhookReq apisv1.HandleApplicationWebhookRequest
if err := req.ReadEntity(&webhookReq); err != nil {
return nil, bcode.ErrInvalidWebhookPayloadBody
handler, err = c.newCustomHandler(req)
if err != nil {
return nil, err
}
for comp, properties := range webhookReq.Upgrade {
component := &model.ApplicationComponent{
AppPrimaryKey: webhookTrigger.AppPrimaryKey,
Name: comp,
}
if err := c.ds.Get(ctx, component); err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return nil, bcode.ErrApplicationComponetNotExist
}
return nil, err
}
merge, err := envbinding.MergeRawExtension(component.Properties.RawExtension(), properties.RawExtension())
if err != nil {
return nil, err
}
prop, err := model.NewJSONStructByStruct(merge)
if err != nil {
return nil, err
}
component.Properties = prop
if err := c.ds.Put(ctx, component); err != nil {
return nil, err
}
case model.PayloadTypeACR:
handler, err = c.newACRHandler(req)
if err != nil {
return nil, err
}
case model.PayloadTypeHarbor:
handler, err = c.newHarborHandler(req)
if err != nil {
return nil, err
}
case model.PayloadTypeDockerhub:
handler, err = c.newDockerHubHandler(req)
if err != nil {
return nil, err
}
case model.PayloadTypeJFrog:
handler, err = c.newJFrogHandler(req)
if err != nil {
return nil, err
}
return c.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{
WorkflowName: webhookTrigger.WorkflowName,
Note: "triggered by webhook",
TriggerType: apisv1.TriggerTypeWebhook,
Force: true,
CodeInfo: webhookReq.CodeInfo,
})
default:
return nil, bcode.ErrInvalidWebhookPayloadType
}
return handler.handle(ctx, webhookTrigger, app)
}
func (c *webhookUsecaseImpl) patchComponentProperties(ctx context.Context, component *model.ApplicationComponent, patch *runtime.RawExtension) error {
merge, err := envbinding.MergeRawExtension(component.Properties.RawExtension(), patch)
if err != nil {
return err
}
prop, err := model.NewJSONStructByStruct(merge)
if err != nil {
return err
}
component.Properties = prop
if err := c.ds.Put(ctx, component); err != nil {
return err
}
return nil
}
func (c *customHandlerImpl) handle(ctx context.Context, webhookTrigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) {
for comp, properties := range c.req.Upgrade {
component := &model.ApplicationComponent{
AppPrimaryKey: webhookTrigger.AppPrimaryKey,
Name: comp,
}
if err := c.w.ds.Get(ctx, component); err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return nil, bcode.ErrApplicationComponetNotExist
}
return nil, err
}
if err := c.w.patchComponentProperties(ctx, component, properties.RawExtension()); err != nil {
return nil, err
}
}
return c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{
WorkflowName: webhookTrigger.WorkflowName,
Note: "triggered by webhook custom",
TriggerType: apisv1.TriggerTypeWebhook,
Force: true,
CodeInfo: c.req.CodeInfo,
})
}
func (c *customHandlerImpl) install() {
WebhookHandlers = append(WebhookHandlers, model.PayloadTypeCustom)
}
func (c *acrHandlerImpl) handle(ctx context.Context, webhookTrigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) {
comp := &model.ApplicationComponent{
AppPrimaryKey: webhookTrigger.AppPrimaryKey,
}
comps, err := c.w.ds.List(ctx, comp, &datastore.ListOptions{})
if err != nil {
return nil, err
}
if len(comps) == 0 {
return nil, bcode.ErrApplicationComponetNotExist
}
// use the first component as the target component
component := comps[0].(*model.ApplicationComponent)
acrReq := c.req
image := fmt.Sprintf("registry.%s.aliyuncs.com/%s:%s", acrReq.Repository.Region, acrReq.Repository.RepoFullName, acrReq.PushData.Tag)
if err := c.w.patchComponentProperties(ctx, component, &runtime.RawExtension{
Raw: []byte(fmt.Sprintf(`{"image": "%s"}`, image)),
}); err != nil {
return nil, err
}
return c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{
WorkflowName: webhookTrigger.WorkflowName,
Note: "triggered by webhook acr",
TriggerType: apisv1.TriggerTypeWebhook,
Force: true,
ImageInfo: &model.ImageInfo{
Type: model.PayloadTypeACR,
Resource: &model.ImageResource{
Digest: acrReq.PushData.Digest,
Tag: acrReq.PushData.Tag,
URL: image,
CreateTime: parseTimeString(acrReq.PushData.PushedAt),
},
Repository: &model.ImageRepository{
Name: acrReq.Repository.Name,
Namespace: acrReq.Repository.Namespace,
FullName: acrReq.Repository.RepoFullName,
Region: acrReq.Repository.Region,
Type: acrReq.Repository.RepoType,
CreateTime: parseTimeString(acrReq.Repository.DateCreated),
},
},
})
}
func (c *acrHandlerImpl) install() {
WebhookHandlers = append(WebhookHandlers, model.PayloadTypeACR)
}
func (c dockerHubHandlerImpl) handle(ctx context.Context, trigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) {
dockerHubReq := c.req
if dockerHubReq.Repository.Status != "Active" {
log.Logger.Debugf("receive dockerhub webhook but not create event: %v", dockerHubReq)
return &apisv1.ApplicationDockerhubWebhookResponse{
State: "failed",
Description: "not create event",
}, nil
}
comp := &model.ApplicationComponent{
AppPrimaryKey: trigger.AppPrimaryKey,
}
comps, err := c.w.ds.List(ctx, comp, &datastore.ListOptions{})
if err != nil {
return nil, err
}
if len(comps) == 0 {
return nil, bcode.ErrApplicationComponetNotExist
}
// use the first component as the target component
component := comps[0].(*model.ApplicationComponent)
image := fmt.Sprintf("docker.io/%s:%s", dockerHubReq.Repository.RepoName, dockerHubReq.PushData.Tag)
if err := c.w.patchComponentProperties(ctx, component, &runtime.RawExtension{
Raw: []byte(fmt.Sprintf(`{"image": "%s"}`, image)),
}); err != nil {
return nil, err
}
repositoryType := "public"
if dockerHubReq.Repository.IsPrivate {
repositoryType = "private"
}
if _, err = c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{
WorkflowName: trigger.WorkflowName,
Note: "triggered by webhook dockerhub",
TriggerType: apisv1.TriggerTypeWebhook,
Force: true,
ImageInfo: &model.ImageInfo{
Type: model.PayloadTypeDockerhub,
Resource: &model.ImageResource{
Tag: dockerHubReq.PushData.Tag,
URL: image,
CreateTime: time.Unix(dockerHubReq.PushData.PushedAt, 0),
},
Repository: &model.ImageRepository{
Name: dockerHubReq.Repository.Name,
Namespace: dockerHubReq.Repository.Namespace,
FullName: dockerHubReq.Repository.RepoName,
Type: repositoryType,
CreateTime: time.Unix(dockerHubReq.Repository.DateCreated, 0),
},
},
}); err != nil {
return nil, err
}
return &apisv1.ApplicationDockerhubWebhookResponse{
State: "success",
Description: fmt.Sprintf("update application %s/%s success", app.Name, component.Name),
}, nil
}
func (c dockerHubHandlerImpl) install() {
WebhookHandlers = append(WebhookHandlers, model.PayloadTypeDockerhub)
}
func parseTimeString(t string) time.Time {
if t == "" {
return time.Time{}
}
l, err := time.LoadLocation("PRC")
if err != nil {
log.Logger.Errorf("failed to load location: %v", err)
return time.Time{}
}
parsedTime, err := time.ParseInLocation("2006-01-02 15:04:05", t, l)
if err != nil {
log.Logger.Errorf("failed to parse time: %v", err)
return time.Time{}
}
return parsedTime
}
type harborHandlerImpl struct {
req apisv1.HandleApplicationHarborReq
w *webhookUsecaseImpl
}
func (c *webhookUsecaseImpl) newHarborHandler(req *restful.Request) (webhookHandler, error) {
var harborReq apisv1.HandleApplicationHarborReq
if err := req.ReadEntity(&harborReq); err != nil {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
if harborReq.Type != model.HarborEventTypePushArtifact {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
return &harborHandlerImpl{
req: harborReq,
w: c,
}, nil
}
func (c *harborHandlerImpl) install() {
WebhookHandlers = append(WebhookHandlers, model.PayloadTypeHarbor)
}
func (c *harborHandlerImpl) handle(ctx context.Context, webhookTrigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) {
resources := c.req.EventData.Resources
if len(resources) < 1 {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
imageURL := resources[0].ResourceURL
digest := resources[0].Digest
tag := resources[0].Tag
comp := &model.ApplicationComponent{
AppPrimaryKey: webhookTrigger.AppPrimaryKey,
}
comps, err := c.w.ds.List(ctx, comp, &datastore.ListOptions{})
if err != nil {
return nil, err
}
if len(comps) == 0 {
return nil, bcode.ErrApplicationComponetNotExist
}
// use the first component as the target component
component := comps[0].(*model.ApplicationComponent)
harborReq := c.req
if err := c.w.patchComponentProperties(ctx, component, &runtime.RawExtension{
Raw: []byte(fmt.Sprintf(`{"image": "%s"}`, imageURL)),
}); err != nil {
return nil, err
}
return c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{
WorkflowName: webhookTrigger.WorkflowName,
Note: "triggered by webhook harbor",
TriggerType: apisv1.TriggerTypeWebhook,
Force: true,
ImageInfo: &model.ImageInfo{
Type: model.PayloadTypeHarbor,
Resource: &model.ImageResource{
Digest: digest,
Tag: tag,
URL: imageURL,
CreateTime: time.Unix(harborReq.OccurAt, 0),
},
Repository: &model.ImageRepository{
Name: harborReq.EventData.Repository.Name,
Namespace: harborReq.EventData.Repository.Namespace,
FullName: harborReq.EventData.Repository.RepoFullName,
Type: harborReq.EventData.Repository.RepoType,
CreateTime: time.Unix(harborReq.EventData.Repository.DateCreated, 0),
},
},
})
}
type jfrogHandlerImpl struct {
req apisv1.HandleApplicationTriggerJFrogRequest
w *webhookUsecaseImpl
}
func (c *webhookUsecaseImpl) newJFrogHandler(req *restful.Request) (webhookHandler, error) {
var jfrogReq apisv1.HandleApplicationTriggerJFrogRequest
if err := req.ReadEntity(&jfrogReq); err != nil {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
if jfrogReq.Domain != model.JFrogDomainDocker || jfrogReq.EventType != model.JFrogEventTypePush {
return nil, bcode.ErrInvalidWebhookPayloadBody
}
// jfrog should use request header to give URL, it is not exist in request body
jfrogReq.Data.URL = req.HeaderParameter("X-JFrogURL")
return &jfrogHandlerImpl{
req: jfrogReq,
w: c,
}, nil
}
func (j *jfrogHandlerImpl) handle(ctx context.Context, webhookTrigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) {
jfrogReq := j.req
comp := &model.ApplicationComponent{
AppPrimaryKey: webhookTrigger.AppPrimaryKey,
}
comps, err := j.w.ds.List(ctx, comp, &datastore.ListOptions{})
if err != nil {
return nil, err
}
if len(comps) == 0 {
return nil, bcode.ErrApplicationComponetNotExist
}
// use the first component as the target component
component := comps[0].(*model.ApplicationComponent)
image := fmt.Sprintf("%s/%s:%s", jfrogReq.Data.RepoKey, jfrogReq.Data.ImageName, jfrogReq.Data.Tag)
if jfrogReq.Data.URL != "" {
image = fmt.Sprintf("%s/%s", jfrogReq.Data.URL, image)
}
if err := j.w.patchComponentProperties(ctx, component, &runtime.RawExtension{
Raw: []byte(fmt.Sprintf(`{"image": "%s"}`, image)),
}); err != nil {
return nil, err
}
return j.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{
WorkflowName: webhookTrigger.WorkflowName,
Note: "triggered by webhook jfrog",
TriggerType: apisv1.TriggerTypeWebhook,
Force: true,
ImageInfo: &model.ImageInfo{
Type: model.PayloadTypeHarbor,
Resource: &model.ImageResource{
Digest: jfrogReq.Data.Digest,
Tag: jfrogReq.Data.Tag,
URL: image,
},
Repository: &model.ImageRepository{
Name: jfrogReq.Data.ImageName,
Namespace: jfrogReq.Data.RepoKey,
FullName: fmt.Sprintf("%s/%s", jfrogReq.Data.RepoKey, jfrogReq.Data.ImageName),
},
},
})
}
func (j *jfrogHandlerImpl) install() {
WebhookHandlers = append(WebhookHandlers, model.PayloadTypeJFrog)
}

View File

@@ -106,7 +106,15 @@ var _ = Describe("Test application usecase function", func() {
triggers, err := appUsecase.ListApplicationTriggers(context.TODO(), appModel)
Expect(err).Should(BeNil())
reqBody := apisv1.HandleApplicationWebhookRequest{
invalidReq, err := http.NewRequest("post", "/", bytes.NewBuffer([]byte(`{"upgrade": "test"}`)))
invalidReq.Header.Add(restful.HEADER_ContentType, "application/json")
Expect(err).Should(BeNil())
_, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), triggers[0].Token, restful.NewRequest(invalidReq))
Expect(err).Should(Equal(bcode.ErrInvalidWebhookPayloadBody))
By("Test HandleApplicationWebhook function with custom payload")
reqBody := apisv1.HandleApplicationTriggerWebhookRequest{
Upgrade: map[string]*model.JSONStruct{
"component-name-webhook": {
"image": "test-image",
@@ -128,6 +136,7 @@ var _ = Describe("Test application usecase function", func() {
Expect(err).Should(BeNil())
res, err := webhookUsecase.HandleApplicationWebhook(context.TODO(), triggers[0].Token, restful.NewRequest(httpreq))
Expect(err).Should(BeNil())
appDeployRes := res.(*apisv1.ApplicationDeployResponse)
comp, err := appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook")
Expect(err).Should(BeNil())
Expect((*comp.Properties)["image"]).Should(Equal("test-image"))
@@ -137,12 +146,155 @@ var _ = Describe("Test application usecase function", func() {
revision := &model.ApplicationRevision{
AppPrimaryKey: "test-app-webhook",
Version: res.Version,
Version: appDeployRes.Version,
}
err = webhookUsecase.ds.Get(context.TODO(), revision)
Expect(err).Should(BeNil())
Expect(revision.CodeInfo.Commit).Should(Equal("test-commit"))
Expect(revision.CodeInfo.Branch).Should(Equal("test-branch"))
Expect(revision.CodeInfo.User).Should(Equal("test-user"))
By("Test HandleApplicationWebhook function with ACR payload")
acrTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{
Name: "test-acr",
PayloadType: "acr",
Type: "webhook",
ComponentName: "component-name-webhook",
})
Expect(err).Should(BeNil())
acrBody := apisv1.HandleApplicationTriggerACRRequest{
PushData: apisv1.ACRPushData{
Digest: "test-digest",
Tag: "test-tag",
},
Repository: apisv1.ACRRepository{
Name: "test-repo",
Namespace: "test-namespace",
Region: "test-region",
RepoFullName: "test-namespace/test-repo",
RepoType: "public",
},
}
body, err = json.Marshal(acrBody)
Expect(err).Should(BeNil())
httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body))
httpreq.Header.Add(restful.HEADER_ContentType, "application/json")
Expect(err).Should(BeNil())
_, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), acrTrigger.Token, restful.NewRequest(httpreq))
Expect(err).Should(BeNil())
comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook")
Expect(err).Should(BeNil())
Expect((*comp.Properties)["image"]).Should(Equal("registry.test-region.aliyuncs.com/test-namespace/test-repo:test-tag"))
By("Test HandleApplicationWebhook function with harbor payload")
harborTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{
Name: "test-harbor",
PayloadType: "harbor",
Type: "webhook",
ComponentName: "component-name-webhook",
})
Expect(err).Should(BeNil())
harborBody := apisv1.HandleApplicationHarborReq{
Type: model.HarborEventTypePushArtifact,
EventData: apisv1.EventData{
Resources: []apisv1.Resources{
{
Digest: "test-digest",
Tag: "test-tag",
ResourceURL: "harbor.server/test-pro/test-repo:test-tag",
},
},
Repository: apisv1.Repository{
Name: "test-repo",
Namespace: "test-namespace",
RepoFullName: "test-pro/test-repo",
RepoType: "public",
},
},
}
body, err = json.Marshal(harborBody)
Expect(err).Should(BeNil())
httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body))
httpreq.Header.Add(restful.HEADER_ContentType, "application/json")
Expect(err).Should(BeNil())
_, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), harborTrigger.Token, restful.NewRequest(httpreq))
Expect(err).Should(BeNil())
comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook")
Expect(err).Should(BeNil())
Expect((*comp.Properties)["image"]).Should(Equal("harbor.server/test-pro/test-repo:test-tag"))
By("Test HandleApplicationWebhook function with dockerhub payload")
dockerhubTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{
Name: "test-dockerhub",
PayloadType: "dockerhub",
Type: "webhook",
ComponentName: "component-name-webhook",
})
Expect(err).Should(BeNil())
dockerhubBody := apisv1.HandleApplicationTriggerDockerHubRequest{
PushData: apisv1.DockerHubData{
Tag: "test-tag",
},
Repository: apisv1.DockerHubRepository{
IsPrivate: true,
Name: "test-repo",
Namespace: "test-namespace",
RepoName: "test-namespace/test-repo",
Status: "Active",
},
}
body, err = json.Marshal(dockerhubBody)
Expect(err).Should(BeNil())
httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body))
httpreq.Header.Add(restful.HEADER_ContentType, "application/json")
Expect(err).Should(BeNil())
_, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), dockerhubTrigger.Token, restful.NewRequest(httpreq))
Expect(err).Should(BeNil())
comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook")
Expect(err).Should(BeNil())
Expect((*comp.Properties)["image"]).Should(Equal("docker.io/test-namespace/test-repo:test-tag"))
By("Test HandleApplicationWebhook function with jfrog payload without header of X-JFrogURL")
jfrogTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{
Name: "test-jfrog",
PayloadType: "jfrog",
Type: "webhook",
ComponentName: "component-name-webhook",
})
Expect(err).Should(BeNil())
jfrogBody := apisv1.HandleApplicationTriggerJFrogRequest{
Domain: "docker",
EventType: "pushed",
Data: apisv1.JFrogWebhookData{
ImageName: "test-image",
RepoKey: "test-repo",
Digest: "test-digest",
Tag: "test-tag",
},
}
body, err = json.Marshal(jfrogBody)
Expect(err).Should(BeNil())
httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body))
httpreq.Header.Add(restful.HEADER_ContentType, "application/json")
Expect(err).Should(BeNil())
_, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), jfrogTrigger.Token, restful.NewRequest(httpreq))
Expect(err).Should(BeNil())
comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook")
Expect(err).Should(BeNil())
Expect((*comp.Properties)["image"]).Should(Equal("test-repo/test-image:test-tag"))
By("Test HandleApplicationWebhook function with jfrog payload with header of X-JFrogURL")
httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body))
Expect(err).Should(BeNil())
httpreq.Header.Add(restful.HEADER_ContentType, "application/json")
httpreq.Header.Add("X-JFrogURL", "test-addr")
_, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), jfrogTrigger.Token, restful.NewRequest(httpreq))
Expect(err).Should(BeNil())
comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook")
Expect(err).Should(BeNil())
Expect((*comp.Properties)["image"]).Should(Equal("test-addr/test-repo/test-image:test-tag"))
})
})

View File

@@ -546,6 +546,11 @@ func resetRevisionsAndRecords(ctx context.Context, ds datastore.DataStore, appNa
}
record.Status = model.RevisionStatusTerminated
record.Finished = "true"
for i, step := range record.Steps {
if step.Phase == common.WorkflowStepPhaseRunning {
record.Steps[i].Phase = common.WorkflowStepPhaseStopped
}
}
if err := ds.Put(ctx, record); err != nil {
klog.Info("failed to set rest records' status to terminate", "app name", appName, "workflow name", record.WorkflowName, "record name", record.Name, "error", err)
}

View File

@@ -510,6 +510,40 @@ var _ = Describe("Test workflow usecase functions", func() {
Expect(originalRevision.Status).Should(Equal(model.RevisionStatusRollback))
Expect(originalRevision.RollbackVersion).Should(Equal("revision-rollback0"))
})
It("Test resetRevisionsAndRecords function", func() {
ctx := context.TODO()
err := workflowUsecase.ds.Add(ctx, &model.WorkflowRecord{
AppPrimaryKey: "reset-app",
WorkflowName: "reset-workflow",
Name: "reset-record",
Finished: "false",
Steps: []model.WorkflowStepStatus{
{
Phase: common.WorkflowStepPhaseSucceeded,
},
{
Phase: common.WorkflowStepPhaseRunning,
},
},
})
Expect(err).Should(BeNil())
err = resetRevisionsAndRecords(ctx, workflowUsecase.ds, "reset-app", "reset-workflow", "", "")
Expect(err).Should(BeNil())
record := &model.WorkflowRecord{
AppPrimaryKey: "reset-app",
WorkflowName: "reset-workflow",
Name: "reset-record",
}
err = workflowUsecase.ds.Get(ctx, record)
Expect(err).Should(BeNil())
Expect(record.Status).Should(Equal(model.RevisionStatusTerminated))
Expect(record.Finished).Should(Equal("true"))
Expect(record.Steps[1].Phase).Should(Equal(common.WorkflowStepPhaseStopped))
})
})
var yamlStr = `apiVersion: core.oam.dev/v1beta1

View File

@@ -87,3 +87,6 @@ var ErrInvalidWebhookPayloadType = NewBcode(400, 10022, "Invalid webhook payload
// ErrInvalidWebhookPayloadBody means the webhook payload body is invalid
var ErrInvalidWebhookPayloadBody = NewBcode(400, 10023, "Invalid webhook payload body")
// ErrApplicationTriggerNotExist means application trigger is not exist
var ErrApplicationTriggerNotExist = NewBcode(404, 10024, "application trigger is not exist")

View File

@@ -133,6 +133,16 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
Returns(400, "", bcode.Bcode{}).
Writes(apis.ApplicationTriggerBase{}))
ws.Route(ws.DELETE("/{name}/triggers/{token}").To(c.deleteApplicationTrigger).
Doc("delete one application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application ").DataType("string")).
Param(ws.PathParameter("token", "identifier of the trigger").DataType("string")).
Returns(200, "", apis.EmptyResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes([]*apis.EmptyResponse{}))
ws.Route(ws.GET("/{name}/triggers").To(c.listApplicationTriggers).
Doc("list application triggers").
Metadata(restfulspec.KeyOpenAPITags, tags).
@@ -494,6 +504,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
Returns(200, "", nil).
Returns(400, "", bcode.Bcode{}).
Writes(apis.ListWorkflowRecordsResponse{}))
return ws
}
@@ -584,6 +595,18 @@ func (c *applicationWebService) listApplicationTriggers(req *restful.Request, re
}
}
func (c *applicationWebService) deleteApplicationTrigger(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application)
if err := c.applicationUsecase.DeleteApplicationTrigger(req.Request.Context(), app, req.PathParameter("token")); err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(apis.EmptyResponse{}); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (c *applicationWebService) publishApplicationTemplate(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application)
base, err := c.applicationUsecase.PublishApplicationTemplate(req.Request.Context(), app)

View File

@@ -0,0 +1,54 @@
/*
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 webservice
import (
restfulspec "github.com/emicklei/go-restful-openapi/v2"
restful "github.com/emicklei/go-restful/v3"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
)
type payloadTypesWebservice struct {
}
func (c *payloadTypesWebservice) GetWebService() *restful.WebService {
ws := new(restful.WebService)
ws.Path(versionPrefix+"/payload_types").
Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML).
Doc("api for payload types manage")
tags := []string{"payload_types"}
ws.Route(ws.GET("/").To(c.ListPayloadTypes).
Doc("list application trigger payload types").
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(200, "", nil).
Returns(400, "", bcode.Bcode{}).
Writes([]string{}))
return ws
}
func (c *payloadTypesWebservice) ListPayloadTypes(req *restful.Request, res *restful.Response) {
if err := res.WriteEntity(usecase.WebhookHandlers); err != nil {
bcode.ReturnError(req, res, err)
return
}
}

View File

@@ -0,0 +1,116 @@
/*
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 webservice
import (
restfulspec "github.com/emicklei/go-restful-openapi/v2"
"github.com/emicklei/go-restful/v3"
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
)
type systemInfoWebService struct {
useCase usecase.SystemInfoUsecase
}
// NewSystemInfoWebService return systemInfo webservice
func NewSystemInfoWebService(systemInfoUseCase usecase.SystemInfoUsecase) WebService {
return &systemInfoWebService{useCase: systemInfoUseCase}
}
// GetWebService return systemInfo webservice
func (u systemInfoWebService) GetWebService() *restful.WebService {
ws := new(restful.WebService)
ws.Path(versionPrefix+"/system_info").Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML).
Doc("api for systemInfo management")
tags := []string{"systemInfo"}
// Get
ws.Route(ws.GET("/").To(u.getSystemInfo).
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(200, "", apis.SystemInfoResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.SystemInfoResponse{}))
// Delete
ws.Route(ws.DELETE("/").To(u.deleteSystemInfo).
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(200, "", apis.SystemInfoResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.SystemInfoResponse{}))
// Post
ws.Route(ws.PUT("/").To(u.updateSystemInfo).
Metadata(restfulspec.KeyOpenAPITags, tags).
Reads(apis.SystemInfoRequest{}).
Returns(200, "", apis.SystemInfoResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.SystemInfoResponse{}))
return ws
}
func (u systemInfoWebService) getSystemInfo(req *restful.Request, res *restful.Response) {
info, err := u.useCase.GetSystemInfo(req.Request.Context())
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(info); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (u systemInfoWebService) updateSystemInfo(req *restful.Request, res *restful.Response) {
var systemInfoReq apis.SystemInfoRequest
var args []byte
_, err := req.Request.Body.Read(args)
if err == nil {
err := req.ReadEntity(&systemInfoReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err = validate.Struct(&systemInfoReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
info, err := u.useCase.UpdateSystemInfo(req.Request.Context(), systemInfoReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(info); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (u systemInfoWebService) deleteSystemInfo(req *restful.Request, res *restful.Response) {
err := u.useCase.DeleteSystemInfo(req.Request.Context())
if err != nil {
bcode.ReturnError(req, res, err)
return
}
}

View File

@@ -20,6 +20,8 @@ import (
"regexp"
"github.com/go-playground/validator/v10"
"github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase"
)
var validate = validator.New()
@@ -38,6 +40,20 @@ func init() {
if err := validate.RegisterValidation("checkalias", ValidateAlias); err != nil {
panic(err)
}
if err := validate.RegisterValidation("checkpayloadtype", ValidatePayloadType); err != nil {
panic(err)
}
}
// ValidatePayloadType check PayloadType
func ValidatePayloadType(fl validator.FieldLevel) bool {
value := fl.Field().String()
for _, v := range usecase.WebhookHandlers {
if v == value {
return true
}
}
return false
}
// ValidateName custom check name field

View File

@@ -51,7 +51,7 @@ func (c *webhookWebService) GetWebService() *restful.WebService {
Doc("handle application webhook request").
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.PathParameter("name", "identifier of the application ").DataType("string")).
Reads(apis.HandleApplicationWebhookRequest{}).
Reads(apis.HandleApplicationTriggerWebhookRequest{}).
Returns(200, "", apis.ApplicationDeployResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.ApplicationDeployResponse{}))

View File

@@ -71,6 +71,7 @@ func Init(ds datastore.DataStore, addonCacheTime time.Duration) {
envBindingUsecase := usecase.NewEnvBindingUsecase(ds, workflowUsecase, definitionUsecase, envUsecase)
applicationUsecase := usecase.NewApplicationUsecase(ds, workflowUsecase, envBindingUsecase, envUsecase, targetUsecase, definitionUsecase, projectUsecase)
webhookUsecase := usecase.NewWebhookUsecase(ds, applicationUsecase)
systemInfoUsecase := usecase.NewSystemInfoUsecase(ds)
// init for default values
@@ -89,7 +90,10 @@ func Init(ds datastore.DataStore, addonCacheTime time.Duration) {
RegisterWebService(NewClusterWebService(clusterUsecase))
RegisterWebService(NewOAMApplication(oamApplicationUsecase))
RegisterWebService(&policyDefinitionWebservice{})
RegisterWebService(&payloadTypesWebservice{})
RegisterWebService(NewTargetWebService(targetUsecase, applicationUsecase))
RegisterWebService(NewVelaQLWebService(velaQLUsecase))
RegisterWebService(NewWebhookWebService(webhookUsecase, applicationUsecase))
RegisterWebService(NewSystemInfoWebService(systemInfoUsecase))
}

View File

@@ -45,6 +45,8 @@ import (
"github.com/oam-dev/kubevela/pkg/cue/model"
"github.com/oam-dev/kubevela/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/cue/process"
monitorContext "github.com/oam-dev/kubevela/pkg/monitor/context"
"github.com/oam-dev/kubevela/pkg/monitor/metrics"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/workflow/step"
@@ -81,6 +83,7 @@ type Workload struct {
Ctx process.Context
Patch *value.Value
engine definition.AbstractEngine
SkipApplyWorkload bool
}
// EvalContext eval workload template and set result to context
@@ -90,12 +93,17 @@ func (wl *Workload) EvalContext(ctx process.Context) error {
// EvalStatus eval workload status
func (wl *Workload) EvalStatus(ctx process.Context, cli client.Client, ns string) (string, error) {
// if the standard workload is managed by trait always return empty message
if wl.SkipApplyWorkload {
return "", nil
}
return wl.engine.Status(ctx, cli, ns, wl.FullTemplate.CustomStatus, wl.Params)
}
// EvalHealth eval workload health check
func (wl *Workload) EvalHealth(ctx process.Context, client client.Client, namespace string) (bool, error) {
if wl.FullTemplate.Health == "" {
// if health of template is not set or standard workload is managed by trait always return true
if wl.FullTemplate.Health == "" || wl.SkipApplyWorkload {
return true, nil
}
return wl.engine.HealthCheck(ctx, client, namespace, wl.FullTemplate.Health)
@@ -176,7 +184,14 @@ type Handler interface {
}
// PrepareWorkflowAndPolicy generates workflow steps and policies from an appFile
func (af *Appfile) PrepareWorkflowAndPolicy() ([]*unstructured.Unstructured, error) {
func (af *Appfile) PrepareWorkflowAndPolicy(ctx context.Context) ([]*unstructured.Unstructured, error) {
if ctx, ok := ctx.(monitorContext.Context); ok {
subCtx := ctx.Fork("prepare-workflow-and-policy", monitorContext.DurationMetric(func(v float64) {
metrics.PrepareWorkflowAndPolicyDurationHistogram.WithLabelValues("application").Observe(v)
}))
defer subCtx.Commit("finish prepare workflow and policy")
}
var externalPolicies []*unstructured.Unstructured
var err error
@@ -704,7 +719,14 @@ func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructu
}
if spec.ProviderReference != nil && !reflect.DeepEqual(configuration.Spec.ProviderReference, spec.ProviderReference) {
configuration.Spec.ProviderReference = spec.ProviderReference
} else if wl.FullTemplate != nil && wl.FullTemplate.ComponentDefinition != nil &&
wl.FullTemplate.ComponentDefinition.Spec.Schematic != nil &&
wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform != nil &&
wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.ProviderReference != nil {
// Check whether the provider reference is set in ComponentDefinition
configuration.Spec.ProviderReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.ProviderReference
}
if spec.Region != "" && configuration.Spec.Region != spec.Region {
configuration.Spec.Region = spec.Region
}

View File

@@ -460,7 +460,7 @@ spec:
}
_, err := testAppfile.GenerateComponentManifests()
Expect(err).Should(BeNil())
gotPolicies, err := testAppfile.PrepareWorkflowAndPolicy()
gotPolicies, err := testAppfile.PrepareWorkflowAndPolicy(context.Background())
Expect(err).Should(BeNil())
Expect(len(gotPolicies)).ShouldNot(Equal(0))
@@ -944,7 +944,6 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
},
"workload's params is bad": {
args: args{
params: badParam,
hcl: "abc",
@@ -952,8 +951,7 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
want: want{err: errors.Wrap(badParamMarshalError, errFailToConvertTerraformComponentProperties)},
},
"terraform workload has a provider reference": {
"terraform workload has a provider reference, but parameters are bad": {
args: args{
params: badParam,
hcl: "abc",
@@ -961,6 +959,14 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
},
want: want{err: errors.Wrap(badParamMarshalError, errFailToConvertTerraformComponentProperties)},
},
"terraform workload has a provider reference": {
args: args{
params: variable,
hcl: "variable \"name\" {\n description = \"Name to be used on all resources as prefix. Default to 'TF-Module-EIP'.\"\n default = \"TF-Module-EIP\"\n type = string\n }",
providerRef: &terraformtypes.Reference{Name: "aws", Namespace: "default"},
},
want: want{err: nil},
},
}
for tcName, tc := range testcases {
@@ -1021,7 +1027,16 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
configSpec.WriteConnectionSecretToReference = tc.args.writeConnectionSecretToRef
}
if tc.args.providerRef != nil {
template.Terraform.ProviderReference = tc.args.providerRef
tf := &common.Terraform{}
tf.ProviderReference = tc.args.providerRef
template.ComponentDefinition = &v1beta1.ComponentDefinition{
Spec: v1beta1.ComponentDefinitionSpec{
Schematic: &common.Schematic{
Terraform: tf,
},
},
}
configSpec.ProviderReference = tc.args.providerRef
}
wl := &Workload{

View File

@@ -32,6 +32,8 @@ import (
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/cue/definition"
"github.com/oam-dev/kubevela/pkg/cue/packages"
monitorContext "github.com/oam-dev/kubevela/pkg/monitor/context"
"github.com/oam-dev/kubevela/pkg/monitor/metrics"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util"
@@ -75,6 +77,12 @@ func NewDryRunApplicationParser(cli client.Client, dm discoverymapper.DiscoveryM
// GenerateAppFile converts an application to an Appfile
func (p *Parser) GenerateAppFile(ctx context.Context, app *v1beta1.Application) (*Appfile, error) {
if ctx, ok := ctx.(monitorContext.Context); ok {
subCtx := ctx.Fork("generate-app-file", monitorContext.DurationMetric(func(v float64) {
metrics.ParseAppFileDurationHistogram.WithLabelValues("application").Observe(v)
}))
defer subCtx.Commit("finish generate appFile")
}
ns := app.Namespace
appName := app.Name

View File

@@ -23,7 +23,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
v1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
@@ -71,7 +71,7 @@ var _ = BeforeSuite(func(done Done) {
scheme = runtime.NewScheme()
Expect(coreoam.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(clientgoscheme.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(v1beta1.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(v1.AddToScheme(scheme)).NotTo(HaveOccurred())
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).ToNot(HaveOccurred())
Expect(k8sClient).ToNot(BeNil())

View File

@@ -35,7 +35,7 @@ func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error {
}
pCtx, err := newValidationProcessContext(wl, a.Name, a.AppRevisionName, a.Namespace)
if err != nil {
return errors.WithMessage(err, "cannot create validationg process context")
return errors.WithMessagef(err, "cannot create the validation process context of app=%s in namespace=%s", a.Name, a.Namespace)
}
for _, tr := range wl.Traits {
if tr.CapabilityCategory != types.CUECategory {

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